分布式消息队列.docx
《分布式消息队列.docx》由会员分享,可在线阅读,更多相关《分布式消息队列.docx(29页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、分布式消息队列vincentchma腾讯IEG后台开发工程师一、消息队列的演进分布式消息队列中间件是是大型分布式系统中常见的中间件。消息队列主要解决应用耦合、异步消息、流量削锋等问题具有高性能、高可用、可伸缩以及最终一致性等特点。消息队列已经逐渐成为企业应用系统内部通信的核心手段使用较多的消息队列有RabbitMQ、RocketMQ、ActiveMQ、Kafka、ZeroMQ、Pulsar等此外利用数据库如Redis、MySQL等可以实现消息队列的局部根本功能。1.基于OS的MQ单机消息队列可以通过操作系统原生的进程间通信机制来实现如消息队列、分享内存等。比方我们可以在分享内存中维护一个双端队
2、列消息产出进程不停地往队列里添加消息同时消息消费进程不断地从队尾有序地取出这些消息。添加消息的任务我们称为producer而取出并使用消息的任务我们称之为consumer。这种形式在早期单机多进程形式中比拟常见比方IO进程把收到的网络恳求存入本机MQ任务处理进程从本机MQ中读取任务并进展处理。单机MQ易于实现但是缺点也很明显因为依赖于单机OS的IPC机制所以无法实现分布式的消息传递并且消息队列的容量也受限于单机资源。2.基于DB的MQ即使用存储组件如Mysql、Redis等存储消息然后在消息的消费侧以及消费侧实现消息的消费消费逻辑进而实现MQ功能。以Redis为例可以使用Redis自带的lis
3、t实现。Redislist使用lpush命令从队列左边插入数据使用rpop命令从队列右边取出数据。与单机MQ相比该方案至少知足了分布式但是仍然带有很多无法承受的缺陷。热key性能问题不管是用codis还是twemproxy这种集群方案对某个队列的读写恳求最终都会落到同一台redis实例上并且无法通过扩容来解决问题。假如对某个list的并发读写非常高就产生了无法解决的热key严重可能导致系统崩溃没有消费确认机制每当执行rpop消费一条数据那条消息就被从list中永久删除了。假如消费者消费失败这条消息也没法找回了。不支持多订阅者一条消息只能被一个消费者消费rpop之后就没了。假如队列中存储的是应用
4、的日志对于同一条消息监控系统需要消费它来进展可能的报警BI系统需要消费它来绘制报表链路追踪需要消费它来绘制调用关系这种场景redislist就没方法支持了不支持二次消费一条消息rpop之后就没了。假如消费者程序运行到一半发当代码有bug修复之后想从头再消费一次就不行了。针对上述缺点redis5.0开场引入stream数据类型它是专门设计成为消息队列的数据构造借鉴了很多kafka的设计但是随着很多分布式MQ组件的出现仍然显得不够友好毕竟Redis天生就不是用来做消息转发的。3.专用分布式MQ中间件随着时代的开展一个真正的消息队列已经不仅仅是一个队列那么简单了业务对MQ的吞吐量、扩展性、稳定性、可
5、靠性等都提出了严苛的要求。因此专用的分布式消息中间件开场大量出现。常见的有RabbitMQ、RocketMQ、ActiveMQ、Kafka、ZeroMQ、Pulsar等等。二、消息队列设计要点消息队列本质上是一个消息的转发系统把一次RPC就可以直接完成的消息投递转换成屡次RPC间接完成这其中包含两个关键环节1.消息转储2.消息投递时机以及对象基于此消息队列的整体设计思路是确定整体的数据流向如producer发送给MQMQ转发给consumerconsumer回复消费确认消息删除、消息备份等。利用RPC将数据流串起来最好基于现有的RPC框架尽量做到无状态方便程度扩展。存储选型综合考虑性能、可靠性
6、以及开发维护本钱等众多因素。消息投递消费形式push、pull。消费关系维护单播、多播等可以利用zk、configserver等保存消费关系。高级特性如可靠投递重复消息顺序消息等很多高级特性之间是互相制约的关系这里要充分结合应用场景做出取舍。1.MQ根本特性RPC通信MQ组件要实现以及消费者和消费者进展通信功能这里涉及到RPC通信问题。消息队列的RPC以及普通的RPC没有本质区别。对于负载平衡、效劳发现、序列化协议等等问题都可以借助现有RPC框架来实现防止重复造轮子。存储系统存储可以做成很多方式。比方存储在内存里存储在分布式KV里存储在磁盘里存储在数据库里等等。但归结起来主要有持久化以及非持久
7、化两种。持久化的形式能更大程度地保证消息的可靠性如断电等不可抗外力并且理论上能承载更大限度的消息堆积外存的空间远大于内存。但并不是每种消息都需要持久化存储。很多消息对于投递性能的要求大于可靠性的要求且数量极大如日志。这时候消息不落地直接暂存内存尝试几次failover最终投递出去也未尝不可。常见的消息队列普遍两种形式都支持。从速度来看理论上文件系统分布式KV持久化分布式文件系统数据库而可靠性却相反。还是要从支持的业务场景出发作出最合理的选择。高可用MQ的高可用依赖于RPC以及存储的高可用。通常RPC效劳自身都具有效劳自动发现负载平衡等功能保证了其高可用。存储的高可用例如Kafka使用分区加主备
8、形式保证每一个分区内的高可用性也就是每一个分区至少要有一个备份且需要做数据的同步。推拉模型push以及pull模型各有利弊两种形式也都有被市面上成熟的消息中间件选用。1.慢消费慢消费是push模型最大的致命伤假如消费者的速度比发送者的速度慢很多会出现两种恶劣的情况1.消息在broker的堆积。假设这些消息都是有用的无法丢弃的消息就要一直在broker端保存。2.broker推送给consumer的消息consumer无法处理此时consumer只能回绝或返回错误。而pull形式下consumer可以按需消费不用担忧自己处理不了的消息来骚扰自己而broker堆积消息也会相对简单无需记录每一个要发
9、送消息的状态只需要维护所有消息的队列以及偏移量就可以了。所以对于慢消费消息量有限且到来的速度不均匀的情况pull形式比拟适宜。2.消息延迟与忙等这是pull形式最大的短板。由于主动权在消费方消费方无法准确地决定何时去拉取最新的消息。假如一次pull取到消息了还可以继续去pull假如没有pull取到那么需要等待一段时间重新pull。消息投放时机即消费者应该在什么时机消费消息。一般有以下三种方式攒够了一定数量才投放。到达了一定时间就投放。有新的数据到来就投放。至于怎样选择也要结合详细的业务场景来决定。比方对及时性要求高的数据可用采用方式3来完成。消息投放对象不管是JMS标准中的Topic/Queu
10、eKafka里面的Topic/Partition/ConsumerGroup还是AMQP如RabbitMQ的Exchange等等都是为了维护消息的消费关系而抽象出来的概念。本质上消息的消费无外乎点到点的一对一单播或者一对多播送。另外比拟特殊的情况是组间播送、组内单播。比拟通用的设计是不同的组注册不同的订阅支持组间播送。组内不同的机器假如注册一个一样的ID那么单播假如注册不同的ID(如IP地址端口)那么播送。例如pulsar支持的订阅模型有Exclusive独占型一个订阅只能有一个消息者消费消息。Failover灾备型一个订阅同时只有一个消费者可以有多个备份消费者。一旦主消费者故障那么备份消费者
11、接收。不会出现同时有两个活泼的消费者。Shared分享型一个订阅中同时可以有多个消费者多个消费者分享Topic中的消息。Key_Shared键分享型多个消费者各取一局部消息。通常会在公共存储上维护播送关系如configserver、zookeeper等。2.队列高级特性常见的高级特性有可靠投递、消息丧失、消息重复、事务等等他们并非是MQ必备的特性。由于这些特性可能是互相制约的所以不可能完全兼顾。所以要按照业务的需求来仔细衡量各种特性实现的本钱、利弊最终做出最为合理的设计。可靠投递怎样保证消息完全不丧失直观的方案是在任何不可靠操作之前先将消息落地然后操作。当失败或不知道结果比方超时时消息状态是待
12、发送定时任务不停轮询所有待发送消息最终一定可以送达。但是这样必然导致消息可能会重复并且在异常情况下消息延迟较大。例如producer往broker发送消息之前需要做一次落地。恳求到server后server确保数据落地后再告诉客户端发送成功。支持播送的消息队列需要对每个接收者持久化一个发送状态直到所有接收者都确认收到才可删除消息。即对于任何不能确认消息已送达的情况都要重推消息。但是随着而来的问题就是消息重复。在消息重复以及消息丧失之间无法兼顾要结合应用场景做出取舍。消费确认当broker把消息投递给消费者后消费者可以立即确认收到了消息。但是有些情况消费者可能需要再次接收该消息比方收到消息、但是
13、处理失败即消费者主动要求重发消息。所以要允许消费者主动进展消费确认。顺序消息对于push形式要求支持分区且单分区只支持一个消费者消费并且消费者只有确认一个消息消费后才能push另外一个消息还要发送者保证发送顺序唯一。对于pull形式比方kafka的做法producer对应partition并且单线程。consumer对应partition消费确认或者批量确认单线程消费。但是这样也只是实现了消息的分区有序性并不一定全局有序。总体而言要求消息有序的MQ场景还是比拟少的。三、KafkaKafka是一个分布式发布订阅消息系统。它以高吞吐、可持久化、可程度扩展、支持流数据处理等多种特性而被广泛使用如St
14、orm、Spark、Flink。在大数据系统中数据需要在各个子系统中高性能、低延迟的不停流转。传统的企业消息系统并不是非常合适大规模的数据处理但Kafka出现了它可以高效的处理实时消息以及离线消息降低编程复杂度使得各个子系统可以快速高效的进展数据流转Kafka承当高速数据总线的作用。kafka根底概念BrokerKafka集群包含一个或者多个效劳器这种效劳器被称为broker。TopicTopic在逻辑上可以被认为是一个queue每条消费都必须指定它的Topic可以简单理解为必须指明把这条消息放进哪个queue里。为了使得Kafka的吞吐率可以线性进步物理上把Topic分成一个或者多个Part
15、ition每个Partition在物理上对应一个文件夹该文件夹下存储这个Partition的所有消息以及索引文件。PartitionParition是物理上的概念每个Topic包含一个或者多个Partition。Producer负责发布消息到Kafkabroker。Consumer消息消费者向Kafkabroker读取消息的客户端。ConsumerGroup每个Consumer属于一个特定的ConsumerGroup可为每个Consumer指定groupname假设不指定groupname那么属于默认的group。kafka实现原理6一个典型的kafka集群包含假设干Producer假设干个B
16、rokerkafka支持程度扩展、假设干个ConsumerGroup和一个zookeeper集群。Producer使用push形式将消息发布到broker。consumer使用pull形式从broker订阅并消费消息。多个broker协同工作producer以及consumer部署在各个业务逻辑中。kafka通过zookeeper管理集群配置及效劳协同。这样就组成了一个高性能的分布式消息发布以及订阅系统。Kafka有一个细节是以及其他mq中间件不同的点producer发送消息到broker的经过是push而consumer从broker消费消息的经过是pull主动去拉数据。而不是broker把
17、数据主动发送给consumer。Producer发送消息到broker时会根据Paritition机制选择将其存储到哪一个Partition。假如Partition机制设置合理所有消息可以均匀分布到不同的Partition里这样就实现了负载平衡。假如一个Topic对应一个文件那这个文件所在的机器I/O将会成为这个Topic的性能瓶颈而有了Partition后不同的消息可以并行写入不同broker的不同Partition里极大的进步了吞吐率。Kafka特点优点高性能单机测试能到达100wtps低延时消费以及消费的延时都很低e2e的延时在正常的cluster中也很低可用性高replicateisr
18、选举机制保证工具链成熟监控运维管理方案齐全生态成熟大数据场景必不可少kafkastream缺乏无法弹性扩容对partition的读写都在partitionleader所在的broker假如该broker压力过大也无法通过新增broker来解决问题扩容本钱高集群中新增的broker只会处理新topic假如要分担老topic-partition的压力需要手动迁移partition这时会占用大量集群带宽消费者新参加以及退出会造成整个消费组rebalance导致数据重复消费影响消费速度增加延迟partition太多会使得性能显著下降ZK压力大broker上partition太多让磁盘顺序写几乎退化成随
19、机写高吞吐机制顺序存取假如把消息以随机的方式写入到磁盘那么磁盘首先要做的就是寻址也就是定位到数据所在的物理地址在磁盘上就要找到对应柱面、磁头和对应的扇区这个经过相对内存来讲会消耗大量时间为了躲避随机读写带来的时间消耗kafka采用顺序写的方式存储数据。页缓存即使是顺序存取但是频繁的I/O操作仍然会造成磁盘的性能瓶颈所以kafka使用了页缓存以及零拷贝技术。当进程准备读取磁盘上的文件内容时操作系统会先查对待读取的数据是否在页缓存中假如存在那么直接返回数据进而防止了对物理磁盘的I/O操作假如没有命中那么操作系统会向磁盘提议读取恳求并将读取的数据页存入页缓存之后再将数据返回给进程。一个进程需要将数据
20、写入磁盘那么操作系统也会检测数据对应的页是否在页缓存中假如不存在那么会先在页缓存中添加相应的页最后将数据写入对应的页。被修改正后的页也就变成了脏页操作系统会在适宜的时间把脏页中的数据写入磁盘以保持数据的一致性。Kafka中大量使用了页缓存这是Kafka实现高吞吐的重要因素之一。固然消息都是先被写入页缓存然后由操作系统负责详细的刷盘任务的但在Kafka中同样提供了同步刷盘及连续性强迫刷盘(fsync),可以通过参数来控制。同步刷盘可以保证消息的可靠性防止因为宕机导致页缓存数据还未完成同步时造成的数据丧失。但是实际使用上我们没必要去考虑这样的因素和这种问题带来的损失消息可靠性可以由多副本来解决同步
21、刷盘会带来性能的影响。页缓存的好处I/OScheduler会将连续的小块写组装成大块的物理写进而进步性能I/OScheduler会尝试将一些写操作重新按顺序排好进而减少磁头挪动时间充分利用所有空闲内存非JVM内存读操作可以直接在PageCache内进展假如消费以及消费速度相当甚至不需要通过物理磁盘交换数据假如进程重启JVM内的Cache会失效但PageCache仍然可用。零拷贝零拷贝技术可以减少CPU的上下文切换以及数据拷贝次数。常规方式应用程序一次常规的数据恳求经过发生了4次拷贝2次DMA以及2次CPU而CPU发生了4次的切换。DMA简单理解就是在进展I/O设备以及内存的数据传输的时候数据搬
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 分布式 消息 队列
限制150内