日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

如何用 Redis 实现延迟队列?

發布時間:2025/3/19 数据库 15 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何用 Redis 实现延迟队列? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

如何用 Redis 實現延遲隊列?

- 前言 -

我們都知道Redis是一種基于內存的單進程單線程數據庫(Redis6.0開始之后支持多線程啦! ),處理速度都非???。 那么為何Redis又能慢呢? 原來,這里說的慢是指Redis可以設置一些參數達到慢處理的結果。

那接下來開始講講我們的Redis在隊列中如何實現延時的情況:

在我們日常生活中,我們可以發現:

在淘寶、京東等購物平臺上下單,超過一定時間未付款,訂單會自動取消。

打車的時候,在規定時間沒有車主接單,平臺會取消你的單并提醒你暫時沒有車主接單。

點外賣的時候,如果商家在10分鐘還沒接單,就會自動取消訂單。

收快遞的時候,如果我們沒有點確認收貨,在一段時間后程序會自動完成訂單。

在平臺完成訂單后,如果我們沒有在規定時間評論商品,會自動默認買家不評論。

……

這時,我們可以想想為什么要這樣做?

因為這樣可以保證商品的庫存可以釋放給其他人購買,你可以不用一直等待打車卻得不到回復,你可以及時換一家店點到外賣。
- 設計與實現 -

那么這些情況都是如何實現的呢?

這時我們可以看看這個圖,來看看消息延遲是如何處理的:

當用戶發送一個消息請求給服務器后臺的時候,服務器會檢測這條消息是否需要進行延時處理,如果需要就放入到延時隊列中,由延時任務檢測器進行檢測和處理,對于不需要進行延時處理的任務,服務器會立馬對消息進行處理,并把處理后的結果返會給用戶。
對于在延時任務檢測器內部的話,有查詢延遲任務和執行延時任務兩個職能,任務檢測器會先去延時任務隊列進行隊列中信息讀取,判斷當前隊列中哪些任務已經時間到期并將已經到期的任務輸出執行(設置一個定時任務)。

這時,我們可以想一想在Redis的數據結構中有哪些能進行時間設置標志的命令?

是不是想到的 zset 這個命令,具有去重有序(分數排序)的功能。沒錯,你想對了呀!

我們可以使用 zset(sortedset)這個命令,用設置好的時間戳作為score進行排序,使用 zadd score1 value1 …命令就可以一直往內存中生產消息。再利用 zrangebysocre 查詢符合條件的所有待處理的任務,通過循環執行隊列任務即可。也可以通過 zrangebyscore key min max withscores limit 0 1 查詢最早的一條任務,來進行消費。

總的來說,你可以通過以下兩種方式來實現:

(1)使用zrangebyscore來查詢當前延時隊列中所有任務,找出所有需要進行處理的延時任務,在依次進行操作。

(2)查找當前最早的一條任務,通過score值來判斷任務執行的時候是否大于了當前系統的時候,比如說:最早的任務執行時間在3點,系統時間在2點58分),表示這個應該需要立馬被執行啦,時間快到了(沖沖沖,他來了他來了,他帶著死神的步伐來了)。
- 優勢 -

我們可以想一想Redis來實現延時隊列有何優勢呢?

其實,Redis用來進行實現延時隊列是具有這些優勢的:

Redis zset支持高性能的 score 排序。

Redis是在內存上進行操作的,速度非常快。

Redis可以搭建集群,當消息很多時候,我們可以用集群來提高消息處理的速度,提高可用性。

Redis具有持久化機制,當出現故障的時候,可以通過AOF和RDB方式來對數據進行恢復,保證了數據的可靠性

這時候,會有小伙伴問了還有沒有其他實現延時隊列的方式呀!emmm…當然有的,只有想不到的沒有做不到。
一、用消息中間件實現延時隊列

(1)通過 RabbitMQ 來實現延時隊列

方法一:在MQ中我們可以對Queue設置 x-expires 過期時間或者對 Message設置超時時間x-message-ttl。

(這里要注意下:延時相同的消息我們要扔到同一個隊列中,對于每一個延時要建立一個與之對應的隊列—這是由于MQ的過期檢測是惰性檢測的。)

方法二:我們可以用RabbitMQ的插件rabbitmq-delayed-message-exchange插件來實現延時隊列。達到可投遞時間時并將其通過 x-delayed-type 類型標記的交換機類型投遞至目標隊列。

(2)RocketMQ實現延時隊列

rocketmq在發送延時消息時,是先把消息按照延遲時間段發送到指定的隊列中(把延時時間段相同的消息放到同一個隊列中,保證了消息處理的順序性,可以讓同一個隊列中消息延時時間是相同的,整個RocketMQ中延時消息時按照遞增順序排序,保證信息處理的先后順序性。)。之后,通過一個定時器來輪詢處理這些隊列里的信息,判斷是否到期。對于到期的消息會發送到相應的處理隊列中,進行處理。

注意 :目前RocketMQ只支持特定的延時時間段,1s,5s,10s,…2h,不能支持任意時間段的延時設置。有興趣的小伙伴可以去了解下它是相關知識呀~

- Kafka 實現延時隊列 -

Kafka基于時間輪自定義了一個用于實現延遲功能的定時器(SystemTimer),Kafka中的時間輪(TimingWheel)是一個存儲定時任務的環形隊列,可以進行相關的延時隊列設置。

- Netty 實現延時隊列 -

Netty也有基于時間輪算法來實現延時隊列。Netty在構建延時隊列主要用HashedWheelTimer,HashedWheelTimer底層數據結構是使用DelayedQueue,采用時間輪的算法來實現。

- DelayQueue 來實現延時隊列 -

Java中有自帶的DelayQueue數據類型,我們可以用這個來實現延時隊列。

DelayQueue是封裝了一個PriorityQueue(優先隊列),在向DelayQueue隊列中添加元素時,會給元素一個Delay(延遲時間)作為排序條件,隊列中最小的元素會優先放在隊首,對于隊列中的元素只有到了Delay時間才允許從隊列中取出。這種實現方式是數據保存在內存中,可能面臨數據丟失的情況,同時它是無法支持分布式系統的。

作 者:_BKing

來源:https://www.tuicool.com/articles/If6zau6

總結

以上是生活随笔為你收集整理的如何用 Redis 实现延迟队列?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。