关系经济人类预测化学自然
中准网
自然科学
知识物理
化学生物
地理解释
预测理解
本质社会
人类现象
行为研究
经济政治
心理结构
关系指导
人文遗产

延时消息常见实现方案

4月28日 月依兮投稿
  前言
  延时消息(定时消息)指的在分布式异步消息场景下,生产端发送一条消息,希望在指定延时或者指定时间点被消费端消费到,而不是立刻被消费。
  延时消息适用的业务场景非常的广泛,在分布式系统环境下,延时消息的功能一般会在下沉到中间件层,通常是MQ中内置这个功能或者内聚成一个公共基础服务。
  本文旨在探讨常见延时消息的实现方案以及方案设计的优缺点。实现方案1。基于外部存储实现的方案
  这里讨论的外部存储指的是在MQ本身自带的存储以外又引入的其他的存储系统。
  基于外部存储的方案本质上都是一个套路,将MQ和延时模块区分开来,延时消息模块是一个独立的服务进程。延时消息先保留到其他存储介质中,然后在消息到期时再投递到MQ。当然还有一些细节性的设计,比如消息进入的延时消息模块时已经到期则直接投递这类的逻辑,这里不展开讨论。
  下述方案不同的是,采用了不同的存储系统。基于数据库(如MySQL)
  基于关系型数据库(如MySQL)延时消息表的方式来实现。CREATETABLEdelaymsg(idbigintunsignedNOTNULLAUTOINCREMENT,deliverytimeDATETIMENOTNULLCOMMENT投递时间,payloadsblobCOMMENT消息内容,PRIMARYKEY(id),KEYtimeindex(deliverytime))
  通过定时线程定时扫描到期的消息,然后进行投递。定时线程的扫描间隔理论上就是你延时消息的最小时间精度。
  优点:实现简单;
  缺点:BTree索引不适合消息场景的大量写入;基于RocksDB
  RocksDB的方案其实就是在上述方案上选择了比较合适的存储介质。
  RocksDB在笔者之前的文章中有聊过,LSM树根更适合大量写入的场景。滴滴开源的DDMQ中的延时消息模块Chronos就是采用了这个方案。
  DDMQ这个项目简单来说就是在RocketMQ外面加了一层统一的代理层,在这个代理层就可以做一些功能维度的扩展。延时消息的逻辑就是代理层实现了对延时消息的转发,如果是延时消息,会先投递到RocketMQ中Chronos专用的topic中。延时消息模块Chronos消费得到延时消息转出到RocksDB,后面就是类似的逻辑了,定时扫描到期的消息,然后往RocketMQ中投递。
  这个方案老实说是一个比较重要的方案。因为基于RocksDB来实现的话,从数据可用性的角度考虑,你还需要自己去处理多副本的数据同步等逻辑。
  优点:RocksDBLSM树很适合消息场景的大量写入;
  缺点:实现方案较重,如果你采用这个方案,需要自己实现RocksDB的数据容灾逻辑;基于Redis
  再来聊聊Redis的方案。下面放一个比较完善的方案。
  本方案来源于:https:www。cnblogs。comlylifep7881950。html
  MessagesPool所有的延时消息存放,结构为KV结构,key为消息ID,value为一个具体的message(这里选择RedisHash结构主要是因为hash结构能存储较大的数据量,数据较多时候会进行渐进式rehash扩容,并且对于HSET和HGET命令来说时间复杂度都是O(1))DelayedQueue是16个有序队列(队列支持水平扩展),结构为ZSET,value为messagespool中消息ID,score为过期时间(分为多个队列是为了提高扫描的速度)Worker代表处理线程,通过定时任务扫描DelayedQueue中到期的消息
  这个方案选用Redis存储在我看来有以下几点考虑,RedisZSET很适合实现延时队列性能问题,虽然ZSET插入是一个O(logn)的操作,但是Redis基于内存操作,并且内部做了很多性能方面的优化。
  但是这个方案其实也有需要斟酌的地方,上述方案通过创建多个DelayedQueue来满足对于并发性能的要求,但这也带来了多个DelayedQueue如何在多个节点情况下均匀分配,并且很可能出现到期消息并发重复处理的情况,是否要引入分布式锁之类的并发控制设计?
  在量不大的场景下,上述方案的架构其实可以蜕化成主从架构,只允许主节点来处理任务,从节点只做容灾备份。实现难度更低更可控。定时线程检查的缺陷与改进
  上述几个方案中,都通过线程定时扫描的方案来获取到期的消息。
  定时线程的方案在消息量较少的时候,会浪费资源,在消息量非常多的时候,又会出现因为扫描间隔设置不合理导致延时时间不准确的问题。可以借助JDKTimer类中的思想,通过waitnotify来节省CPU资源。
  获取中最近的延时消息,然后wait(执行时间当前时间),这样就不需要浪费资源到达时间时会自动响应,如果有新的消息进入,并且比我们等待的消息还要小,那么直接notify唤醒,重新获取这个更小的消息,然后又wait,如此循环。2。开源MQ中的实现方案
  再来讲讲目前自带延时消息功能的开源MQ,它们是如何实现的RocketMQ
  RocketMQ开源版本支持延时消息,但是只支持18个Level的延时,并不支持任意时间。只不过这个Level在RocketMQ中可以自定义的,所幸来说对普通业务算是够用的。默认值为1s5s10s30s1m2m3m4m5m6m7m8m9m10m20m30m1h2h,18个level。
  通俗地讲,设定了延时Level的消息会被暂存在名为SCHEDULETOPICXXXX的topic中,并根据level存入特定的queue,queueIddelayTimeLevel1,即一个queue只存相同延时的消息,保证具有相同发送延时的消息能够顺序消费。broker会调度地消费SCHEDULETOPICXXXX,将消息写入真实的topic。
  下面是整个实现方案的示意图,红色代表投递延时消息,紫色代表定时调度到期的延时消息:
  优点:Level数固定,每个Level有自己的定时器,开销不大将Level相同的消息放入到同一个Queue中,保证了同一Level消息的顺序性;不同Level放到不同的Queue中,保证了投递的时间准确性;通过只支持固定的Level,将不同延时消息的排序变成了固定LevelTopic的追加写操作
  缺点:Level配置的修改代价太大,固定Level不灵活CommitLog会因为延时消息的存在变得很大Pulsar
  Pulsar支持任意时间的延时消息,但实现方式和RocketMQ不同。
  通俗的讲,Pulsar的延时消息会直接进入到客户端发送指定的Topic中,然后在堆外内存中创建一个基于时间的优先级队列,来维护延时消息的索引信息。延时时间最短的会放在头上,时间越长越靠后。在进行消费逻辑时候,再判断是否有到期需要投递的消息,如果有就从队列里面拿出,根据延时消息的索引查询到对应的消息进行消费。
  如果节点崩溃,在这个broker节点上的Topics会转移到其他可用的broker上,上面提到的这个优先级队列也会被重建。
  下面是Pulsar公众号中对于Pulsar延时消息的示意图。
  乍一看会觉得这个方案其实非常简单,还能支持任意时间的消息。但是这个方案有几个比较大的问题内存开销:维护延时消息索引的队列是放在堆外内存中的,并且这个队列是以订阅组(Kafka中的消费组)为维度的,比如你这个Topic有N个订阅组,那么如果你这个Topic使用了延时消息,就会创建N个队列;并且随着延时消息的增多,时间跨度的增加,每个队列的内存占用也会上升。(是的,在这个方案下,支持任意的延时消息反而有可能让这个缺陷更严重)故障转移之后延时消息索引队列的重建时间开销:对于跨度时间长的大规模延时消息,重建时间可能会到小时级别。(摘自Pulsar官方公众号文章)存储开销:延时消息的时间跨度会影响到Pulsar中已经消费的消息数据的空间回收。打个比方,你的Topic如果业务上要求支持一个月跨度的延时消息,然后你发了一个延时一个月的消息,那么你这个Topic中底层的存储就会保留整整一个月的消息数据,即使这一个月中99的正常消息都已经消费了。
  对于前面第一点和第二点的问题,社区也设计了解决方案,在队列中加入时间分区,Broker只加载当前较近的时间片的队列到内存,其余时间片分区持久化磁盘,示例图如下图所示:
  但是目前,这个方案并没有对应的版本。可以在实际使用时,规定只能使用较小时间跨度的延时消息,来减少前两点缺陷的影响。
  至于第三个方案,估计是比较难解决的,需要在数据存储层将延时消息和正常消息区分开来,单独存储延时消息。QMQ
  QMQ提供任意时间的延时定时消息,你可以指定消息在未来两年内(可配置)任意时间内投递。
  把QMQ放到最后,是因为我觉得QMQ是目前开源MQ中延时消息设计最合理的。里面设计的核心简单来说就是多级时间轮延时加载延时消息单独磁盘存储。
  如果对时间轮不熟悉的可以阅读笔者的这篇文章从Kafka看时间轮算法设计
  QMQ的延时定时消息使用的是两层hashwheel来实现的。第一层位于磁盘上,每个小时为一个刻度(默认为一个小时一个刻度,可以根据实际情况在配置里进行调整),每个刻度会生成一个日志文件(schedulelog),因为QMQ支持两年内的延时消息(默认支持两年内,可以进行配置修改),则最多会生成23662417568个文件(如果需要支持的最大延时时间更短,则生成的文件更少)。第二层在内存中,当消息的投递时间即将到来的时候,会将这个小时的消息索引(索引包括消息在schedulelog中的offset和size)从磁盘文件加载到内存中的hashwheel上,内存中的hashwheel则是以500ms为一个刻度。
  总结一下设计上的亮点:时间轮算法适合延时定时消息的场景,省去延时消息的排序,插入删除操作都是O(1)的时间复杂度;通过多级时间轮设计,支持了超大时间跨度的延时消息;通过延时加载,内存中只会有最近要消费的消息,更久的延时消息会被存储在磁盘中,对内存友好;延时消息单独存储(schedulelog),不会影响到正常消息的空间回收;总结
  本文汇总了目前业界常见的延时消息方案,并且讨论了各个方案的优缺点。希望对读者有所启发。
  原文https:ricstudio。toparchivesdelaymsgdesigns
投诉 评论 转载

女排全明星评选最新数据天津占据五个榜首,李盈莹遥遥领先女排全明星评选投票的时间已经过半,按照之前的规则,这次全明星将会评选出8个主攻、8个副攻、4个二传、4个接应、4个自由人以及4个教练,而这是按照每个位置上得票最多的球员依次选出……看曼联季前热身赛,聊新赛季的打法瞎想,这样的曼联可期随着夏季引援的不断深入,曼联的新阵容初见端倪,随着第一场和利物浦的热身赛以四比一狂胜后,球迷们不禁开始对这个推倒重建,新帅上任后的全新曼联有了一个初步的印像,且不论这场比赛参考……海南机场众高管被罚450万元随着海南航空摘帽成功,股票简称由ST海航变为海航控股。原海航旗下另一大板块海航基础也加快了摘帽的进程。当然如今的海航基础已经改名海南机场。不过就股票名称而言,……科比的运球也不是很花哨,为什么过人那么轻松?篮球是一项运动,并不是杂技表演。运球的目的不是花式表演,是为了进球得分。只要你能够进球得分,你直接扛着人投篮那也是本事。科比并不惧怕对方的防守,所以过不过人对他的影响并不大。他……自述2022年业绩不可接受奔跑的汤臣倍健怎么了?白马股汤臣倍健,2022年被业绩绊倒了。3月17日,公司董事长梁允超在致股东信中自述,公司营收、归母净利润均与年初预算存在明显偏差,并称这样的结果显然是不可接受的。年报显……又一美妆巨头揭幕全球研发中心,以新科技驱动本土发展成都日报锦观新闻记者陈超继资生堂、雅诗兰黛等先后在中国建设全球第二大创新中心后,又一跨国美妆巨头在中国掀起了新一轮的研发投资热潮。在日前举行的皮肤光生物学国际峰会上,Mi……小山智丽不是叛徒,是乒乓球发展的有功之臣中国乒乓挑战季中国乒乓女队长盛不哀,从九十年代开始统治乒坛的女皇先后有邓亚萍,张怡宁,王楠等,他们都对中国乒乓球做出了不可抹灰的贡献。但要说到女运动员谁对乒乓球的发展做出……陈慧琳久违上班憋太久,光着手臂穿吊带好清凉,换发型变国际美人很多女性对裙装那真的是情有独钟,尤其是吊带裙这种单品,凭借独特的裁剪设计,结合驾驭者的身材从而展现出时尚性感的一面,将女性的气质和身材展现得淋漓尽致,不过吊带裙虽美,对于女性的……立秋后,多吃五种防秋燥食材,顺应时节,安稳过秋天今年立秋尤其的早,还是二伏之中,真是一年之中最热的时候,酷暑时节,立秋了该怎么吃呢?正所谓应季而食,不时不食,不同季节的能吃到什么?应该吃到什么?充满智慧的老祖宗们早已经给总结……科尔皮芬兰的冰公主,因伤病退役,活成大女主如果你只能再活一年、一个月或一天,你会去做什么。你会如何生活?科尔皮选择了直面自己曾遭受的不公,她以一己之力对抗整个芬兰体育体系。四岁的时候科尔皮就已经开始滑冰,那……从3199跌至2209元,骁龙87019GB运存,真香曲面屏不难发现如今很多旗舰手机都采用了曲面屏的设计,而且越是高端的型号,越是Pro的版本,采用曲面屏设计的越多,当然这是对于安卓手机来说,苹果这边,一直都是采用直屏设计。三星可以说是……延时消息常见实现方案前言延时消息(定时消息)指的在分布式异步消息场景下,生产端发送一条消息,希望在指定延时或者指定时间点被消费端消费到,而不是立刻被消费。延时消息适用的业务场景非常的广……
察言观色教你六招都是拖拉惹的祸收藏火车提前几分钟停止检票?官方解答经常堕胎药对身体有哪些副作用瑞媒中国解封导致油价继续攀升?姜堰溱湖号高铁列车启程青海湖今年冬季特色节目赏冰雪看天鹅相隔造句用相隔造句大全魅力盐源丨二月的泸沽湖藏着什么样的美景?年货造句用年货造句大全看看三月你的桃花运来了吗疼痛一抹灵疼痛一喷灵疼痛一敷灵号称
妇女安全期有哪些常用的自测方法热播韩剧网(追韩剧美剧网站推荐)热文聚热点网 教师交流工作总结草莓籽红色是染色吗暑假趣事的500字作文热评聚热点网 三观超正的句子简短三观正能量的短句子李玉成新婚在即?豪掷50万买新车,开心直跳迪斯科,网友太嘚瑟寒假征文寒假生活省份年平均工资出炉北京最高河南垫底篮球联赛上大闹裁判席,吼裁判骂人现象咋不治理?欧盟议会认定俄罗斯为支持恐怖主义国家美国为何怂了靠辛苦和努力赚不了大钱

友情链接:中准网聚热点快百科快传网快生活快软网快好知文好找菏泽德阳山西湖州宝鸡上海茂名内江三亚信阳长春北海西安安徽黄石烟台沧州湛江肇庆鹤壁六安韶关成都钦州