精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

如果有人再問你怎么實現分布式延時消息,這篇文章丟給他

開源 分布式
我們實現本地延時比較簡單,直接使用Java中現成的即可,那我們分布式消息隊列的實現有哪些難點呢?

 背景

開源版的RocketMQ只提供了18個層級的消息隊列延時,這個功能在開源版中顯得特別雞肋,但是在阿里云中的RocketMQ卻提供了支持40天之內任意秒級延時隊列,果然有些功能你只能充錢才能擁有。當然你或許想換一個開源的消息隊列,在開源社區中消息隊列延時消息很多都沒有被支持比如:RabbitMQ,Kafka等,都只能通過一些特殊方法才能完成延時的功能。為什么這么多都沒有實現這個功能呢?是因為技術難度比較復雜嗎?接下來我們分析一下如何才能實現一個延時消息。

[[285062]]

本地延時

在實現分布式消息隊列的延時消息之前,我們想想我們平時是如何在自己的應用程序上實現一些延時功能的?在Java中可以通過下面的方式來完成我們延時功能:

  • ScheduledThreadPoolExecutor:ScheduledThreadPoolExecutor繼承了ThreadPoolExecutor,我們提交任務的時候,會將任務首先提交到DelayedWorkQueue一個優先級隊列中,按照過期時間進行排序,這個優先級隊列也就是我們堆結構,每次提交任務排序的復雜度是O(logN)。然后取任務的時候就會從堆頂取出我們的任務,也就是我們延遲時間最小的任務。ScheduledThreadPoolExecutor有個好處是執行延時任務可以支持多線程并行執行,因為他繼承的是ThreadPoolExecutor。
  • Timer:Timer也是利用優先級隊列結構做的,但是其沒有繼承線程池,相對來說比較獨立,不支持多線程,只能使用單獨的一個線程。

分布式消息隊列延時

我們實現本地延時比較簡單,直接使用Java中現成的即可,那我們分布式消息隊列的實現有哪些難點呢?

有很多同學首先會想到我們實現分布式消息隊列的延時任務,可不可以直接使用本地的那一套,用ScheduledThreadPoolExecutor,Timer,當然這是可以的,前提是你的消息量很小,但是我們分布式消息隊列往往都是企業級別的中間件,數據量都是非常的大,那么我們純內存的方案肯定是行不通的。所以我們就有了下面這幾個方案來解決我們這個問題。

數據庫

數據庫一般來說是我們很容易想到的一個辦法,我們通常可以建立下面這樣一個表:

  1. CREATE TABLE `delay_message` ( 
  2.  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, 
  3.  `excute_time` bigint(16) DEFAULT NULL COMMENT '執行時間,ms級別'
  4.  `body` varchar(4096) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '消息體'
  5.  PRIMARY KEY (`id`), 
  6.  KEY `time_index` (`excute_time`) 
  7. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; 

這個表中我們使用excute_time代表我們真實的執行時間,并且對其建立索引,然后在我們的消息服務中,啟動一個定時任務,定時從數據庫中掃描已經可以執行的消息,然后開始執行,具體流程如下面所示:

 

如果有人再問你怎么實現分布式延時消息,這篇文章丟給他

 

使用數據庫的方法是一個比較原始的方法,在沒有延時消息這個概念之前,要做一個訂單多少分鐘過期的這種功能,通常使用這個方法去完成。而這個方法通常也比較局限于我們單個業務,如果想擴展為我們企業級的一個中間件的話是不行的,因為mysql由于BTree的特性,會隨著維護二級索引的開銷越來越大,導致寫入會越來越慢,所以這個方案通常不會被考慮。

RocksDB/LevelDB

我們之前介紹RocketMQ在開源版本中只實現了18個Level的延時消息,但是有很多公司基于RocketMQ做了自己的一套支持任意時間的延時消息,在美團內部封裝了RocketMQ使用LevelDB做了對延時消息的封裝,在滴滴開源的DDMQ中,使用了RocksDB對RocketMQ的延時消息部分進行了封裝。

其原理基本和Mysql類似,如下圖所示:

 

如果有人再問你怎么實現分布式延時消息,這篇文章丟給他

 

  • Step1: DDMQ發送消息的時候會有一個代理層,用于將消息做分發,因為其內部有多種消息隊列,kafka,rocketMQ等等,如果是延時消息會將消息發送到RockesDB的存儲。
  • Step2: 通過定時任務輪訓掃描將數據轉發投遞至RocketMQ集群。
  • Step3: 消費者進行消費。

為什么同樣是數據庫RocksDB會比Mysql更加合適呢?因為RocksDB的特性是LSM樹,其使用場景適用于大量寫入,和消息隊列的場景更加契合,所以這個也是滴滴和美團選擇其作為延時消息封裝的存儲介質。

3.2 時間輪+磁盤存儲

再說時間輪之前,讓我們再次回到我們的實現本地延時的時候使用的ScheduledThreadPoolExecutor還有Timer,他們都是使用的優先級隊列完成的,優先級隊列本質上也就是堆結構,堆結構的插入的時間復雜度是O(LogN),如果未來我們的內存可以做到無限,我們使用使用優先級隊列去做延時消息的存儲,但是隨著消息的增多,我們的插入消息的效率也會越來越低,那么怎么才能讓我們的插入消息的效率不隨著消息的增多而變低呢?答案就是時間輪。

什么是時間輪呢?其實我們可以簡單的將其看做是一個多維數組。在很多框架中都使用了時間輪來做一些定時的任務,用來替代我們的Timer,比如我之前講過的有關本地緩存Caffeine一篇文章,在Caffeine中是一個二層時間輪,也就是二維數組,其一維的數據表示較大的時間維度比如,秒,分,時,天等,其二維的數據表示該時間維度較小的時間維度,比如秒內的某個區間段。當定位到一個TimeWhile[i][j]之后,其數據結構其實是一個鏈表,記錄著我們的Node。在Caffeine利用時間輪記錄我們在某個時間過期的數據,然后去處理。

 

如果有人再問你怎么實現分布式延時消息,這篇文章丟給他

 

由于時間輪是一個數組的結構,那么其插入復雜度是O(1)。我們解決了效率之后,但是我們的內存依舊不是無限的,我們時間輪如何使用呢?答案當然就是磁盤,在去哪兒開源的QMQ中已經實現了時間輪+磁盤存儲,這里為了方便描述我將其轉化為RocketMQ中的結構來進行講解,實現圖如下:

 

如果有人再問你怎么實現分布式延時消息,這篇文章丟給他

 

  • Step 1: 生產者投遞延時消息到CommitLog,這個時候使用了偷換Topic的那招,來達到后面的效果。
  • Step 2: 后臺有一個Reput的任務定時拉取,延時Topic相關的Message。
  • Step 3: 判斷這個Message是否在當前時間輪范圍中,如果不在則來到Step4,如果在的話就直接將消息投遞進入時間輪。
  • Step 4: 找到當前消息所屬的scheduleLog,然后寫入進去,去哪兒默認劃分是一個小時為一段,這里可以根據業務自行調整。
  • Step 5:時間輪會定時預加載下個時間段的scheduleLog到內存。
  • Step 6: 到點的消息會還原topic再次投遞到CommitLog,如果投遞成功這里會記錄dispatchLog。記錄的原因是因為時間輪是內存的,你不知道已經執行到哪個位置了,如果執行到最后最后1s鐘的時候掛了,這段時間輪之前的所有數據又得重新加載,這里是用來過濾已經投遞過的消息。

時間輪+磁盤存儲我個人覺得比上面的RocksDB要更加正統一點,不依賴其他的中間件就可以完成,可用性自然也就更高,當然阿里云的RocketMQ具體怎么實現的這個兩種方案都有可能。

3.3 redis

在社區中也有很多公司使用的Redis做的延時消息,在Redis中有一個數據結構是Zest,也就是有序集合,他可以實現類似我們的優先級隊列的功能,同樣的他也是堆結構,所以插入算法復雜度依然是O(logN),但是由于Redis足夠快,所以這一塊可以忽略。(這塊沒有做對比的基準測試,只是猜測)。有同學會問,redis不是純內存的k,v嗎,同樣的應該也會受到內存限制啊,為什么還會選擇他呢?

其實在這個場景中,Redis是很容易水平擴展的當一個Redis內存不夠,這里可以使用兩個甚至更多,來滿足我們的需要,redis延時消息的原理圖(原圖出自:https://www.cnblogs.com/lylife/p/7881950.html)如下:

 

如果有人再問你怎么實現分布式延時消息,這篇文章丟給他

 

  • Delayed Messages Pool: Redis Hash結構,key為消息ID,value為具體的message,當然這里也可以用磁盤或者數據庫代替。這里主要存儲我們所有消息的內容。
  • Delayed Queue: ZSET數據結構,value為消息ID,score為執行時間,這里Delayed Queue可以水平擴展從而增加我們可以支持的數據量。
  • Worker Thread Pool: 其中有多個Worker,可以部署在多個機器上形成一個集群,集群中的所有Worker通過ZK進行協調,分配Delayed Queue。

我們怎么才能知道Delayed Queue中的消息到期了呢?這里有兩種方法:

  • 每個Worker定時掃描,ZSET的最小執行時間,如果到了就取出,這個方法在消息少的時候特別浪費資源,在消息量多的時候,由于輪訓不及時導致延時的時間不準確。
  • 因為第一個方法問題比較多,所以這里借鑒了Timer中的一些思想,通過wait-notify可以達到一個比較好的延時效果,并且資源也不會浪費,第一次的時候還是獲取ZSET中最小的時間,然后wait(執行時間-當前時間),這樣就不需要浪費資源到達時間時會自動響應,如果當前ZSET有新的消息進入,并且比我們等待的消息還要小,那么直接notify喚醒,重新獲取這個更小的消息,然后又wait,如此循環。

總結

本文介紹了三種方式實現分布式延時消息,希望能在你實現自己的延遲消息的時候提供一點思路。總的來說可能前兩種方法來說適用面更加廣一點,畢竟在RocketMQ這些大型的消息隊列中間件,還有一些其他的集成功能,比如順序消息,事務消息等,延時消息可能更加傾向于是分布式消息隊列中的一個功能,而不是作為一個獨立的組件存在。當然其中還有一些細節并沒有一一介紹,具體細節可以去參考QMQ和DDMQ的源碼。

責任編輯:武曉燕 來源: 今日頭條
相關推薦

2018-12-07 09:31:52

分布式鎖服務框架分布式系統

2022-09-26 10:09:08

MVCC控制并發

2018-08-07 16:01:32

synchronizevolatilefinal

2021-02-22 13:32:19

MySQLSQL索引

2022-11-08 09:33:36

訂單系統電商

2019-09-19 14:03:32

B樹節點數據結構

2020-04-20 13:11:21

HashMap底層存儲

2018-07-03 14:54:25

Java內存模型

2020-12-11 08:23:06

JavaMemory Mode內存模型

2020-04-28 09:15:58

HashMapJava數組

2021-03-08 12:47:42

MySQL查詢數據

2022-05-23 09:41:27

分庫分表數據庫算法

2021-03-08 10:25:37

MySQL數據庫索引

2021-05-31 09:42:48

MySQL隔離級別

2023-12-11 08:32:58

數據庫DruidDBA

2020-12-21 14:58:25

分布式性能系統

2018-10-12 09:42:00

分布式鎖 Java多線

2022-10-21 16:39:56

JDK優化

2017-11-02 15:04:15

2019-04-15 14:40:46

消息隊列Java編程
點贊
收藏

51CTO技術棧公眾號

九色精品美女在线| 欧美日韩国产丝袜美女| 亚洲一区二区三区视频| 国产精品7777| 国产在视频线精品视频www666| 91传媒视频在线播放| 色中文字幕在线观看| 日韩一级免费视频| 奇米精品一区二区三区在线观看| 欧美精品免费播放| 在线免费看黄视频| 国产精品高清一区二区 | 天天爽天天爽天天爽| 成人h动漫精品一区二区器材| 色婷婷一区二区| 毛片av在线播放| a天堂在线资源| 成人a免费在线看| 成人有码在线播放| 亚洲s码欧洲m码国产av| 欧美精品18| 日韩小视频网址| 亚洲精品成人无码熟妇在线| 亚洲精品a区| 欧美日韩一二三| 蜜臀av午夜一区二区三区 | 98精品国产高清在线xxxx天堂| 2014亚洲天堂| 日本在线电影一区二区三区| 国产婷婷成人久久av免费高清| 日本r级电影在线观看| 99re久久| 欧美亚洲丝袜传媒另类| 男人日女人逼逼| av影院在线| 亚洲男人的天堂在线aⅴ视频| 先锋在线资源一区二区三区| 天堂а√在线8种子蜜桃视频| 国产精品亚洲一区二区三区妖精 | 草草视频在线一区二区| 欧美一区二区三区视频免费| 国产精品视频分类| 香蕉久久免费电影| 精品成人久久av| 人妻少妇精品无码专区二区| 黄页网站大全在线免费观看| 中文字幕中文乱码欧美一区二区| 无码免费一区二区三区免费播放 | 久久精品国产亚洲7777| 亚洲欧美综合7777色婷婷| 少妇精品久久久一区二区| 日韩精品在线视频| 亚洲天堂网一区二区| 日韩精品福利一区二区三区| 日韩电影中文 亚洲精品乱码| 99热超碰在线| 日韩av不卡一区| 亚洲黄色av女优在线观看| 亚洲中文字幕无码一区| 精品国产一区二区三区不卡蜜臂| 欧美精品一区二区在线观看| avtt香蕉久久| 国产精品亚洲人成在99www| 亚洲美女在线观看| 男人的天堂av网| 久久精品高清| 免费不卡欧美自拍视频| 天天干中文字幕| 精品动漫3d一区二区三区免费版 | 欧美久久在线观看| 第四色日韩影片| 婷婷综合在线观看| 精品久久久久久中文字幕2017| 日韩一级二级| 91精品国产色综合久久ai换脸 | 国产精品欧美久久久久一区二区| 亚洲一区精品视频| a毛片在线看免费观看| 亚洲一区二区三区四区不卡| 国产91在线视频观看| 国产另类xxxxhd高清| 56国语精品自产拍在线观看| 亚洲最大视频网| 丝袜美腿综合| 久久视频在线播放| 国产一级视频在线| 久久综合影视| av免费精品一区二区三区| 色哟哟中文字幕| 中文在线免费一区三区高中清不卡| 在线观看成人一级片| 里番在线播放| 欧洲精品一区二区| 岛国大片在线免费观看| 亚洲人成精品久久久| 日韩中文字幕欧美| 韩国av免费观看| 精品亚洲成a人在线观看| 精品蜜桃一区二区三区| 欧美69xxx| 欧美性猛交xxxx免费看| 日本一区二区三区在线免费观看| 婷婷国产精品| 欧美成人午夜激情视频| 欧美一区二区三区网站| 国产精品综合久久| 日韩欧美视频一区二区三区四区| 最新av在线播放| 91久久精品一区二区三| 在线观看免费视频黄| 日韩大片在线| 日韩av手机在线观看| 性一交一乱一精一晶| 亚洲国产精品成人综合色在线婷婷 | 蜜桃91麻豆精品一二三区| 欧美国产精品专区| 日本福利视频在线| 欧美久久一区二区三区| 在线精品国产欧美| 欧美日韩综合一区二区三区| 成人h动漫精品一区二区| 在线观看三级网站| 成人在线黄色| 亚洲人成电影网| 中文字幕亚洲精品在线| 风流少妇一区二区| 午夜探花在线观看| 国产精品天堂蜜av在线播放| 国产午夜精品理论片a级探花| 久久亚洲精品大全| 国内久久精品视频| 亚洲一区二区自拍偷拍| 欧洲成人一区| 亚洲香蕉伊综合在人在线视看| 日韩无码精品一区二区三区| 国产激情一区二区三区| 公共露出暴露狂另类av| 色8久久久久| 俺去啦;欧美日韩| 91麻豆视频在线观看| 国产精品麻豆欧美日韩ww| 88av.com| 精品成人影院| 国产精品精品视频| 国产午夜视频在线观看| 色婷婷av一区| 欧美 日韩 成人| 日韩成人免费在线| 日韩亚洲视频| 精品69视频一区二区三区| 中文字幕久久亚洲| 伊人网av在线| 自拍偷拍国产精品| 亚洲一区二区福利视频| 亚洲第一天堂| 国产成人一区二区三区免费看| 好吊日av在线| 日韩精品免费在线视频观看| 日韩免费av网站| 国产精品女主播在线观看| 老司机久久精品| 欧美一区免费| 国产日本一区二区三区| 成人动漫一区| 最近2019中文免费高清视频观看www99 | 久久精品aaaaaa毛片| 神马久久午夜| 国产一区二区精品丝袜| 国产伦一区二区| 亚洲国产另类精品专区| 成人h动漫精品一区| 免费人成在线不卡| 加勒比海盗1在线观看免费国语版| 深夜激情久久| 日韩av理论片| 国产福利视频在线| 亚洲激情视频网| 中文字幕 国产| 亚洲国产日产av| 全黄一级裸体片| 国产一区 二区 三区一级| 人妻久久久一区二区三区| 禁断一区二区三区在线| 亚洲a在线观看| 亚洲欧洲高清| 久久夜色撩人精品| 人成在线免费视频| 91精品一区二区三区在线观看| 日韩大片免费在线观看| 欧美激情一区二区三区全黄| gogo亚洲国模私拍人体| 裸体一区二区| 欧美乱做爰xxxⅹ久久久| 久久91精品| 国产66精品久久久久999小说| 久久久久久久| 久久久久久亚洲精品中文字幕| 经典三级在线| 亚洲精品一区二区三区香蕉| 一级一级黄色片| 亚洲成人激情av| av资源在线免费观看| av成人免费在线观看| 一级做a爱视频| 日韩成人一级片| 国自产拍偷拍精品啪啪一区二区| 希岛爱理一区二区三区| 欧美一区二视频在线免费观看| 91成人噜噜噜在线播放| 国产日产欧美精品| 国产免费不卡| 91精品国产99久久久久久| 黄色小网站在线观看| 亚洲色图欧美制服丝袜另类第一页| 亚洲av综合色区无码一二三区 | 久久久久亚洲AV成人网人人小说| 免费av网站大全久久| 欧美黄色免费影院| 在线视频观看日韩| 女人床在线观看| 亚洲人体av| 伊人久久大香线蕉午夜av| 国产日韩欧美一区二区三区| 国产一区二区三区高清| 涩爱av色老久久精品偷偷鲁| 国产一区玩具在线观看| 九色成人搞黄网站| 国产高清在线不卡| 一根才成人网| 2019中文字幕在线| 99re6在线精品视频免费播放| 欧美理论电影在线播放| 成人av福利| 久久亚洲精品一区二区| 精品视频在线一区二区| 日韩小视频在线| 麻豆免费在线视频| 日韩小视频在线观看| 日本三级在线视频| 一区二区三区四区精品| 国产私拍精品| 在线看国产精品| 秋霞a级毛片在线看| 久久精品国产欧美激情| 久久精品视频免费看| 久久在线视频在线| 粗大黑人巨茎大战欧美成人| 久久深夜福利免费观看| 色网在线观看| 97色在线视频观看| 这里有精品可以观看| 日韩免费不卡av| 123成人网| 成人两性免费视频| 日韩一级淫片| 黑人中文字幕一区二区三区| 欧美交a欧美精品喷水| 久久久久久久久久久一区| 美女久久久久| 在线国产99| 狠狠入ady亚洲精品| 国产欧美日韩网站| 免费日韩视频| www.这里只有精品| 国产精品一卡二| 中国xxxx性xxxx产国| xfplay精品久久| 青青青视频在线播放| 亚洲三级久久久| 国产一国产二国产三| 大伊人狠狠躁夜夜躁av一区| 波多野结衣视频网址| 欧美高清一级片在线| 性生交生活影碟片| 国产视频精品xxxx| 男人资源在线播放| 国内精品视频久久| 亚洲www啪成人一区二区| 91免费看国产| 日韩三区视频| 手机成人av在线| 国产精品试看| 国产精品久久久毛片| 国产suv精品一区二区883| 日韩人妻一区二区三区| 国产精品久久久久影院| 黄色小视频在线免费看| 欧美综合天天夜夜久久| 性猛交富婆╳xxx乱大交天津| 亚洲精品视频免费| 国产黄色在线网站| 日本aⅴ大伊香蕉精品视频| 亚洲精品毛片| 噜噜噜噜噜久久久久久91| 欧美激情国产在线| 国产午夜伦鲁鲁| 国产尤物一区二区在线| 亚洲精品乱码久久久久久久久久久久| 亚洲码国产岛国毛片在线| 国产精品suv一区| 精品剧情v国产在线观看在线| 午夜不卡视频| 热久久免费国产视频| 日韩三级精品| 亚洲人体一区| 老牛嫩草一区二区三区日本 | 国产情人综合久久777777| 国产精品suv一区二区| 欧美日本一区二区三区| 日韩大片b站免费观看直播| 欧美精品一本久久男人的天堂| 欧美在线va视频| 麻豆传媒一区| 亚洲成人中文| 三级网站免费看| 国产精品午夜在线| 国产精品久免费的黄网站| 日韩欧美国产精品一区| 欧美三级理伦电影| 国产极品jizzhd欧美| 极品国产人妖chinesets亚洲人妖| 在线播放 亚洲| 蜜桃视频第一区免费观看| 91精品人妻一区二区| 天天操天天色综合| 日本韩国在线观看| 九九热这里只有在线精品视| 高清一区二区中文字幕| 一区二区三区av| 麻豆精品在线视频| 免费看裸体网站| 在线观看91精品国产入口| 日韩精品123| 欧美专区第一页| 蜜臀av免费一区二区三区| 69堂免费视频| 久久女同精品一区二区| 亚洲 欧美 日韩 综合| 亚洲激情自拍图| 三妻四妾完整版在线观看电视剧| 九色91在线视频| 国产精品视频久久一区| 黄色在线观看av| 色婷婷av一区二区三区大白胸 | 日本成人一级片| 日韩精品小视频| 三级在线看中文字幕完整版| 国产欧美日韩一区| 日韩视频中文| 动漫精品一区二区三区| 欧美视频中文在线看| 日本a一级在线免费播放| 日本在线精品视频| 精品国产一级毛片| 亚洲免费一级视频| 国产精品的网站| 精品毛片一区二区三区| 欧美国产日韩免费| 哺乳一区二区三区中文视频 | 欧美aaaaa成人免费观看视频| 五月婷婷欧美激情| 欧美日本在线观看| 91亚洲天堂| 黑人中文字幕一区二区三区| 久久久久久一区二区| 超碰人人干人人| 91精品国产综合久久福利软件 | 亚洲va欧美va人人爽午夜| 香蕉视频成人在线| 国产成人亚洲精品| 91视频久久| 精品人妻一区二区三区日产| 欧美午夜丰满在线18影院| av在线电影免费观看| 亚洲va电影大全| 亚洲精品极品| 亚洲综合欧美综合| 日韩欧美国产不卡| 亚洲小少妇裸体bbw| 在线视频91| 99久久精品国产导航| 超碰在线97观看| 欧美另类极品videosbestfree| 欧美一级色片| 欧美激情第3页| 都市激情亚洲色图| 欧美一区二区三区在线观看免费| 国产经品一区二区| 免费人成精品欧美精品| 九九热精品免费视频| 亚洲一区二区国产| 亚洲国产精品免费视频| 免费黄色日本网站| 亚洲人午夜精品天堂一二香蕉| 性猛交xxxx| 114国产精品久久免费观看| 免播放器亚洲| 久久久久久久久艹| 中文字幕精品一区久久久久| 日韩欧美中文字幕电影|