基於Redis的延遲隊列

業務背景

7號10:00創建活動,7號0:00到7號10:00之間下單未支付的用戶push催付,7號10:00後用戶下單5分鐘內沒有支付,以PUSH的方式催付

方案

0-10點間數據可理解爲離線數據,可通過創建一個ad-hoc查詢任務,並吐出人羣到給發送服務。

下單後5分鐘後沒有支付以push催付,採用Redis的延遲列隊方案

如果爲下單半個小時後催付,建議採用DB輪詢方案。

https://blog.csdn.net/asd491310/article/details/90418292中列舉了延遲任務的解決方案,不論是RocketMQ、TimingWheel等方案,基本思路是有效減少掃描數據集。

集合S按時間排序,T1輪詢隊頭若干個元素,判斷是否符合條件,若符合條件,就取出所有符合條件的元素。

假設每5分鐘符合預期的元素有1000個以上,建議通過消息中間件發送給專門消息上發送的集羣處理

假設每5分鐘符合預期的元素在1000以內,建議採用Reactor線程池模式。

方案思考:

優點:實現簡單,輪詢消耗資源少

缺點:按延遲時間建立延遲隊列,建議按1、5、10分鐘做延遲隊列,不建義隨意創建延遲隊列,不好維護,一個隊列最大吞吐量爲單臺Redis的吞吐量。

數據結構

假設每5分鐘內的訂單數據爲10000以內,5秒輪詢一次

a. Sorted sets,timestamp爲score

1. 查找元素是否到達可發送時間:

    ZREMRANGEBYSCORE key min max

    時間複雜度: O( log(N)+ M),其中 N 是已排序集合中元素的數量,M 是由操作移除的元素數量,複雜度爲1004

    注意:這裏不使用ZCOUNT key min max  

    時間複雜度: O( log(N)),其中 N 是有序集合中元素的數量。複雜度爲4。當ZREMRANGEBYSCORE 沒有返回數據時時間複雜度均爲O( log(N)),同ZREMRANGEBYSCORE 可簡化應用代碼邏輯,查找、獲取數據、刪除數據代碼統一了。也可取一個元素存儲在本地做輪詢。減少輪詢對Redis的開銷

2. 刪除已移除購物車的元素

    ZREM key member [member ...]

    時間複雜度: O( M * log(N)),其中 N 是有序集合中元素的數量,M 是要移除的元素的數量,複雜度爲4*1

3. 新增元素

    ZADD key [NX|XX] [CH] [INCR] score member [score member ...]

    時間複雜度:添加每個項目的O(log(N)),其中N是排序集合中元素的數量,複雜度爲4

   延遲時間內數據量10000以內,Sorted sets爲筆者建議數據結構,數據量在往上建議,查找元素步驟與獲取數據步驟分離,減少對Redis的壓力。

b. List ,按插入順序存儲

假設秒級誤差可以忽略,那麼從5秒級的視角看,List也是一個有效有序的列表,且符合業務預期

1. 查找元素是否到達可發送時間:

 LINDEX key index

   時間複雜度: O(N)其中N是要到達索引處元素的遍歷元素的數量。

   LINDEX key 0 查詢列表第一個元素,複雜度爲1

2. 刪除已移除購物車元素

    LREM key count value,時間複雜度爲O(N),不建議使用。移除購物車的訂單建議使用string結構存儲,有效期爲10分鐘。

不支持

3. 新增元素

    lpush/rpush,複雜度爲1

4. 獲取元素

     lpop/rpop,複雜度爲1

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章