消息队列原理总结

消息队列应用的场景
  1. 业务解耦:消息队列要解决的最本质问题,实现设计的单一性原则,不耦合其他模块的业务。
  2. 最终一致性:用来处理延迟不那么敏感的“分布式事务”场景或者不重要的业务。
  3. 广播:下游有很多系统关心你的系统发出的通知的时候。
  4. 错峰和流控:上下游系统处理能力存在差距的时候,利用消息队列做一个通用的“漏斗”。在下游有能力处理的时候,再进行分发。
为什么消息队列需要broker(消息队列服务端)
  1. 一般基于消息的系统设计范式的mq都没有broker,像ActiveMQ。
  2. 设计有broker主要考虑下面几点:
    • 消息的转储,在更合适的时间点投递,或者通过一系列手段辅助消息最终能送达消费机。
    • 规范一种范式和通用的模式,以满足解耦、最终一致性、错峰等需求。其实简单理解就是一个消息转发器,把一次RPC做成两次RPC。发送者把消息投递到broker,broker再将消息转发一手到接收端。
    • 总结起来就是两次RPC加一次转储,如果要做消费确认,则是三次RPC
消息队列服务端broker的消息存储系统选型
  1. 主要的存储方案有:文件系统、分布式KV(持久化)、分布式文件系统、数据库。速度从左到右递减,可靠性相反。
  2. 用来支持支付、交易等对可靠性要求非常高,但对性能和量的要求没有这么高,DB是最好的选择。但是DB受制于IOPS,如果要求单broker5位数以上的QPS性能,基于文件的存储是比较好的解决方案。
  3. 很多消息对于投递性能的要求大于可靠性的要求,且数量极大(如日志)。这时候消息直接暂存内存,尝试几次failover,最终投递出去也可以。
最终一致性的设计思路
  1. 主要是用“记录”和“补偿”的方式。
  2. 本地事务维护业务变化和通知消息,一起落地,然后RPC到达broker,在broker成功落地后,RPC返回成功,本地消息可以删除。否则本地消息一直靠定时任务轮询不断重发,这样就保证了消息可靠落地broker。
  3. broker往consumer发送消息的过程类似,一直发送消息,直到consumer发送消费成功确认。
  4. 我们先不理会重复消息的问题,通过两次消息落地加补偿,下游是一定可以收到消息的。然后依赖状态机版本号等方式做判重,更新自己的业务,就实现了最终一致性。
  5. 如果出现消费方处理过慢消费不过来,要允许消费方主动ack error,并可以与broker约定下次投递的时间。
  6. 对于broker投递到consumer的消息,由于不确定丢失是在业务处理过程中还是消息发送丢失的情况下,有必要记录下投递的IP地址。决定重发之前询问这个IP,消息处理成功了吗?如果询问无果,再重发。
  7. 事务:本地事务,本地落地,补偿发送。本地事务做的,是业务落地和消息落地的事务,而不是业务落地和RPC成功的事务。消息只要成功落地,很大程度上就没有丢失的风险。
广播的设计思路
  1. 主要就是单播与广播的区别。所谓单播,就是点到点;而广播,是一点对多点。对于互联网的大部分应用来说,组间广播、组内单播是最常见的情形,即通知到多个业务集群中,同业务的集群中只有一个消费。
  2. 不同的组注册不同的订阅。组内的不同机器,如果注册一个相同的ID,则单播;如果注册不同的ID(如IP地址+端口),则广播。至于广播关系的维护,一般由于消息队列本身都是集群,所以都维护在公共存储上,如Zookeeper。维护广播关系所要做的事情基本都是:发送关系的维护和发送关系变更时的通知。
满足顺序消息的条件
  1. 允许消息丢失。
  2. 从发送方到服务方到接受者都是单点单线程。
如何鉴别消息重复,并幂等的处理重复消息
  1. 鉴别消息重复:利用存储系统的唯一键,给每个消息加上一个MessageId
  2. 幂等处理重复消息的方法:
    • 跟鉴别消息重复一样,利用MessageId,重复即不处理
    • 版本号,每个消息都带一个版本号,只处理比当前存储版本号高的消息
    • 状态机,跟业务耦合比较严重,根据具体业务类型判断
消息队列的同步和异步
  1. 对于客户端来说,同步与异步主要是拿到一个Result,还是Future的区别。实现方式可以是线程池,NIO或者其他事件机制。
  2. 对于服务端异步,这个是需要RPC协议支持的。参考servlet 3.0规范,服务端可以返回一个future给客户端,并且在future done的时候通知客户端。
  3. 消息队列的模型:客户端半同步半异步(使用线程池不阻塞主流程,但线程池中的任务需要等待服务端的返回),服务端是纯异步。客户端的线程池wait在服务端返回的future上,直到服务端处理完毕,才解除阻塞继续进行。
  4. 总结一句,同步能够保证结果,异步能够保证效率,要合理的结合才能做到最好的效率。
为什么网络请求小包合并成大包会提高性能
  1. 减少无谓的请求头,如果你每个请求只有几字节,而头却有几十字节,无疑效率非常低下。
  2. 减少回复的ack包个数。把请求合并后,ack包数量必然减少,确认和重发的成本就会降低。
消息队列的两种模型push和pull的对比
  1. push的缺点:慢消费。指broker给consumer推送一堆consumer无法处理的消息,consumer不是reject就是error,然后来回踢皮球。
  2. pull的缺点:消息延迟与盲等。pull是消费方主动定时去拉去消息,由于消息的不确定性,所以会造成会多无用的请求。
  3. RocketMQ的设计方案:长轮询,来平衡推拉模型各自的缺点。基本思路是:消费者如果尝试拉取失败,不是直接return,而是把连接挂在那里wait,服务端如果有新的消息到来,把连接notify起来。但海量的长连接block对系统的开销还是不容小觑的,还是要合理的评估时间间隔,给wait加一个时间上限。
ActiveMQ和RocketMQ的对比
  1. 两者都能用于分布式系统的解耦,ActiveMQ使用于企业级内部系统,RocketMQ使用大流量、高并发的互联网项目,所以还起到了流量削峰的作用。
  2. ActiveMQ定位用于企业级应用服务,所以使用于用户规模较小的场景。遵循JMS规范,由JMS Provider、Provider和Consumer三者构成,其中JMS Provider负责消息路由和消息传递。主要支持的消息模型:点对点和发布/订阅两种模型。
  3. RocketMQ的基本流程参考pg63,由NameServer(注册中心)、Boker(消息服务端)、Producer和Consumer构成。具有的基本特点:
    • 支持顺序消息。
    • 支持事务消息。
    • 支持集群(点对点)与广播(发布/订阅)模式。
    • 亿级消息堆积能力。
    • 完善的分布式特性。
    • 支持Push与Pull两种消息订阅模式。
  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值