剛到新公司一個月左右,有個新需求,想做定時任務,比如在用戶注冊時間的3天后推送用戶一條消息。
從剛開始腦子里面閃現的數據庫輪詢,立馬否定掉(浪費資源),再到linux系統的定時任務,但是當用戶量過大時,肯定不行。
最后想着redis如果key過期了,能不能監聽觸發一個事件,這樣便可以不用時刻的查詢是否到了發送消息的時間,從而節省資源。
最終找到了 redis的key過期事件。通過監聽redis的過期時間,在過期時觸發一個事件,從而通過這個事件做其他事情。
操作步驟(liunx系統):
1.找到redis.conf配置文件,可以通過命令 find / | grep redis.conf
2.修改配置文件,找到 notify-keyspace-events,默認是被注釋的,改為 notify-keyspace-events Ex
# K 鍵空間通知,以__keyspace@<db>__為前綴 # E 鍵事件通知,以__keysevent@<db>__為前綴 # g del , expipre , rename 等類型無關的通用命令的通知, ... # $ String命令 # l List命令 # s Set命令 # h Hash命令 # z 有序集合命令 # x 過期事件(每次key過期時生成) # e 驅逐事件(當key在內存滿了被清除時生成) # A g$lshzxe的別名,因此”AKE”意味着所有的事件
3.重啟redis; 輸入命令:service redis-server restart
4.編寫python代碼:
redis_fabu.py
import redis import time r = redis.Redis(host='127.0.0.1', port=6379, db=0)
# r.publish('fm87.7', 'send msg') #可以發布固定的頻道
r.setex(name='test-name',value='val',time=1)
redis_dingyue.py
import redis r = redis.Redis(host='127.0.0.1', port=6379, db=0)
# sub.subscribe('fm87.7') #可以訂閱固定的頻道
sub_expire = r.pubsub()
# 事件通過 Redis 的訂閱與發布功能(pub/sub)來進行分發,故需要訂閱 __keyevent@0__:expired,其中0表示dbindex
sub_expire.subscribe('__keyevent@0__:expired') while True: ex_pire=sub_expire.parse_response() print(ex_pire[0],ex_pire[1],ex_pire[2])
輸出結果為:
b'subscribe' b'__keyevent@0__:expired' 1 b'message' b'__keyevent@0__:expired' b'test-name'
Notice:
1.redis的key過期事件在獲返回結果時是 key的值,所以在做相關任務時,可以把key名寫成需要執行的函數名等等。
2.redis的key過期事件是通過發布訂閱機制,如果在key過期發布觸發事件時,沒有訂閱服務的話,此過期事件會被舍棄掉,也就是發布過期事件,但是無法判斷是否被訂閱到,並且不會保存此次過期事件。所以要時刻確保 訂閱機制完好。
3. sub_expire.subscribe('__keyevent@0__:expired') 中 __keyevent@0__:expired 的 0 表示數據庫index,表示只觸發本數據庫的過期事件。
4.由於redis放在內存中,所以做好備份到硬盤的工作,盡量減少數據損失。
相關連接:
https://www.jianshu.com/p/eb27967739cd
https://www.jianshu.com/p/eb27967739cd
http://www.cnblogs.com/wujf/p/8080109.html
https://www.cnblogs.com/chen-lhx/p/6626371.html
https://blog.csdn.net/qq744746842/article/details/70195945