持久化的唯一BrokerId

现阶段问题

在 RocketMQ 5.0.0 和 5.1.0 版本中,采用BrokerAddress作为Broker在Controller模式下的唯一标识。导致如下情景出现问题:

  • 在容器或者K8s环境下,每次Broker的重启或升级都可能会导致IP发生变化,导致之前的BrokerAddress留下的记录没办法和重启后的Broker联系起来,比如说ReplicaInfo, SyncStateSet等数据。

改进方案

在Controller侧采用BrokerName:BrokerId作为唯一标识,不再以BrokerAddress作为唯一标识。并且需要对BrokerId进行持久化存储,由于ClusterNameBrokerName都是启动的时候在配置文件中配置好的,所以只需要处理BrokerId的分配和持久化问题。 Broker第一次上线的时候,只有配置文件中配置的ClusterNameBrokerName,以及自身的BrokerAddress。那么我们需要和Controller协商出一个在整个集群生命周期中都唯一确定的标识:BrokerId,该BrokerId从1开始分配。当某一个Broker被选为Master的时候,在向Name Server中重新注册时,将更改为BrokerId为0 (兼容之前逻辑 brokerId为0代表着Broker是Master身份)。

上线流程

register process

1. GetNextBrokerId Request

这时候发起一个GetNextBrokerId的请求到Controller,为了拿到当前的下一个待分配的BrokerId(从1开始分配)。

1.1 ReadFromDLedger

此时Controller接收到请求,然后走DLedger去获取到状态机的NextBrokerId数据。

2. GetNextBrokerId Response

Controller将NextBrokerId返回给Broker。

2.1 CreateTempMetaFile

Broker拿到NextBrokerId之后,创建一个临时文件.broker.meta.temp,里面记录了NextBrokerId(也就是期望应用的BrokerId),以及自己生成一个RegisterCode(用于之后的身份校验)也持久化到临时文件中。

3. ApplyBrokerId Request

Broker携带着当前自己的基本数据(ClusterNameBrokerNameBrokerAddress)以及此时期望应用的BrokerIdRegisterCode,发送一个ApplyBrokerId的请求到Controller。

3.1 CASApplyBrokerId

Controller通过DLedger写入该事件,当该事件(日志)被应用到状态机的时候,判断此时是否可以应用该BrokerId(若BrokerId已被分配并且也不是分配给该Broker时则失败)。并且此时会记录下来该BrokerIdRegisterCode之间的关系。

4. ApplyBrokerId Response

若上一步成功应用了该BrokerId,此时则返回成功给Broker,若失败则返回当前的NextBrokerId

4.1 CreateMetaFileFromTemp

若上一步成功的应用了该BrokerId,那么此时可以视为Broker侧成功的分配了该BrokerId,那么此时我们也需要彻底将这个BrokerId的信息持久化,那么我们就可以直接原子删除.broker.meta.temp并创建.broker.meta。删除和创建这两步需为原子操作。

经过上述流程,第一次上线的broker和controller成功协商出一个双方都认同的brokeId并持久化保存起来。

5. RegisterBrokerToController Request

之前的步骤已经正确协商出了BrokerId,但是这时候有可能Controller侧保存的BrokerAddress是上次Broker上线的时候的BrokerAddress,所以现在需要更新一下BrokerAddress,发送一个RegisterBrokerToController 请求并带上当前的BrokerAddress

5.1 UpdateBrokerAddress

Controller比对当前该Broker在Controller状态机中保存的BrokerAddress,若和请求中携带的不一致则更新为请求中的BrokerAddress

6. RegisterBrokerToController Response

Controller侧在更新完BrokerAddress之后可携带着当前该Broker所在的Broker-set的主从信息返回,用于通知Broker进行相应的身份转变。

注册状态轮转

register state transfer

故障容错

如果在正常上线流程中出现了各种情况的宕机,则以下流程保证正确的BrokerId分配

正常重启后的节点上线

若是正常重启,那么则已经在双方协商出唯一的BrokerId,并且本地也在broker.meta中有该BrokerId的数据,那么就该注册流程不需要进行,直接继续后面的流程即可。即从RegisterBrokerToController处继续上线即可。

restart normally

CreateTempMetaFile失败

fail at creating temp metadata file

如果是上图中的流程失败的话,那么Broker重启后,Controller侧的状态机本身也没有分配任何BrokerId。Broker自身也没有任何数据被保存。因此直接重新按照上述流程从头开始走即可。

CreateTempMetaFile成功,ApplyBrokerId未成功

若是Controller侧已经认为本次ApplyBrokerId请求不对(请求去分配一个已被分配的BrokerId并且该 RegisterCode不相等),并且此时返回当前的NextBrokerId给Broker,那么此时Broker直接删除.broker.meta.temp文件,接下来回到第2步,重新开始该流程以及后续流程。

fail at applying broker id

ApplyBrokerId成功,CreateMetaFileFromTemp未成功

上述情况可以出现在ApplyResult丢失、CAS删除并创建broker.meta失败,这俩流程中。 那么重启后,Controller侧是已经认为我们ApplyBrokerId流程是成功的了,而且也已经在状态机中修改了BrokerId的分配数据,那么我们这时候重新直接开始步骤3,也就是发送ApplyBrokerId请求的这一步。

fail at create metadata file

因为我们有.broker.meta.temp文件,可以从中拿到我们之前成功在Controller侧应用的BrokerIdRegisterCode,那么直接发送给Controller,如果Controller中存在该BrokerId并且RegisterCode和请求中的RegisterCode相等,那么视为成功。

正确上线后使用BrokerId作为唯一标识

当正确上线之后,之后Broker的请求和状态记录都以BrokerId作为唯一标识。心跳等数据的记录都以BrokerId为标识。 同时Controller侧也会记录当前该BrokerIdBrokerAddress,在主从切换等时候用于通知Broker状态变化。

默认持久化ID的文件在~/store/brokerIdentity,也可以设置storePathBrokerIdentity参数来决定存储路径。在自动主备切换模式下,不要随意删除该文件,否则该 Broker 会被当作新 Broker 上线。

升级方案

4.x 版本升级遵守 5.0 升级文档流程即可。 5.0.0 和 5.1.0 非持久化BrokerId版本升级到 5.1.1 及以上持久化BrokerId版本按照如下流程:

升级Controller

  1. 将旧版本Controller组停机。
  2. 清除Controller数据,即默认在~/DLedgerController下的数据文件。
  3. 上线新版Controller组。

在上述升级Controller流程中,Broker仍可正常运行,但无法切换。

升级Broker

  1. 将Broker从节点停机。
  2. 将Broker主节点停机。
  3. 将所有的Broker的Epoch文件删除,即默认为~/store/epochFileCheckpoint~/store/epochFileCheckpoint.bak
  4. 将原先的主Broker先上线,等待该Broker当选为master。(可使用admin命令的getSyncStateSet来观察)
  5. 将原来的从Broker全部上线。

建议停机时先停从再停主,上线时先上原先的主再上原先的从,这样可以保证原来的主备关系。 若需要改变升级前后主备关系,则需要停机时保证主、备的CommitLog对齐,否则可能导致数据被截断而丢失。

兼容性

5.1.0 及以下版本 Controller 5.1.1 及以上版本 Controller
5.1.0 及以下版本 Broker 正常运行,可切换 若已主备确定则可正常运行,不可切换。若broker重新启动则无法上线
5.1.1 及以上版本 Broker 无法正常上线 正常运行,可切换
作者:admin  创建时间:2023-08-22 15:27
 更新时间:2023-08-22 16:10