rocketmq代码解析(RocketMQ架构技术分享五)

基于DLedger技术的原理

DLedger技术实际上首先他自己就有一个CommitLog机制,你把数据交给他,他会写入CommitLog磁盘文件里去,这是他能干的第一件事情。

所以首先我们在下面的图里可以看到,如果基于DLedger技术来实现Broker高可用架构,实际上就是用DLedger先替换掉原来Broker自己管理的CommitLog,由DLedger来管理CommitLog。

然后Broker还是可以基于DLedger管理的CommitLog去构建出来机器上的各个ConsumeQueue磁盘文件。

rocketmq代码解析(RocketMQ架构技术分享五)(1)

1、DLedger是如何基于Raft协议选举Leader Broker的?

简单来说,三台Broker机器启动的时候,他们都会投票自己作为Leader,然后把这个投票发送给其他Broker。

我们举一个例子,Broker01是投票给自己的,Broker02是投票给自己的,Broker03是投票给自己的,他们都把自己的投票发送给了别人。

此时在第一轮选举中,Broker01会收到别人的投票,他发现自己是投票给自己,但是Broker02投票给Broker02自己,Broker03投票给Broker03自己,似乎每个人都很自私,都在投票给自己,所以第一轮选举是失败的。

接着每个人会进入一个随机时间的休眠,比如说Broker01休眠3秒,Broker02休眠5秒,Broker03休眠4秒。

此时Broker01必然是先苏醒过来的,他苏醒过来之后,直接会继续尝试投票给自己,并且发送自己的选票给别人。

接着Broker03休眠4秒后苏醒过来,他发现Broker01已经发送来了一个选票是投给Broker01自己的,此时他自己因为没投票,所以会尊重别人的选择,就直接把票投给Broker01了,同时把自己的投票发送给别人。

Broker02醒来跟Broker03一样,此时所有人都会收到三张投票,都是投给Broker01的,那么Broker01收到了大多数的投票,就会当选为Leader。

这就是Raft协议中选举leader算法的简单描述,简单来说,他确保有人可以成为Leader,核心机制就是一轮选举不出来Leader的话,就让大家随机休眠一下,先苏醒过来的人会投票给自己,其他人苏醒过后发现自己收到选票了,就会直接投票给那个人。

2、DLedger是如何基于Raft协议进行多副本同步的?

数据同步会分为两个阶段,一个是uncommitted阶段,一个是commited阶段。

首先Leader Broker上的DLedger收到一条数据之后,会标记为uncommitted状态,然后他会通过自己的DLedgerServer组件把这个uncommitted数据发送给Follower Broker的DLedgerServer。

接着Follower Broker的DLedgerServer收到uncommitted消息之后,必须返回一个ack给Leader Broker的DLedgerServer,然后如果Leader Broker收到超过半数的Follower Broker返回ack之后,就会将消息标记为committed状态。

然后Leader Broker上的DLedgerServer就会发送commited消息给Follower Broker机器的DLedgerServer,让他们也把消息标记为comitted状态。

RocketMQ高性能底层技术1、RocketMQ 是如何基于Netty扩展出高性能网络通信架构的?

比如对于处理发送消息请求而言,就会把请求转交给SendMessage线程池,而且如果大家还有一点点印象的话,其实在之前讲集群部署的时候,我们讲到过这个SendMessage线程是可以配置的,你配置的越多,自然处理消息的吞吐量越高。

rocketmq代码解析(RocketMQ架构技术分享五)(2)

为什么这套网络通信框架会是高性能以及高并发的?

1、Reactor主线程在端口上监听Producer建立连接的请求,建立长连接

2、Reactor线程池并发的监听多个连接的请求是否到达

3、Worker请求并发的对多个请求进行预处理

4、业务线程池并发的对多个请求进行磁盘读写业务操作

2、基于mmap技术 pagecache技术实现高性能的文件读写

首先,RocketMQ底层对CommitLog、ConsumeQueue之类的磁盘文件的读写操作,基本上都会采用mmap技术来实现。如果具体到代码层面,就是基于JDK NIO包下的MappedByteBuffer的map()函数,来先将一个磁盘文件(比如一个CommitLog文件,或者是一个ConsumeQueue文件)映射到内存里来,建立映射的时候,并没有任何的数据拷贝操作,其实磁盘文件还是停留在那里,只不过他把物理上的磁盘文件的一些地址和用户进程私有空间的一些虚拟内存地址进行了一个映射。

另外这里给大家说明白的一点是,这个mmap技术在进行文件映射的时候,一般有大小限制,在1.5GB~2GB之间,所以RocketMQ才让CommitLog单个文件在1GB,ConsumeQueue文件在5.72MB,不会太大。接着就可以对这个MappedByteBuffer执行写入操作了,写入的时候他会直接进入PageCache中,然后过一段时间之后,由os的线程异步刷入磁盘中,此时才会发生一次拷贝。

接着如果我们要从磁盘文件里读取数据呢?那么此时就会判断一下,当前你要读取的数据是否在PageCache里?如果在的话,就可以直接从PageCache里读取了!但是如果PageCache里没有你要的数据,那么此时就会从磁盘文件里加载数据到PageCache中去,也只会发生一次拷贝,如下图

rocketmq代码解析(RocketMQ架构技术分享五)(3)

通过上述优化,才真正能实现一个效果,就是写磁盘文件的时候都是进入PageCache的,保证写入高性能;同时尽可能多地通过mmap madvise的映射后预热机制,把磁盘文件里的数据尽可能多的加载到PageCache里来,后续对CosumeQueue、CommitLog进行读取的时候,才能尽可能从内存里读取数据。

,

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com

    分享
    投诉
    首页