DLedger是如何基于Raft协议进行多副本同步的?
数据会分为两个阶段:
1.uncommitted阶段
Leader Broker上的DLedger收到一条数据后,会标记为uncommitted状态,然后通过自己的DLedgerServer组件把这个uncommitted数据发送给FollowerBroker的DLedgerServer。
FollowerBroker的DLedgerServer接收到数据后返回一个ack给Leader Broker的DLedgerServer。
2.committed阶段
Leader Broker的DLedgerServer收到超过半数的ack后,会将数据标记为committed。然后将committed消息发送给 FollowerBroker的DLedgerServer,让他们也标记为committed。
对于一个消费组而言,获取到一条消息,每台机器都会获取到这条消息吗?
1.集群模式
一个消费组获取到一条消息,只会交给组内的一台机器去处理。
2.广播模式
切换广播模式:consumer.setMessageModel(MessageModel.BROADCASTING)。
组内每台机器都会获取到消息
消费者怎么决定是从Master还是Slave拉取消息
一般消费者都会先去Master拉取消息,如果Master Broker觉得自己负载过高,就会告诉消费者机器,下次可以从Slave Broker拉。
消费者在拉取消息的时候,第一步大量的频繁获取ConsumerQueue文件,因为该文件主要存放消息的offset,所以每个文件很小,30万条消息的offset只有大概5.72MB,可以被os缓存在内存cache中。所以第一步读取offset的时候几乎和从内存中读没什么两样。
RocketMQ如何基于Netty扩展出高性能网络通信架构
Brocker有一个Reactor主线程,负责监听一个端口。一个Producer现在想跟Broker建立一个TCP长连接(按照TCP的规矩发送)。
Reactor在端口上监听到这个Producer发来的请求:
长连接建立的证明就是SocketChannel。
Reactor建立好的每个连接SocketChannel,都会交给这个Reactor的线程池中的一个线程监听。
Worker线程池做预处理工作,预处理是请求被正式处理前要做一些准备工作(SSL加密验证,编码解码,连接空闲检查等)。Reactor的线程会把请求交给Worker线程池中的一个线程。
Worker线程将请求交给SendMessage线程池。
基于mmap内存映射实现CommitLog磁盘文件的高性能读写
RocketMQ底层对CommitLog等磁盘文件的读写操作,都采用mmap技术,代码层面就是JDK NIO包下的MappedByteBuffer的map()函数,先将一个磁盘文件映射到内存里来。