分布式消息队列.docx

上传人:安*** 文档编号:73267560 上传时间:2023-02-17 格式:DOCX 页数:29 大小:31.44KB
返回 下载 相关 举报
分布式消息队列.docx_第1页
第1页 / 共29页
分布式消息队列.docx_第2页
第2页 / 共29页
点击查看更多>>
资源描述

《分布式消息队列.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设备以及内存的数据传输的时候数据搬

22、运的工作全部交给DMA控制器而CPU不再介入任何与数据搬运相关的事情零拷贝的方式通过零拷贝优化CPU只发生了2次的上下文切换以及3次数据拷贝。批量发送Kafka允许进展批量发送消息先将消息缓存在内存中然后一次恳求批量发送出去这种策略将大大减少效劳端的I/O次数。数据压缩Kafka还支持对消息集合进展压缩Producer可以通过GZIP或者Snappy格式对消息集合进展压缩Producer压缩之后在Consumer需进展解压固然增加了CPU的工作但在对大数据处理上瓶颈在网络上而不是CPU所以这个本钱很值得。高可用机制副本Producer在发布消息到某个Partition时先通过ZooKeeper

23、找到该Partition的Leader然后无论该Topic的ReplicationFactor为多少Producer只将该消息发送到该Partition的Leader。Leader会将该消息写入其本地Log。每个Follower都从Leaderpull数据。这种方式上Follower存储的数据顺序与Leader保持一致。Follower在收到该消息后向Leader发送ACK并把消息写入其Log。一旦Leader收到了ISR中的所有Replica的ACK该消息就被认为已经commit了Leader将增加HW并且向Producer发送ACK。为了进步性能每个Follower在接收到数据后就立马向L

24、eader发送ACK而非等到数据写入Log中。因此对于已经commit的消息Kafka只能保证它被存于多个Replica的内存中而不能保证它们被持久化到磁盘中也就不能完全保证异常发生后该条消息一定能被Consumer消费。Consumer读消息也是从Leader读取只有被commit过的消息才会暴露给Consumer。KafkaReplication的数据流如下列图所示对于Kafka而言定义一个Broker是否“活着包含两个条件一是它必须维护与ZooKeeper的session这个通过ZooKeeper的Heartbeat机制来实现。二是Follower必须可以及时将Leader的消息复制过来

25、不能“落后过多。Leader会跟踪与其保持同步的Replica列表该列表称为ISR即in-syncReplica。假如一个Follower宕机或落后过多Leader将把它从ISR中移除。这里所描绘的“落后过多指Follower复制的消息落后于Leader后的条数超过预定值或Follower超过一定时间未向Leader发送fetch恳求。Kafka的复制机制既不是完全的同步复制也不是单纯的异步复制。完全同步复制要求所有能工作的Follower都复制完这条消息才会被认为commit这种复制方式极大的影响了吞吐率高吞吐率是Kafka非常重要的一个特性。异步复制方式下Follower异步的从Leade

26、r复制数据数据只要被Leader写入log就被认为已经commit这种情况下假如Follower都复制完都落后于Leader而假如Leader突然宕机那么会丧失数据。而Kafka的这种使用ISR的方式那么很好的平衡了确保数据不丧失和吞吐率。Follower可以批量的从Leader复制数据这样极大的进步复制性能批量写磁盘极大减少了Follower与Leader的差距。一条消息只有被ISR里的所有Follower都从Leader复制过去才会被认为已提交。这样就防止了局部数据被写进了Leader还没来得及被任何Follower复制就宕机了而造成数据丧失Consumer无法消费这些数据。而对于Prod

27、ucer而言它可以选择是否等待消息commit。这种机制确保了只要ISR有一个或者以上的Follower一条被commit的消息就不会丧失。故障恢复Leader故障leader发生故障后会从ISR中选出一个新的leader之后为保证多个副本之间的数据一致性其余的follower会先将各自的log文件高于HW的局部截掉然后从新的leader同步数据。注意这只能保证副本之间的数据一致性并不能保证数据不丧失或不重复。Kafka在ZooKeeper中动态维护了一个ISRin-syncreplicas这个ISR里的所有Replica都跟上了leader只有ISR里的成员才有被选为Leader的可能。在这

28、种形式下对于f1个Replica一个Partition能在保证不丧失已经commit的消息的前提下容忍f个Replica的失败。LEO每个副本最大的offset。HW消费者能见到的最大的offsetISR队列中最小的LEO。Follower故障follower发生故障后会被临时踢出ISR集合待该follower恢复后follower会读取本地磁盘记录的上次的HW并将log文件高于HW的局部截取掉从HW开场向leader进展同步数据操作。等该follower的LEO大于等于该partition的HW即follower追上leader后就可以重新参加ISR了。扩展性由于Broker存储着特定分区的

29、数据因此不管是Broker还是分区的扩缩容都是比拟复杂的属于典型的“有状态效劳扩缩容问题。接下来我们看一下Pulsar是怎么针对kafka的缺乏进展优化的。四、PulsarApachePulsar是Apache软件基金会顶级工程是下一代云原生分布式消息流平台集消息、存储、轻量化函数式计算为一体。采用计算与存储别离架构设计支持多租户、持久化存储、多机房跨区域数据复制具有强一致性、高吞吐、低延时及高可扩展性等流数据存储特性。在消息领域Pulsar是第一个将存储计算别离云原生架构落地的开源工程。效劳以及存储别离在kafka的根底上把数据存储功能从Broker中别离出来Broker仅面向消费者、消费者

30、提供数据读写才能但其自身并不存储数据。而在Broker层下面使用Bookie作为存储层承当详细的数据存储职责。在Pulsar中broker的含义以及kafka中的broker是一致的就是一个运行的Pulsar实例提供多个分区的读写效劳。由于broker层不在承当数据存储职责使得Broker层成为无状态效劳。这样一来Broker的扩缩容就变得非常简单。相比之下效劳存储集于一体的Kafka就非常难以扩容。Broker以及Bookie互相独立方便实现独立的扩展和独立的容错Broker无状态便于快速上、下线更加合适于云原生场景分区存储不受限于单个节点存储容量Bookie数据分布均匀分片存储1.在Kaf

31、ka分区Partition概念的根底上按照时间或者大小把分区切分成分片Segment。2.同一个分区的分片分散存储在集群中所有的Bookie节点上。3.同一个分片拥有多个副本副本数量可以指定存储于不同的Bookie节点。Pulsar性能以及Kafka一样Pulsar也使用了顺序读写以及零拷贝等技术来进步系统的性能。此外Pulsar还设计了分层缓存机制在效劳层以及存储层都做了分层缓存来进步性能。消费者发送消息时调用Bookie层写入消息时同时将消息写入broker缓存中。实时消费时追尾读首先从broker缓存中读取数据防止从持久层bookie中读取进而降低投递延迟。读取历史消息追赶读场景中boo

32、kie会将磁盘消息读入bookie读缓存中进而防止每次都读取磁盘数据降低读取延时。Pulsar扩展性分片存储解决了分区容量受单节点存储空间限制的问题当容量不够时可以通过扩容Bookie节点的方式支撑更多的分区数据也解决了分区数据倾斜问题数据可以均匀的分配在Bookie节点上。Broker以及Bookie灵敏的容错和无缝的扩容才能让ApachePulsar具备非常高的可用性实现了无限制的分区存储。Broker扩展在Pulsar中Broker是无状态的可以通过增加节点的方式实现快速扩容。当需要支持更多的消费者或者消费者时可以简单地添加更多的Broker节点来知足业务需求。Pulsar支持自动的分区

33、负载平衡在Broker节点的资源使用率到达阈值时会将负载迁移到负载较低的Broker节点。新增Broker节点时分区也将在Brokers中做平衡迁移一些分区的所有权会转移到新的Broker节点。Bookie扩展存储层的扩容通过增加Bookie节点来实现。通过资源感悟以及数据放置策略流量将自动切换到新的ApacheBookie中整个经过不会涉及到不必要的数据搬迁。即扩容时不会将旧数据从现有存储节点重新复制到新存储节点。如下图起始状态有四个存储节点Bookie1,Bookie2,Bookie3,Bookie4以Topic1-Part2为例当这个分区的最新的存储分片是SegmentX时对存储层扩容添

34、加了新的Bookie节点BookieX,BookieY那么当存储分片滚动之后新生成的存储分片SegmentX1,SegmentX2会优先选择新的Bookie节点BookieX,BookieY来保存数据。Pulsar可用性Broker容错如下列图假设当存储分片滚动到SegmentX时Broker2节点失败。此时消费者以及消费者向其他的Broker提议恳求这个经过会触发分区的所有权转移即将Broker2拥有的分区Topic1-Part2的所有权转移到其他的Broker(Broker3)。由于数据存储以及数据效劳别离所以新Broker接收分区的所有权时它不需要复制Partiton的数据。新的分区Ow

35、nerBroker3会产生一个新的分片SegmentX1,假如有新数据到来会存储在新的分片Segmentx1上不会影响分区的可用性。即当某个Broker实例故障时整个集群的消息存储才能仍然完好。此时集群只是丧失了特定分区的消息效劳只需要把这些分区的效劳权限分配给其他Broker即可。注意以及Kafka一样Pulsar的一个分区仍然只能由一个Broker提供效劳否那么无法保证消息的分区有序性。Bookie容错如下列图假设Bookie2上的Segment4损坏。BookieAuditor会检测到这个错误并进展复制修复。Bookie中的副本修复是Segment级别的多对多快速修复BookKeeper

36、可以从Bookie3以及Bookie4读取Segment4中的消息并在Bookie1处修复Segment4。假如是Bookie节点故障这个Bookie节点上所有的Segment会按照上述方式复制到其他的Bookie节点。所有的副本修复都在后台进展对Broker以及应用透明Broker会产生新的Segment来处理写入恳求不会影响分区的可用性。Pulsar其他特性基于上述的设计特点Pulsar提供了很多特性。读写别离Pulsar另外一个有吸引力的特性是提供了读写别离的才能读写别离保证了在有大量滞后消费磁盘IO会增加时不会影响效劳的正常运行尤其是不会影响到数据的写入。读写别离的才能由Bookie提

37、供简单讲一下Bookie存储涉及到的概念JournalsJournal文件包含了Bookie事务日志在Ledger(可以认为是分片的一局部)更新之前Journal保证描绘更新的事务写入到Non-volatile的存储介质上EntryloggerEntry日志文件管理写入的Entry来自不同ledger的entry会被聚合然后顺序写入Indexfiles每个Ledger都有一个对应的索引文件记录数据在Entry日志文件中的Offset信息。Entry的读写入经过下列图所示数据的写入流程数据首先会写入Journal写入Journal的数据会实时落到磁盘然后数据写入到MemtableMemtable

38、是读写缓存写入Memtable之后对写入恳求进展响应Memtable写满之后会Flush到EntryLogger以及IndexcacheEntryLogger中保存了数据Indexcache保存了数据的索引信息然后由后台线程将EntryLogger以及Indexcache数据落到磁盘。数据的读取流程假如是Tailingread恳求直接从Memtable中读取Entry假如是Catch-upread滞后消费恳求先读取Index信息然后索引从EntryLogger文件读取Entry。一般在进展Bookie的配置时会将Journal以及Ledger存储磁盘进展隔离减少Ledger对于Journal写

39、入的影响并且推荐Journal使用性能较好的SSD磁盘读写别离主要表达在写入Entry时Journal中的数据需要实时写到磁盘Ledger的数据不需要实时落盘通过后台线程批量落盘因此写入的性能主要受到Journal磁盘的影响读取Entry时首先从Memtable读取命中那么返回假如不命中再从Ledger磁盘中读取所以对于Catch-upread的场景读取数据会影响Ledger磁盘的IO对Journal磁盘没有影响也就不会影响到数据的写入。所以数据写入是主要是受Journal磁盘的负载影响不会受Ledger磁盘的影响。另外Segment存储的多个副本都可以提供读取效劳相比于主从副本的设计Apac

40、hePulsar可以提供更好的数据读取才能。通过以上分析ApachePulsar使用ApacheBookKeeper作为数据存储可以带来以下的收益支持将多个Ledger的数据写入到同一个Entrylogger文件可以防止分区膨胀带来的性能下降问题支持读写别离可以在滞后消费场景导致磁盘IO上升时保证数据写入的不受影响支持全部本读取可以充分利用存储副本的数据读取才能多种消费模型Pulsar提供了多种订阅方式来消费消息分为三种类型独占Exclusive故障切换Failover或者分享Share。Exclusive独占订阅在任何时间一个消费者组订阅中有且只有一个消费者来消费Topic中的消息。Fail

41、over故障切换多个消费者Consumer可以附加到同一订阅。但是一个订阅中的所有消费者只会有一个消费者被选为该订阅的主消费者。其他消费者将被指定为故障转移消费者。当主消费者断开连接时分区将被重新分配给其中一个故障转移消费者而新分配的消费者将成为新的主消费者。发生这种情况时所有未确认ack的消息都将传递给新的主消费者。Share分享订阅使用分享订阅在同一个订阅背后用户按照应用的需求挂载任意多的消费者。订阅中的所有消息以循环分发形式发送给订阅背后的多个消费者并且一个消息仅传递给一个消费者。当消费者断开连接时所有传递给它但是未被确认ack的消息将被重新分配以及组织以便发送给该订阅上剩余的剩余消费者

42、。多种ACK模型消息确认ACK的目的就是保证当发生故障后消费者可以从上一次停顿的地方恢复消费保证既不会丧失消息也不会重复处理已经确认ACK的消息。在Pulsar中每个订阅中都使用一个专门的数据构造游标Cursor来跟踪订阅中的每条消息确实认ACK状态。每当消费者在分区上确认消息时游标都会更新。Pulsar提供两种消息确认方法单条确认IndividualAck单独确认一条消息。被确认后的消息将不会被重新传递累积确认CumulativeAck通过累积确认消费者只需要确认它收到的最后一条消息上图讲明了单条确认以及累积确认的差异灰色框中的消息被确认并且不会被重新传递。对于累计确认M12之前的消息被标记为Acked。对于单独进展ACK仅确认消息M7以及M12在消费者失败的情况下除了M7以及M12之外其他所有消息将被重新传送。腾讯程序员视频号最新视频欢送点赞腾讯技术工程

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 技术资料 > 工程图纸

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知得利文库网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号-8 |  经营许可证:黑B2-20190332号 |   黑公网安备:91230400333293403D

© 2020-2023 www.deliwenku.com 得利文库. All Rights Reserved 黑龙江转换宝科技有限公司 

黑龙江省互联网违法和不良信息举报
举报电话:0468-3380021 邮箱:hgswwxb@163.com