redis过期监听性能_基于Redis的延迟处理
延遲處理是一個非常常用的一個功能;
例如, 下單成功后,在30分鐘內(nèi)沒有支付,自動取消訂單;
延遲隊列便是延遲處理中最常見的實現(xiàn)方式;
先一起看下JDK中延遲隊列是如何實現(xiàn)的.
JUC的DelayQueue
在JDK中, 提供了一套延遲隊列的實現(xiàn), 是JUC包中DelayQueue類.
在使用時只需要讓處理的元素對象實現(xiàn)Delayed接口, 就可以根據(jù)延遲時間實現(xiàn)延遲處理了.
DelayQueue隊列內(nèi)部是用優(yōu)先隊列實現(xiàn)的, 優(yōu)先隊列的實現(xiàn)原理可以參考小頂堆.
public class DelayQueue<E extends Delayed> extends AbstractQueue<E>implements BlockingQueue<E> {private final transient ReentrantLock lock = new ReentrantLock();private final PriorityQueue<E> q = new PriorityQueue<E>(); }元素對象需要實現(xiàn)Delayed接口的兩個方法
(1) compareTo()
元素自定義方法實現(xiàn), 根據(jù)延時時間, 確定元素在隊列中的位置; 元素剩余延時時間越小排列越靠前, 反之越靠后;
(2) getDelay()
元素自定義方法實現(xiàn), 判斷元素剩余延時時間;
public interface Delayed extends Comparable<Delayed> {long getDelay(TimeUnit unit); }彈出元素時, 會根據(jù)元素對象的剩余延時方法getDelay(), 判斷元素是否應(yīng)該被彈出; 后續(xù)邏輯可以根據(jù)業(yè)務(wù)需要繼續(xù)輪詢或休眠等待一段時間.
public E poll() { E first = q.peek();if (first == null || first.getDelay(NANOSECONDS) > 0)return null;elsereturn q.poll(); }雖然DelayQueue不能滿足分布式要求, 但它卻提供了一個很好的延遲處理框架, 可以根據(jù)不同的底層存儲介質(zhì)替換PriorityQueue實現(xiàn).
例如, Redis中的Zset.
Redis Zset
在上述DelayQueue框架的基礎(chǔ)上, 使用zset代替PriorityQueue存儲, 并用延遲時間作為zset的score項, 很容易就能實現(xiàn)一個分布式的高性能延遲隊列.
Redis過期事件監(jiān)聽
利用Redis的事件監(jiān)聽機制, 還有另外一種方式實現(xiàn)延遲處理.
Redis可以根據(jù)需要, 修改redis.conf配置, 實現(xiàn)對一些事件的監(jiān)聽, 其中就包括key過期事件.
redis.conf 配置
notify-keyspace-events Ex這個事件監(jiān)聽是通過pubsub機制實現(xiàn)的, 所以業(yè)務(wù)代碼中實現(xiàn)對事件的訂閱, 就可以知道哪個key過期了.
PUBSUB 主題:
<db>是指redis的database
__keyevent@<db>__:expired有了上述事件監(jiān)聽基礎(chǔ), 將延期事件對應(yīng)key存入Redis, 并根據(jù)延遲時間設(shè)置key過期時間, 當(dāng)key過期時, 便能觸發(fā)監(jiān)聽事件, 完成延遲處理邏輯.
當(dāng)然, 除了上述方式之外, 還可以使用定時任務(wù)輪詢, 死信隊列等等方式實現(xiàn)延遲處理
總結(jié)
以上是生活随笔為你收集整理的redis过期监听性能_基于Redis的延迟处理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 舌头下面疼是怎么回事
- 下一篇: sql if 和insert_拼多多面试