1.過期設(shè)置
Redis 中設(shè)置過期時間主要通過以下四種方式:
- expire key seconds:設(shè)置 key 在 n 秒后過期;
- pexpire key milliseconds:設(shè)置 key 在 n 毫秒后過期;
- expireat key timestamp:設(shè)置 key 在某個時間戳(精確到秒)之后過期;
- pexpireat key millisecondsTimestamp:設(shè)置 key 在某個時間戳(精確到毫秒)之后過期;
下面分別來看以上這些命令的具體實現(xiàn)。
1)expire:N 秒后過期
127.0.0.1:6379> set key value
OK
127.0.0.1:6379> expire key 100
(integer) 1
127.0.0.1:6379> ttl key
(integer) 97
其中命令 ttl 的全稱是 Time To Live 表示此鍵值在 n 秒后過期。例如,上面的結(jié)果 97 表示 key 在 97s 后過期。
2)pexpire:N 毫秒后過期
127.0.0.1:6379> set key2 value2
OK
127.0.0.1:6379> pexpire key2 100000
(integer) 1
127.0.0.1:6379> pttl key2
(integer) 94524
其中 pexpire key2 100000 表示設(shè)置 key2 在 100000 毫秒(100秒)后過期。
3)expireat:過期時間戳精確到秒
127.0.0.1:6379> set key3 value3
OK
127.0.0.1:6379> expireat key3 1573472683
(integer) 1
127.0.0.1:6379> ttl key3
(integer) 67
其中 expireat key3 1573472683 表示 key3 在時間戳 1573472683 后過期(精確到秒),使用 ttl 查詢可以發(fā)現(xiàn)在 67s 后 key3 會過期。
小貼士:在 Redis 可以使用 time 命令查詢當(dāng)前時間的時間戳(精確到秒),示例如下:
127.0.0.1:6379> time
1) "1573472563"
2) "248426"
4)pexpireat:過期時間戳精確到毫秒
127.0.0.1:6379> set key4 value4
OK
127.0.0.1:6379> pexpireat key4 1573472683000
(integer) 1
127.0.0.1:6379> pttl key4
(integer) 3522
其中 pexpireat key4 1573472683000 表示 key4 在時間戳 1573472683000 后過期(精確到毫秒),使用 ttl 查詢可以發(fā)現(xiàn)在 3522ms 后 key4 會過期。
5)字符串中的過期操作
字符串中幾個直接操作過期時間的方法,如下列表:
- set key value ex seconds:設(shè)置鍵值對的同時指定過期時間(精確到秒);
- set key value ex milliseconds:設(shè)置鍵值對的同時指定過期時間(精確到毫秒);
- setex key seconds valule:設(shè)置鍵值對的同時指定過期時間(精確到秒)。
實現(xiàn)示例如下:
① set key value ex seconds
127.0.0.1:6379> set k v ex 100
OK
127.0.0.1:6379> ttl k
(integer) 97
② set key value ex milliseconds
127.0.0.1:6379> set k2 v2 px 100000
OK
127.0.0.1:6379> pttl k2
(integer) 92483
③ setex key seconds valule
127.0.0.1:6379> setex k3 100 v3
OK
127.0.0.1:6379> ttl k3
(integer) 91
2.移除過期時間
使用命令: persist key 可以移除鍵值的過期時間,如下代碼所示:
127.0.0.1:6379> ttl k3
(integer) 97
127.0.0.1:6379> persist k3
(integer) 1
127.0.0.1:6379> ttl k3
(integer) -1
可以看出第一次使用 ttl 查詢 k3 會在 97s 后過期,當(dāng)使用了 persist 命令之后,在查詢 k3 的存活時間發(fā)現(xiàn)結(jié)果是 -1,它表示 k3 永不過期。
3.Java實現(xiàn)過期操作
本文將使用 Jedis 框架來實現(xiàn)對 Redis 過期時間的操作,如下代碼所示:
public class TTLTest {
public static void main(String[] args) throws InterruptedException {
// 創(chuàng)建 Redis 連接
Jedis jedis = new Jedis("xxx.xxx.xxx.xxx", 6379);
// 設(shè)置 Redis 密碼(如果沒有密碼,此行可省略)
jedis.auth("xxx");
// 存儲鍵值對(默認(rèn)情況下永不過期)
jedis.set("k", "v");
// 查詢 TTL(過期時間)
Long ttl = jedis.ttl("k");
// 打印過期日志
System.out.println("過期時間:" + ttl);
// 設(shè)置 100s 后過期
jedis.expire("k", 100);
// 等待 1s 后執(zhí)行
Thread.sleep(1000);
// 打印過期日志
System.out.println("執(zhí)行 expire 后的 TTL=" + jedis.ttl("k"));
}
}
程序的執(zhí)行結(jié)果為:
過期時間:-1
執(zhí)行 expire 后的 TTL=99
可以看出使用 Jedis 來操作 Redis 的過期時間還是很方便的,可直接使用 jedis.ttl("k") 查詢鍵值的生存時間,使用 jedis.expire("k",seconds) 方法設(shè)置過期時間(精確到秒)。
小貼士:使用 Jedis 之前,先要把 Jedis 引入到程序中,如果使用的是 Maven 項目的,直接在 pom.xml 文件中添加以下引用:
!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
dependency>
groupId>redis.clients/groupId>
artifactId>jedis/artifactId>
version>version/version>
/dependency>
更多過期操作方法,如下列表:
- pexpire(String key, long milliseconds):設(shè)置 n 毫秒后過期;
- expireAt(String key, long unixTime):設(shè)置某個時間戳后過期(精確到秒);
- pexpireAt(String key, long millisecondsTimestamp):設(shè)置某個時間戳后過期(精確到毫秒);
- persist(String key):移除過期時間。
完整示例代碼如下:
public class TTLTest {
public static void main(String[] args) throws InterruptedException {
// 創(chuàng)建 Redis 連接
Jedis jedis = new Jedis("xxx.xxx.xxx.xxx", 6379);
// 設(shè)置 Redis 密碼(如果沒有密碼,此行可省略)
jedis.auth("xxx");
// 存儲鍵值對(默認(rèn)情況下永不過期)
jedis.set("k", "v");
// 查詢 TTL(過期時間)
Long ttl = jedis.ttl("k");
// 打印過期日志
System.out.println("過期時間:" + ttl);
// 設(shè)置 100s 后過期
jedis.expire("k", 100);
// 等待 1s 后執(zhí)行
Thread.sleep(1000);
// 打印過期日志
System.out.println("執(zhí)行 expire 后的 TTL=" + jedis.ttl("k"));
// 設(shè)置 n 毫秒后過期
jedis.pexpire("k", 100000);
// 設(shè)置某個時間戳后過期(精確到秒)
jedis.expireAt("k", 1573468990);
// 設(shè)置某個時間戳后過期(精確到毫秒)
jedis.pexpireAt("k", 1573468990000L);
// 移除過期時間
jedis.persist("k");
}
}
4.持久化中的過期鍵
上面我們講了過期鍵在 Redis 正常運行中一些使用案例,接下來,我們來看 Redis 在持久化的過程中是如何處理過期鍵的。
Redis 持久化文件有兩種格式:RDB(Redis Database)和 AOF(Append Only File),下面我們分別來看過期鍵在這兩種格式中的呈現(xiàn)狀態(tài)。
1)RDB中的過期鍵
RDB 文件分為兩個階段,RDB 文件生成階段和加載階段。
① RDB 文件生成
從內(nèi)存狀態(tài)持久化成 RDB(文件)的時候,會對 key 進行過期檢查,過期的鍵不會被保存到新的 RDB 文件中,因此 Redis 中的過期鍵不會對生成新 RDB 文件產(chǎn)生任何影響。
② RDB 文件加載
RDB 加載分為以下兩種情況:
- 如果 Redis 是主服務(wù)器運行模式的話,在載入 RDB 文件時,程序會對文件中保存的鍵進行檢查,過期鍵不會被載入到數(shù)據(jù)庫中。所以過期鍵不會對載入 RDB 文件的主服務(wù)器造成影響;
- 如果 Redis 是從服務(wù)器運行模式的話,在載入 RDB 文件時,不論鍵是否過期都會被載入到數(shù)據(jù)庫中。但由于主從服務(wù)器在進行數(shù)據(jù)同步時,從服務(wù)器的數(shù)據(jù)會被清空。所以一般來說,過期鍵對載入 RDB 文件的從服務(wù)器也不會造成影響。
RDB 文件加載的源碼可以在 rdb.c 文件的 rdbLoad() 函數(shù)中找到,源碼所示:
/* Check if the key already expired. This function is used when loading
* an RDB file from disk, either at startup, or when an RDB was
* received from the master. In the latter case, the master is
* responsible for key expiry. If we would expire keys here, the
* snapshot taken by the master may not be reflected on the slave.
*
* 如果服務(wù)器為主節(jié)點的話,
* 那么在鍵已經(jīng)過期的時候,不再將它們關(guān)聯(lián)到數(shù)據(jù)庫中去
*/
if (server.masterhost == NULL expiretime != -1 expiretime now) {
decrRefCount(key);
decrRefCount(val);
// 跳過
continue;
}
2)AOF中的過期鍵
① AOF 文件寫入
當(dāng) Redis 以 AOF 模式持久化時,如果數(shù)據(jù)庫某個過期鍵還沒被刪除,那么 AOF 文件會保留此過期鍵,當(dāng)此過期鍵被刪除后,Redis 會向 AOF 文件追加一條 DEL 命令來顯式地刪除該鍵值。
② AOF 重寫
執(zhí)行 AOF 重寫時,會對 Redis 中的鍵值對進行檢查已過期的鍵不會被保存到重寫后的 AOF 文件中,因此不會對 AOF 重寫造成任何影響。
5.主從庫的過期鍵
當(dāng) Redis 運行在主從模式下時,從庫不會進行過期掃描,從庫對過期的處理是被動的。也就是即時從庫中的 key 過期了,如果有客戶端訪問從庫時,依然可以得到 key 對應(yīng)的值,像未過期的鍵值對一樣返回。
從庫的過期鍵處理依靠主服務(wù)器控制,主庫在 key 到期時,會在 AOF 文件里增加一條 del 指令,同步到所有的從庫,從庫通過執(zhí)行這條 del 指令來刪除過期的 key。
6.小結(jié)
本文我們知道了 Redis 中的四種設(shè)置過期時間的方式:expire、pexpire、expireat、pexpireat,其中比較常用的是 expire 設(shè)置鍵值 n 秒后過期。
字符串中可以在添加鍵值的同時設(shè)置過期時間,并可以使用 persist 命令移除過期時間。同時我們也知道了過期鍵在 RDB 寫入和 AOF 重寫時都不會被記錄。
過期鍵在主從模式下,從庫對過期鍵的處理要完全依靠主庫,主庫刪除過期鍵之后會發(fā)送 del 命令給所有的從庫。
本文的知識點,如下圖所示:

7.引用鳴謝
https://www.jb51.net/article/174204.htm
https://www.jb51.net/article/174207.htm
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,謝謝大家對腳本之家的支持。
您可能感興趣的文章:- Redis使用Eval多個鍵值自增的操作實例
- Redis不使用 keys 命令獲取鍵值信息的方法