电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

JAVA 實(shí)現(xiàn)延遲隊(duì)列的方法

瀏覽:3日期:2022-08-30 10:19:41

延遲隊(duì)列的需求各位應(yīng)該在日常開(kāi)發(fā)的場(chǎng)景中經(jīng)常碰到。比如:

用戶登錄之后5分鐘給用戶做分類推送; 用戶多少天未登錄給用戶做召回推送; 定期檢查用戶當(dāng)前退款賬單是否被商家處理等等場(chǎng)景。

一般這種場(chǎng)景和定時(shí)任務(wù)還是有很大的區(qū)別,定時(shí)任務(wù)是你知道任務(wù)多久該跑一次或者什么時(shí)候只跑一次,這個(gè)時(shí)間是確定的。延遲隊(duì)列是當(dāng)某個(gè)事件發(fā)生的時(shí)候需要延遲多久觸發(fā)配套事件,引子事件發(fā)生的時(shí)間不是固定的。

業(yè)界目前也有很多實(shí)現(xiàn)方案,單機(jī)版的方案就不說(shuō)了,現(xiàn)在也沒(méi)有哪個(gè)公司還是單機(jī)版的服務(wù),今天我們一一探討各種方案的大致實(shí)現(xiàn)。

1. Redis zset

這個(gè)方案比較常用,簡(jiǎn)單有效。利用 Redis 的 sorted set 結(jié)構(gòu),使用 timeStamp 作為 score,比如你的任務(wù)是要延遲5分鐘,那么就在當(dāng)前時(shí)間上加5分鐘作為 score ,輪詢?nèi)蝿?wù)每秒只輪詢 score 大于當(dāng)前時(shí)間的 key即可,如果任務(wù)支持有誤差,那么當(dāng)沒(méi)有掃描到有效數(shù)據(jù)的時(shí)候可以休眠對(duì)應(yīng)時(shí)間再繼續(xù)輪詢。

方案優(yōu)劣:

優(yōu)點(diǎn):

簡(jiǎn)單實(shí)用,一針見(jiàn)血。

缺點(diǎn):

單個(gè) zset 肯定支持不了太大的數(shù)據(jù)量,如果你有幾百萬(wàn)的延遲任務(wù)需求,大哥我還是勸你換一個(gè)方案; 定時(shí)器輪詢方案可能會(huì)有異常終止的情況需要自己處理,同時(shí)消息處理失敗的回滾方案,您也要自己處理。

所以,sorted set 的方案并不是一個(gè)成熟的方案,他只是一個(gè)快速可供落地的方案。

2. RabbitMQ隊(duì)列

下面說(shuō)一個(gè)可以落地的方案,這個(gè)方案也被大多數(shù)目前在架構(gòu)中使用了 RabbitMQ 的項(xiàng)目組使用。不好的一點(diǎn)就是,捆綁 RabbitMQ,當(dāng)你的架構(gòu)方案是要用別的 MQ 替換 RabbitMQ 的時(shí)候,你就蛋疼了(我現(xiàn)在正在經(jīng)歷)。

RabbitMQ 有兩個(gè)特性,一個(gè)是 Time-To-Live Extensions,另一個(gè)是 Dead Letter Exchanges。

Time-To-Live Extensions

RabbitMQ允許我們?yōu)橄⒒蛘哧?duì)列設(shè)置TTL(time to live),也就是過(guò)期時(shí)間。TTL表明了一條消息可在隊(duì)列中存活的最大時(shí)間,單位為毫秒。也就是說(shuō),當(dāng)某條消息被設(shè)置了TTL或者當(dāng)某條消息進(jìn)入了設(shè)置了TTL的隊(duì)列時(shí),這條消息會(huì)在經(jīng)過(guò)TTL秒后 “死亡”,成為Dead Letter。如果既配置了消息的TTL,又配置了隊(duì)列的TTL,那么較小的那個(gè)值會(huì)被取用。

Dead Letter Exchanges

在 RabbitMQ 中,一共有三種消息的 “死亡” 形式:

消息被拒絕。通過(guò)調(diào)用 basic.reject 或者 basic.nack 并且設(shè)置的 requeue 參數(shù)為 false; 消息因?yàn)樵O(shè)置了TTL而過(guò)期; 隊(duì)列達(dá)到最大長(zhǎng)度。

DLX同一般的 Exchange 沒(méi)有區(qū)別,它能在任何的隊(duì)列上被指定,實(shí)際上就是設(shè)置某個(gè)隊(duì)列的屬性。當(dāng)隊(duì)列中有 DLX 消息時(shí),RabbitMQ就會(huì)自動(dòng)的將 DLX 消息重新發(fā)布到設(shè)置的 Exchange 中去,進(jìn)而被路由到另一個(gè)隊(duì)列,publish 可以監(jiān)聽(tīng)這個(gè)隊(duì)列中消息做相應(yīng)的處理。

由上簡(jiǎn)介大家可以看出,RabbitMQ本身是不支持延遲隊(duì)列的,只是他的特性讓勤勞的 中國(guó)脫發(fā)群體 急中生智(為了完成任務(wù))弄出了這么一套可用的方案。

可用的方案就是:

如果有事件需要延遲那么將該事件發(fā)送到MQ 隊(duì)列中,為需要延遲的消息設(shè)置一個(gè)TTL; TTL到期后就會(huì)自動(dòng)進(jìn)入設(shè)置好的DLX,然后由DLX轉(zhuǎn)發(fā)到配置好的實(shí)際消費(fèi)隊(duì)列; 消費(fèi)該隊(duì)列的延遲消息,處理事件。

方案優(yōu)劣:

優(yōu)點(diǎn):

大品牌組件,用的放心。如果面臨大數(shù)據(jù)量需求可以很容易的橫向擴(kuò)展,同時(shí)消息支持持久化,有問(wèn)題可回滾。

缺點(diǎn):

配置麻煩,額外增加一個(gè)死信交換機(jī)和一個(gè)死信隊(duì)列的配置; RabbitMQ 是一個(gè)消息中間件,TTL 和 DLX 只是他的一個(gè)特性,將延遲隊(duì)列綁定在一個(gè)功能軟件的某一個(gè)特性上,可能會(huì)有風(fēng)險(xiǎn)。不要杠,當(dāng)你們組不用 RabbitMQ 的時(shí)候遷移很痛苦; 消息隊(duì)列具有先進(jìn)先出的特點(diǎn),如果第一個(gè)進(jìn)入隊(duì)列的消息 A 的延遲是10分鐘,第二個(gè)進(jìn)入隊(duì)列的消息B 的延遲是5分鐘,期望的是誰(shuí)先到 TTL誰(shuí)先出,但是事實(shí)是B已經(jīng)到期了,而還要等到 A 的延遲10分鐘結(jié)束A先出之后,B 才能出。所以在設(shè)計(jì)的時(shí)候需要考慮不同延遲的消息要放到不同的隊(duì)列。另外該問(wèn)題官方已經(jīng)給出了插件來(lái)支持:插件地址。

3. 基于 Netty#HashedWheelTimer類方法的實(shí)現(xiàn)

HashedWheelTimer 是 Netty 中 的一個(gè)基礎(chǔ)工具類,主要用來(lái)高效處理大量定時(shí)任務(wù),且任務(wù)對(duì)時(shí)間精度要求相對(duì)不高, 在Netty 中的應(yīng)用場(chǎng)景就是連接超時(shí)或者任務(wù)處理超時(shí),一般都是操作比較快速的任務(wù),缺點(diǎn)是內(nèi)存占用相對(duì)較高。

算法思想

HashedWheelTimer 主要還是一個(gè) DelayQueue 和一個(gè)時(shí)間輪算法組合。

JAVA 實(shí)現(xiàn)延遲隊(duì)列的方法

Hash Wheel Timer是一個(gè)環(huán)形結(jié)構(gòu),可以想象成時(shí)鐘,分為很多格子,一個(gè)格子代表一段時(shí)間(越短Timer精度越高),并用一個(gè)List保存在該格子上到期的所有任務(wù)。同時(shí)一個(gè)指針隨著時(shí)間流逝一格一格轉(zhuǎn)動(dòng),并執(zhí)行對(duì)應(yīng)List中所有到期的任務(wù)。

以上圖為例,假設(shè)一個(gè)格子是1s,則整個(gè)時(shí)間輪能表示的時(shí)間段16s。當(dāng)前任務(wù)指向格子2,表明在第2s的時(shí)候有任務(wù)需要執(zhí)行。任務(wù)列表中有兩個(gè)任務(wù),每個(gè)任務(wù)前面的數(shù)字表示圈數(shù)。2表示當(dāng)走到第2圈的時(shí)候才會(huì)執(zhí)行,那么整個(gè)任務(wù)的真正執(zhí)行時(shí)間其實(shí)是在12s之后執(zhí)行,即第二圈走到2的時(shí)候。每推進(jìn)一格,對(duì)應(yīng)的每一個(gè) slot 中的round數(shù)都要減一。整體算法就是這么個(gè)邏輯。

時(shí)間輪設(shè)計(jì)要點(diǎn):

tick,一次時(shí)間推進(jìn),每次推進(jìn)會(huì)檢查/執(zhí)行超時(shí)任務(wù); tickDuration,時(shí)間輪推進(jìn)的最小單元,每隔 tickDuration 會(huì)有一次 tick,它決定了時(shí)間輪的精確程度; bucket(ticksPerWheel),上圖中的每一隔就是一個(gè)bucket,表示一個(gè)時(shí)間輪可以有多少個(gè)tick,它是存儲(chǔ)任務(wù)的最小單元; 上層時(shí)間輪的 tickDuration 是下層時(shí)間輪的表示時(shí)間的最大范圍,即:父 tickDuration = 子 tickDuration * 子 bucket 。

需要注意的是,這種方式任務(wù)是串行執(zhí)行的。意味著你如果在時(shí)間輪中執(zhí)行任務(wù)且任務(wù)耗時(shí)較長(zhǎng),將會(huì)出現(xiàn)調(diào)度超時(shí)或者任務(wù)堆積的情況。所以要將任務(wù)的執(zhí)行異步化。

算法的要點(diǎn):

任務(wù)并不是直接放在格子中的,而是維護(hù)了一個(gè)雙向鏈表,這種數(shù)據(jù)結(jié)構(gòu)非常便于插入和移除; 新添加的任務(wù)并不直接放入格子,而是先放入一個(gè)隊(duì)列中,這是為了避免多線程插入任務(wù)的沖突。在每個(gè)tick運(yùn)行任務(wù)之前由worker線程自動(dòng)對(duì)任務(wù)進(jìn)行歸集和分類,插入到對(duì)應(yīng)的槽位里面。

Netty 使用數(shù)組 + 雙向鏈表的方式來(lái)組織時(shí)間輪,對(duì)于添加/取消操作僅做了記錄,真正的操作實(shí)際發(fā)生在下一個(gè)tick。時(shí)間的推進(jìn)是獨(dú)立的線程在做,該線程同時(shí)也負(fù)責(zé)過(guò)期任務(wù)的執(zhí)行等操作,可簡(jiǎn)單認(rèn)為此步驟操作為O(n),因?yàn)橥七M(jìn)線程需要完全遍歷timeouts、cancelledTimeouts與bucket鏈表,在遍歷timeouts時(shí),Netty為了避免任務(wù)過(guò)多,所以限制每次最多遍歷10萬(wàn)個(gè),也就是說(shuō),一個(gè)tick只能規(guī)劃10萬(wàn)個(gè)任務(wù),當(dāng)任務(wù)量過(guò)大時(shí),會(huì)存在超時(shí)任務(wù)執(zhí)行時(shí)間延遲的現(xiàn)象。

方案優(yōu)劣:

優(yōu)點(diǎn):

實(shí)現(xiàn)比較優(yōu)雅。效率高。

缺點(diǎn):

無(wú)法實(shí)現(xiàn)HA和橫向擴(kuò)展,要么就使用多個(gè)時(shí)間輪。最重要的是,實(shí)現(xiàn)也比較復(fù)雜,開(kāi)發(fā)者需要考慮所有可能的情況。目前我了解到的延遲隊(duì)列在生產(chǎn)環(huán)境下有如上三種實(shí)現(xiàn)方式,每一種都有人在使用。當(dāng)然沒(méi)有最好的只有最適合的,你覺(jué)得 redis 能滿足需求,就按照最簡(jiǎn)單的來(lái),你要是有充足的開(kāi)發(fā)周期,你也可以實(shí)現(xiàn)時(shí)間輪展現(xiàn)實(shí)力。

需求千萬(wàn)種,變化就一種:給時(shí)間都能做。

以上就是JAVA 實(shí)現(xiàn)延遲隊(duì)列的方法的詳細(xì)內(nèi)容,更多關(guān)于JAVA 實(shí)現(xiàn)延遲隊(duì)列的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Java
相關(guān)文章:
主站蜘蛛池模板: 浙江富广阀门有限公司| 立式_复合式_壁挂式智能化电伴热洗眼器-上海达傲洗眼器生产厂家 理化生实验室设备,吊装实验室设备,顶装实验室设备,实验室成套设备厂家,校园功能室设备,智慧书法教室方案 - 东莞市惠森教学设备有限公司 | 阁楼货架_阁楼平台_仓库仓储设备_重型货架_广州金铁牛货架厂 | 一级建造师培训_一建培训机构_中建云筑建造师培训网校 | 工程管道/塑料管材/pvc排水管/ppr给水管/pe双壁波纹管等品牌管材批发厂家-河南洁尔康建材 | 精密交叉滚子轴承厂家,转盘轴承,YRT转台轴承-洛阳千协轴承 | 佛山市德信昌电子有限公司 | 高温热泵烘干机,高温烘干热泵,热水设备机组_正旭热泵 | 武汉不干胶印刷_标签设计印刷_不干胶标签印刷厂 - 武汉不干胶标签印刷厂家 | 兰州UPS电源,兰州山特UPS-兰州万胜商贸| 罐体电伴热工程-消防管道电伴热带厂家-山东沃安电气 | 尾轮组_头轮组_矿用刮板_厢式刮板机_铸石刮板机厂家-双驰机械 | POS机办理_个人pos机免费领取-银联pos机申请首页 | 真空干燥烘箱_鼓风干燥箱 _高低温恒温恒湿试验箱_光照二氧化碳恒温培养箱-上海航佩仪器 | 京马网,京马建站,网站定制,营销型网站建设,东莞建站,东莞网站建设-首页-京马网 | 贵州成人高考网_贵州成考网| 小型气象站_便携式自动气象站_校园气象站-竞道气象设备网 | 郑州爱婴幼师学校_专业幼师培训_托育师培训_幼儿教育培训学校 | 精密交叉滚子轴承厂家,转盘轴承,YRT转台轴承-洛阳千协轴承 | 湿地保护| 东莞猎头公司_深圳猎头公司_广州猎头公司-广东万诚猎头提供企业中高端人才招聘服务 | 根系分析仪,大米外观品质检测仪,考种仪,藻类鉴定计数仪,叶面积仪,菌落计数仪,抑菌圈测量仪,抗生素效价测定仪,植物表型仪,冠层分析仪-杭州万深检测仪器网 | 冰晶石|碱性嫩黄闪蒸干燥机-有机垃圾烘干设备-草酸钙盘式干燥机-常州市宝康干燥 | 渣土车电机,太阳能跟踪器电机,蜗轮蜗杆减速电机厂家-淄博传强电机 | 双段式高压鼓风机-雕刻机用真空泵-绍兴天晨机械有限公司 | 理化生实验室设备,吊装实验室设备,顶装实验室设备,实验室成套设备厂家,校园功能室设备,智慧书法教室方案 - 东莞市惠森教学设备有限公司 | 深圳法律咨询【24小时在线】深圳律师咨询免费 | 交变/复合盐雾试验箱-高低温冲击试验箱_安奈设备产品供应杭州/江苏南京/安徽马鞍山合肥等全国各地 | 定制/定做冲锋衣厂家/公司-订做/订制冲锋衣价格/费用-北京圣达信 | 氟氨基酮、氯硝柳胺、2-氟苯甲酸、异香兰素-新晨化工 | 大米加工设备|大米加工机械|碾米成套设备|大米加工成套设备-河南成立粮油机械有限公司 | 色谱柱-淋洗液罐-巴罗克试剂槽-巴氏吸管-5ml样品瓶-SBS液氮冻存管-上海希言科学仪器有限公司 | 组织研磨机-高通量组织研磨仪-实验室多样品组织研磨机-东方天净 传递窗_超净|洁净工作台_高效过滤器-传递窗厂家广州梓净公司 | 智慧钢琴-电钢琴-便携钢琴-数码钢琴-深圳市特伦斯乐器有限公司 | 中高频感应加热设备|高频淬火设备|超音频感应加热电源|不锈钢管光亮退火机|真空管烤消设备 - 郑州蓝硕工业炉设备有限公司 | 商秀—企业短视频代运营_抖音企业号托管 | 北京亦庄厂房出租_经开区产业园招商信息平台 | 本安接线盒-本安电路用接线盒-本安分线盒-矿用电话接线盒-JHH生产厂家-宁波龙亿电子科技有限公司 | 数控走心机-双主轴走心机厂家-南京建克| 磷酸肌酸二钠盐,肌酐磷酰氯-沾化欣瑞康生物科技 | 胶水,胶粘剂,AB胶,环氧胶,UV胶水,高温胶,快干胶,密封胶,结构胶,电子胶,厌氧胶,高温胶水,电子胶水-东莞聚力-聚厉胶粘 |