RabbitMQ 消息的可靠投递
2020-03-24 16:24:48来源:博客园 阅读 ()
RabbitMQ 消息的可靠投递
可靠性投递:
1、保障消息能够成功发出
2、保障rabbitmq(broker)能够成功接收。接收指的是:broker接收到生产者发送的消息,放到exchange中,分发给对应的queue,交付给对应的消费者。
3、发送端要收到broker的确认应答,确认broker已收到|处理消息
4、完善的消息补偿机制。发送端没收到broker的确认应答,不知道消息是否成功投递成功,这时候就需要做一些补偿处理,比如重新投递。
rabbitmq的server又叫做broker,接收客户端的连接,实现AMQP实体服务,包含exchange、queue等多种组件。
说白了,broker就是rabbitmq服务器。
实现消息可靠性投递的、常见的2种解决方案
- 消息状态入库,对消息状态进行打标
- 延时再次投递消息,回调确认
第一种方案 消息状态打标
1、生产者将消息入库、消息状态入库。
比如用户下单,产生一个Order对象,把这个Order对象数据持久化到数据库中
单独用一张表来存储消息状态:
用外键关联消息(比如关联订单表的id),
设置一个status列记录消息投递状态,默认值为0,表示消息未投递到broker;
设置一个时间列,记录消息投递时间;
设置一个重试次数列,记录重新投递的次数,默认值为0。
2、生产者发送消息到broker
把Order对象发送到broker,因为消息都要转换为byte[ ]发送,什么类型都可以。
3、生产者接收到broker的确认应答,将数据库中该条消息的状态修改为1,表示成功投递
4、分布式系统的定时任务
如果消息投递一段时间后,未收到broker的确认应答,怎么补偿处理?
使用定时任务来做:
生产者每隔一段时间,比如5min,启动一条线程来查询数据库中重试次数达到指定值(比如3)、且投递时间已超过指定值(比如5min)的消息,将其状态修改为2,表示重试指定次数后仍未能成功投递;
再查询状态为0、且发送时间已超过指定时间的消息,重新投递,并更新投递时间为当前时间、重试次数+1;
第一种方案存在的问题
生产者执行定时任务也有额外的开销,生产者要进行2方面的数据库IO操作(消息本身+消息状态),IO是很花时间的,在高并发的情况下,数据库性能很容易成为系统性能的瓶颈。
并发量大的情况下,第一种方案严重拉低生产者的性能。
相比之下,第二种方案用得更多,但稍微复杂一点。
第二种方案 延时再次投递消息
1、生产者将消息入库,并将消息发送给broker,broker将消息放到对应的queue1中
2、消费者监听queue1,处理消息,处理一条消息后产生一条新消息作为确认(绑定queue2),比如以Order的id作为新消息,总之要能唯一标识处理的消息。
3、消费者将产生的消息发送给broker,broker将消息放到queue2中(注意不是消费者监听的queue1)
4、单独写一个callback service(回调服务),来监听queue2,把queue2中的消息入库,比如放在tb_msg_processed表中,一条记录代表一条已被消费者处理的消息
5、生产者发送消息后,延时再次发送这条消息(绑定queue3),比如3min|5min后再次发送这条消息。
6、回调服务监听queue3,把queue中消息与数据库中的记录对比,比如把queue3获取到的Order的id取出来,查询tb_msg_processed中有没有这个Order id,有就说明投递成功;没有就说说明未投妥,回调服务rpc通知生产者(传递order id),生产者从数据库查询该条消息的数据(order对象),重新投递(queue1)——重新走一遍流程。
第一种方案消费者使用数据包来确认应答(ack),第二种由消费者自己产生一条消息来确认应答。
整个流程中,生产者又叫做upstream service(上游服务),消费者又叫做downstream service(下游服务)。
第二种方案的优缺点
相较于第一种方案,第二种方案多写一个服务,每对生产者——消费者都使用一个额外的queue来确认,回调服务开发成本高些、略微复杂些;
部署回调服务又要使用、维护额外的机器,成本变高了。
但生产者的数据库IO操作减少了,提升了性能。只要性能上去,稍微增加点成本完全可以接受。
说明
(1)消息入库完成,然后发送消息(Order对象)到broker,注意顺序
(2)分布式事务对性能的影响很大,并发量中小的可以加事务,如果并发量很大,事务会严重拉低性能,不建议加事务(能不加就不加)
(3)不管是第一种、还是第二种,都很难做到100%的投递成功。优先考虑能够扛得住高并发(性能),在保证性能的前提下尽可能提高消息投递的可靠性
原文链接:https://www.cnblogs.com/chy18883701161/p/12558074.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
上一篇:Jenkins的邮件通知
下一篇:Java8 Stream流
- 数据源管理 | Kafka集群环境搭建,消息存储机制详解 2020-06-11
- 高吞吐量的分布式发布订阅消息系统Kafka之Producer源码分析 2020-05-30
- SpringBoot2.3整合RabbitMQ实现延迟消费消息 2020-05-26
- RedisTemplate实现消息队列并且批量插入数据。 2020-05-22
- Docker中使用RabbitMQ 2020-05-21
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash