原创:小姐姐味道(微信公众号ID:xjjdog),欢迎分享,转载请保留出处。java
分布式缓存方面,redis勇夺花魁。但对于消息队列mq来讲,还处于百花齐放的年代。程序员
缓存系统,基本上解决一个存取问题,就万事大吉了,调用是同步的。对于消息队列来讲,就不太同样。它的使用场景多样,可靠级别多变,从生产端到消费端,过程是异步的。web
消息系统的设计要点,有不少。如今,很难有一个消息系统,可以兼顾下面提到的设计要点。它要是说能够,那就是母体在吹。redis
因此不少时候,如今流行的Kafka、RabbitMQ、RocketMQ等,会被同时使用。若是你在作相关方面的选型,下面这些技术点就是权衡之处。那句话叫什么来着:牝鸡司晨,唯家之索。spring
本文将针对这些mq,从总体上抽象一些共有特性。包括:协议、类型、消费方式、堆积能力、高可用、高可靠、高性能、扩展性和生态。若是你想要深刻某个mq,这里也有几篇关于kafka的文章。数据库
Kafka基础知识索引 系统讲解kafka的基础知识 360度测试:KAFKA会丢数据么?其高可用是否知足需求? 经过测试深刻探讨kafka业务场景的使用编程
经过增长副本,能够将数据的风险分散到多台机器上。这就须要在主分片出现问题时,可以从副本中找出一个做为新的主分片。有不少这样的协调工具,好比zk。也有的mq,本身去实现这个过程。缓存
有的模式就比较浪费资源了,好比rocketmq,使用standby从机进行高可用保证,出问题再顶上来。微信
单机高可靠
集群的高可靠方面,会有ack机制和多副本机制进行保证。对于单个节点来讲,断电或者主机异常,会是一个比较大的挑战。为了处理这种状况,须要有刷盘机制或者其余持久化机制。同时,数据的完整性校验也是须要的,这也是相似kafka这种消息系统,数据量大的时候,启动时间很是长的缘由。websocket
生产端
生产端除了要考虑buffer丢失的问题,还要考虑到一些发送错误的状况,包括与集群通讯的超时和重试处理。
消费端
消费端经过消息确认机制来保证消息已经被正确消费。因为其间会发生不少异常状况,因此大多数消息系统保证at least once语义。即确保消息至少被消费1次。
言外之意,消息是会重复的,消费者须要作到幂等,保证重复消费不会引发业务异常。
消费端一样会发生一些错误状况,有些mq能够在屡次消费失败后自动进入死信队列,有些mq须要自行设计topic进行规划。
消息从生产端发出,到消费者处理,其间的过程不能太长,对于使用拉模式来消费的mq来讲,就要加快轮询速度,并使用零拷贝一类的技术加快数据传输。
对于消息吞吐量来讲,是一个生产端、mq节点、消费端共同优化的结果。目前主要有如下手段:
异步化
消息采用异步发送的方式,发送端不用同步等待,加快了处理速度。
batch
采用批量发送的方式,减小网络传输的次数,方便进行数据压缩。通常是内存中缓冲一个buffer,若是buffer满了,或者到达了时间窗口,则进行一次传输。这可以显著增长传输速度,但处理不当容易丢失数据。
顺序IO
xjjdog已经在多篇文章提到,顺序性操做磁盘,比随机操做内存速度快的多。这也是kafka之类的消息队列速度快的缘由之一,但要注意主题的数量(想下为何)。
另外,还有其余手段。好比优化操做系统参数,使用分片增长并行度等。
除了普通发送的消息,还有一些特殊用途的消息。顺序性消息有全局有序和分区有序之分,通常用于有严格顺序要求的业务。经过业务的设计,能够规避全局有序这种很是耗性能的操做。
有些mq还支持定时消息(私觉得这种放业务系统更佳)。事务消息更加耗费性能,慎用。
还有一些mq,提供打tag、进行消息过滤的功能。好比订单信息发送到一个topic,消费者只订阅相关商品的订单,某些有求隔离的状况,很是有用。
推模式的实时性更好一些,但很差评估消费端能力,容易将其压垮。同时,处理pub/sub,失败重试等,也有不少挑战。
这个传输协议,与功能关系不大。好比就有基于http协议的,或者redis协议,甚至websocket之上的stomp。
mqtt是物联网IoT的应用协议,你会发现一大坨基于它的消息队列。
堆积能力的体如今海量存储上,好比存放在数据库中(矛盾转移),挂载很是大的磁盘等。但别高兴的太早,大型集群的启动加载,以及故障再平衡,一般会花费比较长的时间。
堆积能力的另一个体现,就是对历史消息的清理。通常有两个策略:磁盘上线和过时清理,能够结合需求灵活设置。
这方面除了比较新的mq系统,都作的不错。
消息系统在目前的分布式系统中设计中,做用愈来愈大。它的使用场景,包括但不限于:
削峰 用于承接超出业务系统处理能力的请求,使业务平稳运行。这可以大量节约成本,好比某些秒杀活动,并非针对峰值设计容量。
缓冲 在服务层和缓慢的落地层做为缓冲层存在,做用与削峰相似,但主要用于服务内数据流转。好比批量短信发送。
解耦 项目尹始,并不能肯定具体需求。消息队列能够做为一个接口层,解耦重要的业务流程。只须要遵照约定,针对数据编程便可获取扩展能力。
冗余 消息数据可以采用一对多的方式,供多个毫无关联的业务使用。
健壮性 消息队列能够堆积请求,因此消费端业务即便短期死掉,也不会影响主要业务的正常进行。
根据消息的体量和用途,目前能够将分布式mq大致分为两类。
一类用于业务系统,保证极高的可靠性。要求不可以丢失消息,好比订单、支付等,有较高的SLA服务水准。这种状况,对mq的功能要求也比较多,包括消息的可查性。
另一类用于大数据相关的系统,典型的特色就是吞吐量很是大。异常状况下,丢失几条消息,无伤大雅。
但消息系统,可能关注的只是mq自己。怎么保证生产端、消费端、mq自己三者的可用性,是须要业务进行权衡的。
好比,前段时间xjjdog开源的okmq,就是用来解决一个特定场景的高可用问题。 开源一个kafka加强:okmq-1.0.0
做者简介:小姐姐味道 (xjjdog),一个不容许程序员走弯路的公众号。聚焦基础架构和Linux。十年架构,日百亿流量,与你探讨高并发世界,给你不同的味道。个人我的微信xjjdog0,欢迎添加好友,进一步交流。