前言

hello小伙伴们,今天王子又来继续和大家聊RocketMQ了,之前的文章我们一直说Broker的主从切换是可以基于Dledger实现自动切换的,那么小伙伴们是不是很好奇它究竟是如何实现的呢?今天我们就来聊一聊这个话题。

首先我们回顾一下上一篇文章深入研究Broker是如何持久化的中,producer发送消息给Broker后,首先将消息写入到CommitLog日志文件中,然后会把具体的MessageQueue中消息的位置信息存储到ConsumeQueue中。

之后Broker为了实现高可用,是有一个Broker组的,包含Master和Slave,Master接收到数据同步给Slave,一旦出现故障,可以实现主从自动切换。

使用Dledger技术替换CommitLog

现在我们就开始聊聊Dledger是如何实现主从自动切换的。

首先我们要知道Dledger是个什么东西,实际上Dledger自己就有一套CommitLog机制,如果使用了它,它接到数据第一步就是写入自己的CommitLog。

所以,引入Dledger技术,其实就是使用Dledger的CommitLog来替换掉Broker自己的CommitLog。

然后Broker仍然可以基于Dledger的CommitLog,把消息的位置信息保存到ConsumeQueue中。

Dledger是怎么选举Leader的

了解了Dledger是干什么的,那接下来我们就来探索一下,它是如何选举Leader的。

实际上它是通过Raft协议来进行选举的,那Raft又是个什么东东,别急我们慢慢聊。

假设我们的一组Broker中有三台机器,它们之间首先要选择一个Leader,这需要发起一轮一轮的投票,三台机器互相投票最终确定出Leader。

在刚刚启动的时候,这三台机器都会投给自己一票,说:"我要当Leader,别跟老子抢",然后把这条消息通知给其他机器。

为了方便说明,我们把三台机器分别命名为A,B,C.

那么经过第一轮投票后,A,B,C分别给自己投了一票,并发送给了别人。

这个时候A接到消息一看,好家伙,每个人都投的自己,都很自私,那算了,这次投票直接无效。

接着,每个人开始一段随机时间的休眠,比如A休眠了3秒,B休眠了4秒,C休眠了5秒。

那么3秒过去了,A醒了,抓紧给自己投了一票,又发给别人了。

又过了1秒,B醒了,它也想给自己投票,但是它发现已经有人发给了它消息,现在A已经有一票了,这个时候B会尊重别人的选择,也把票投给A,然后发送给别人。

又过了1秒,C醒了,同样也想给自己投票,但是发现别人已经投了两票给A了,那这时候它也会直接尊重别人的选择,投票给A,然后发送给别人。

这个时候所有人都收到了投票,全是投票给A的,那么A就光荣上岗了。

选举的时候就是谁的票数多,谁就去当老大。

这就是Raft协议中选举Leader的简单解释,总结起来就是,假如一轮投票不能得到结果,那就每个人随机休眠一下,先醒过来的投给自己,后醒过来的尊重大多数人的意见

依靠这种方式的投票,几轮下来就能选出一个Leader了。

当然,职位越高,责任越大,选举出Leader后,所有的接收消息操作全都由Leader来负责了,Follower只能同步Leader的数据。

Dledger的数据同步机制

现在我们了解了Dledger的投票选举机制,那么Broker接收到消息后,是如何基于Dledger实现数据同步的呢?

同样,Dledger也是通过Raft协议进行多副本同步的,简单来讲,数据同步分为两个阶段,uncommitted阶段和committed阶段

首先,当Leader接到消息数据后,会先标记消息为uncommitted状态,然后通过Dledger的组件把uncommitted状态的消息发送给Follower上的DledgerServer。

接着Follower接到消息后,会发送一个ack给Leader上的DledgerServer,然后如果Leader发现超过半数的Follower已经给自己返回了ack,那么就认为同步成功了,这时候把状态改为committed。

然后再发消息给Follower,将Follower上的状态也改为committed。

这就是基于Dledger的数据同步机制。

总结

到这里,关于Dledger如何实现主从自动切换的问题我们已经聊完了。

可能有的小伙伴会问,如果Leader宕机了,它是怎么实现自动切换的,好像还是没有说啊。

其实我们只要明白了Dledger是如何通过Raft协议进行选举的就很容易能够猜测出这个问题的答案。

Leader宕机后,自然是剩余的Follower重新发起新的一轮的选举了,然后还是按照老规矩,最后一定会选出一个Leader。

新的消息就由新选举出来的Leader来接收就可以了。

同时,由于数据同步是分为两阶段同步的,超过半数的机器返回ack才会认为是同步成功。

所以就算是在同步过程中Leader宕机了,其实Follower中已经同步了消息,只不过状态是uncommitted而已,新的Leader可以根据这些uncommitted的消息进行数据的恢复操作,更改消息状态为commited。

好了,这下子相信小伙伴们就能更好的理解Dledger了吧,那今天的文章就到这里了,下次见。

往期文章推荐:

什么是消息中间件?主要作用是什么?

常见的消息中间件有哪些?你们是怎么进行技术选型的?

你懂RocketMQ 的架构原理吗?

聊一聊RocketMQ的注册中心NameServer

Broker的主从架构是怎么实现的?

RocketMQ生产部署架构如何设计

RabbitMQ和Kafka的高可用集群原理

RocketMQ的发送模式和消费模式

讨论一下秒杀系统的技术难点与解决方案

秒杀系统中的扣减库存和流量削峰

深入研究RocketMQ生产者发送消息的底层原理

深入研究Broker是如何持久化的

Dledger的是如何实现主从自动切换的的更多相关文章

  1. java使用Redis7--分布式存储并实现sentinel主从自动切换

    前面实现了分布式存储,也实现了sentinel单点故障时主从自动切换,现在还需要一种机制,实现分布式存储下,单点故障时的主从自动切换. Server配置 # cd /usr/redis/src/tes ...

  2. 【转】双机高可用、负载均衡、MySQL(读写分离、主从自动切换)架构设计

    架构简介 前几天网友来信说帮忙实现这样一个架构:只有两台机器,需要实现其中一台死机之后另一台能接管这台机器的服务,并且在两台机器正常服务时,两台机器都能用上.于是设计了如下的架构.此架构主要是由kee ...

  3. 双机高可用、负载均衡、MySQL(读写分离、主从自动切换)架构设计

    前几天网友来信说帮忙实现这样一个架构:只有两台机器,需要实现其中一台死机之后另一台能接管这台机器的服务,并且在两台机器正常服务时,两台机器都能用上.于是设计了如下的架构. 架构简介 此架构主要是由ke ...

  4. redis哨兵主从自动切换

    1.用的是TP5框架,改写框架自带的redis类 thinkphp/library/think/cache/driver/Redis.php //两台服务器都配置好了监控哨兵 //主从配置要设置好密码 ...

  5. 利用Redis Sentinel实现redis主从自动切换

    redis主从配置很简单,只需要在slave的配置里加slaveof 192.168.0.100 6379(master的ip和端口) 如果master有密码再设置 masterauth passwo ...

  6. mysql mha 主从自动切换 高可用

    mha(Master High Availability)目前在MySQL多服务器(超过二台),高可用方面是一个相对成熟的解决方案. 一,什么是mha,有什么特性 1. 主服务器的自动监控和故障转移 ...

  7. Redis集群_3.redis主从自动切换Sentinel(转)

    Redis SentinelSentinel(哨兵)是用于监控redis集群中Master状态的工具,其已经被集成在redis2.4+的版本中 一.Sentinel作用:1):Master状态检测 2 ...

  8. java使用Redis6--sentinel单点故障主从自动切换

    Redis SentinelSentinel(哨兵)是用于监控redis集群中Master状态的工具,其已经被集成在redis2.4+的版本中 一.Sentinel作用:1):Master状态检测 2 ...

  9. Keepalived与MySQL互为主从自动切换配置

    为解决Mysql数据库单点问题,实现两台MySQL数据库互为主备,双向replication.当一Master出现问题,则将Slave切换为Master继续工作. 环境说明 系统版本:CentOS L ...

随机推荐

  1. 【python系统学习17】python中的文件读写

    python中的文件读写 文件读写,是Python代码调用电脑文件的主要功能,能被用于读取和写入文本.音频片段.Excel文档.邮件以及任何保存在电脑上的东西. 可使用python批量的操作本地文件, ...

  2. python数据类型和运算符

    一.python类型判断 type,isinstance type(变量或常量):返回数据类型 a = 23.3print(type(a))b = 2e3print(b, type(b))输出: &l ...

  3. HTTP系列1番外之头部字段大全

    原文地址:https://www.jianshu.com/p/6e86903d74f7 常用标准请求头 字段 属性 举例 Accept 设置接受的内容类型 Accept: text/plain Acc ...

  4. springboot之对之前的补充

    Spring Cloud 初级 一. Spring Boot 回顾   1 什么是 Spring Boot?   Spring Boot 是在 Spring 的基础之上产生的(确切的说是在 Sprin ...

  5. SwiftUI - Grid View 的实现方法,逐步剖析助你实现

    简介 在当前正式 SwiftUI 版本而言,很多控件都是缺少的.比如在 UIKit 框架里有 UICollectionView 组件,可以很方便地做 Gird 格子类型的视图.但是在 SwiftUI ...

  6. PageObject六大原则

    The public methods represent the services that the page offers 公共方法表示页面提供的服务 Try not to expose the i ...

  7. 还在写if/else if ... ?

    在日常开发中,我们经常会写出很多 if  else if ... 很多看起来又长又糟糕的代码, 那么策略模式你该去get 了. 点我查看哦!

  8. Codeforces 1337C Linova and Kingdom

    题意 给你一颗有根树,你要选择\(k\)个点,最大化\(\sum_{i \in S} val_i\),其中\(S\)是被选点的集合,\(val_i\)等于节点\(i\)到根的路径上未被选择点的个数. ...

  9. 【Gin-API系列】守护进程和平滑重启(八)

    生产环境的API服务我们都会部署在Linux服务器上,为了不受终端状态的影响,启动服务的时候会让服务在后台运行.那么如何让服务在后台运行呢,目前有2种常见的方法. 1.nohub 运行 表示忽略SIG ...

  10. spring cloud 通过zuul网关去请求的时候报404的几个原因。

    spring cloud 中 zuul 网关的那些坑: 1.检查你的服务是否正常启动. 2.检查你的服务是否正常注册到注册中心. 3.zuul网关的路由规则是会把你注册在注册中心的serviceId ...