redis過期key監聽事件
- 2021 年 3 月 10 日
- 筆記
redis常用語快取操作,但是redis功能不僅僅於此。今天我們來看看redis的key失效事件
redis安裝
- 為了方便安裝。我們直接使用docker安裝redis。這裡不多贅述docker了。直接貼出程式碼自己搞成腳本執行就可以了
docker拉取
docker pull redis:3.2
啟動
docker run -p 6379:6379 -v /opt/soft/docker/redis/redis.conf:/etc/redis/redis.conf -v /opt/soft/docker/redis/data:/data --name=myredis --restart=always -d redis:3.2 redis-server /etc/redis/redis.conf --requirepass "password" --appendonly yes
-
為了安全我們還是設置下密碼,將上述腳本password修改為自己的密碼即可
-
上面的/opt/soft/docker/redis/data這個我們只需要創建空文件夾就行了,這個我們是為了將redis日誌映射出來方便定位問題。
-
redis.conf文件去官網上下載就行了。docker安裝的redis默認沒有配置文件。或者直接複製我這裡的。
# Redis配置文件樣例
# Note on units: when memory size is needed, it is possible to specifiy
# it in the usual form of 1k 5GB 4M and so forth:
#
# 1k => 1000 bytes
# 1kb => 1024 bytes
# 1m => 1000000 bytes
# 1mb => 1024*1024 bytes
# 1g => 1000000000 bytes
# 1gb => 1024*1024*1024 bytes
#
# units are case insensitive so 1GB 1Gb 1gB are all the same.
# Redis默認不是以守護進程的方式運行,可以通過該配置項修改,使用yes啟用守護進程
# 啟用守護進程後,Redis會把pid寫到一個pidfile中,在/var/run/redis.pid
daemonize no
# 當Redis以守護進程方式運行時,Redis默認會把pid寫入/var/run/redis.pid文件,可以通過pidfile指定
pidfile /var/run/redis.pid
# 指定Redis監聽埠,默認埠為6379
# 如果指定0埠,表示Redis不監聽TCP連接
port 6379
# 綁定的主機地址
# 你可以綁定單一介面,如果沒有綁定,所有介面都會監聽到來的連接
# bind 127.0.0.1
# Specify the path for the unix socket that will be used to listen for
# incoming connections. There is no default, so Redis will not listen
# on a unix socket when not specified.
#
# unixsocket /tmp/redis.sock
# unixsocketperm 755
# 當客戶端閑置多長時間後關閉連接,如果指定為0,表示關閉該功能
timeout 0
# 指定日誌記錄級別,Redis總共支援四個級別:debug、verbose、notice、warning,默認為verbose
# debug (很多資訊, 對開發/測試比較有用)
# verbose (many rarely useful info, but not a mess like the debug level)
# notice (moderately verbose, what you want in production probably)
# warning (only very important / critical messages are logged)
loglevel verbose
# 日誌記錄方式,默認為標準輸出,如果配置為redis為守護進程方式運行,而這裡又配置為標準輸出,則日誌將會發送給/dev/null
logfile stdout
# To enable logging to the system logger, just set 'syslog-enabled' to yes,
# and optionally update the other syslog parameters to suit your needs.
# syslog-enabled no
# Specify the syslog identity.
# syslog-ident redis
# Specify the syslog facility. Must be USER or between LOCAL0-LOCAL7.
# syslog-facility local0
# 設置資料庫的數量,默認資料庫為0,可以使用select <dbid>命令在連接上指定資料庫id
# dbid是從0到『databases』-1的數目
databases 16
################################ SNAPSHOTTING #################################
# 指定在多長時間內,有多少次更新操作,就將數據同步到數據文件,可以多個條件配合
# Save the DB on disk:
#
# save <seconds> <changes>
#
# Will save the DB if both the given number of seconds and the given
# number of write operations against the DB occurred.
#
# 滿足以下條件將會同步數據:
# 900秒(15分鐘)內有1個更改
# 300秒(5分鐘)內有10個更改
# 60秒內有10000個更改
# Note: 可以把所有「save」行注釋掉,這樣就取消同步操作了
save 900 1
save 300 10
save 60 10000
# 指定存儲至本地資料庫時是否壓縮數據,默認為yes,Redis採用LZF壓縮,如果為了節省CPU時間,可以關閉該選項,但會導致資料庫文件變的巨大
rdbcompression yes
# 指定本地資料庫文件名,默認值為dump.rdb
dbfilename dump.rdb
# 工作目錄.
# 指定本地資料庫存放目錄,文件名由上一個dbfilename配置項指定
#
# Also the Append Only File will be created inside this directory.
#
# 注意,這裡只能指定一個目錄,不能指定文件名
dir ./
notify-keyspace-events Ex
################################# REPLICATION #################################
redis 配置
- 這裡的配置我在上面已經配置了。在官網下載的是默認的配置。上面我加了一個配置
notify-keyspace-events Ex
。關於Ex下表中有解釋
屬性 | 說明 |
---|---|
K | 鍵空間通知,所有通知keyspace@ 為前綴,追對key |
E | 鍵事件通知,所有通知已keyspace@為前綴,追對event |
g | DEL、EXPIRE、RENAME等類型無關的通用命令通知 |
$ | 字元串命令通知 |
l | 列表命令通知 |
s | 集合命令通知 |
h | 哈希命令通知 |
z | zset命令通知 |
x | 過期事件通知,每當key過期就會觸發 |
e | 驅逐事件,每當有鍵因為maxmemory策略被清楚是觸發 |
A | g$lshzxe總稱 |
命令監聽
- 完成上述配置後,我們打開redis客戶端
docker exec -it myredis redis-cli
- myredis是上面安裝redis容器的別名。這個讀者可以自己設置
- 因為設置了密碼,連接後我們需要進行密碼驗證
auth password
- 然後註冊監聽器
PSUBSCRIBE __keyevent@*__:expired
- 其中expired就是我們註冊類型 , @ 後面的* 表示DB。這裡我們監聽所有資料庫的key過期事件。
問題
- 比如我們想監聽DB0的key刪除事件。我們可以這麼註冊
PSUBSCRIBE __keyevent@0__:del
- 127.0.0.1:6379後面沒有數字說明使用的是默認的db0。
- 切換到DB1中查看hello沒有查到。且6379後面有了資料庫索引值。這個時候在DB1新增hello並進行刪除。看看另外一個監聽DB0的監聽器會不會有響應
- 很明顯,我們沒有任何的通知。現在我們在DB0 中進行刪除hello。看看監聽器的效果
- 這個時候在DB0 中執行刪除也沒有監控到資訊。這裡不知道為什麼。還望指點
程式監聽
- springboot程式添加依賴
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
@Configuration
public class RedisConfig {
@Bean
public RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory redisConnectionFactory) {
RedisMessageListenerContainer redisMessageListenerContainer = new RedisMessageListenerContainer();
redisMessageListenerContainer.setConnectionFactory(redisConnectionFactory);
return redisMessageListenerContainer;
}
}
- 這裡只是為了演示過期事件的監聽。所以這裡的redisConfig沒有加入太多的配置。
spring:
redis:
host: 39.102.60.114
port: 6379
database: 0
password: password
timeout: 1000s
具體監聽類
@Slf4j
@Component
public class RedisKeyExpireListener extends KeyExpirationEventMessageListener {
public RedisKeyExpireListener(RedisMessageListenerContainer listenerContainer) {
super(listenerContainer);
}
@Override
public void onMessage(Message message, byte[] pattern) {
log.info("接受到消息:{},{}",message,new String(pattern));
}
}
效果
總結
- key過期事件的監聽實際使用的不是很多。因為redis大部分都是快取作用。快取本來就會可有可無的。所以監聽意義不大。但是也可以在不少場景下使用。
- 訂單30分鐘未付款自動取消場景
- 系統定時提醒功能