Redis和DelayQueue設計具有過期時間的快取

Evankaka發表於2017-02-27


1、場景:

有一款APP,使用者登陸後。會將使用者的使用者號,手機號、以及裝置號等上報給後臺的清洗程式(這裡裝置號是唯一的)。後臺因為需要根據這三個做一定的運算。所以希望
對於每一個訪客-使用者關係進行快取,並只快取10分鐘,並且快取使用redis。注意,是每一條記錄都只快取10分鐘。而不是一批記錄!

2、解決方案
1、在redis裡有個函式,hset(String key,String field ,String value),也有對應的hexpire(String key,int second),但是這裡如果以裝置號為key的話,
field和value要怎麼設定??因為快取進去後,因為我們取的時候是不知道裝置號的,只能說一條記錄10分鐘到了,就應該從redis取出來。並刪除redis的記錄。
這裡筆者還注意到有另一個函式,刪除函式為hdel(String key,String ..fields).如果將裝置號放到hset的field 欄位,key為一個固定的字串。但是還是那一個問題
怎麼知道有一個裝置號已快取10分鐘了?反覆思考,想到Java的一個類,叫DelayQueue。就是它。

DelayQueue是一個支援延時獲取元素的無界阻塞佇列。佇列使用PriorityQueue來實現。佇列中的元素必須實現Delayed介面,在建立元素時可以指定多久才能從佇列中獲取當前元素。只有在延遲期滿時才能從佇列中提取元素。我們可以將DelayQueue運用在以下應用場景:
其主要有以下兩種使用場景:
快取系統的設計:可以用DelayQueue儲存快取元素的有效期,使用一個執行緒迴圈查詢DelayQueue,一旦能從DelayQueue中獲取元素時,表示快取有效期到了。
定時任務排程。使用DelayQueue儲存當天將會執行的任務和執行時間,一旦從DelayQueue中獲取到任務就開始執行,從比如TimerQueue就是使用DelayQueue實現的。

注:
hset
描述:將雜湊表key中的域field的值設為value。如果key不存在,一個新的雜湊表被建立並進行HSET操作。如果域field已經存在於雜湊表中,舊值將被覆蓋。
引數:key field value
返回值:如果field是雜湊表中的一個新建域,並且值設定成功,返回1。如果雜湊表中域field已經存在且舊值已被新值覆蓋,返回0。
hdel 
描述:刪除指定的field
引數:key field:


3、編碼設計

    上面的方案還要注意一點,進行快取操作和刪除快取操作應該要在不同的執行緒。

這是strom的版本:

(1)延遲佇列設計


(2)初始化函式



這裡prepare在整個strom工程起來之後,只會執行一次,而execute只要會資料會一直不斷執行。

然後是進行快取操作:



刪除訪客記錄的執行緒:


相關文章