You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@rocketmq.apache.org by "RongtongJin (via GitHub)" <gi...@apache.org> on 2023/03/15 23:57:15 UTC

[GitHub] [rocketmq] RongtongJin commented on a diff in pull request #6359: [ISSUE #6358]Add chinese docs about persistent-unique-broker-id

RongtongJin commented on code in PR #6359:
URL: https://github.com/apache/rocketmq/pull/6359#discussion_r1137899746


##########
docs/cn/controller/persistent_unique_broker_id.md:
##########
@@ -0,0 +1,207 @@
+# 持久化的唯一BrokerId
+
+## 现阶段问题
+现在采用`BrokerAddress`作为Broker在Controller模式下的唯一标识。导致如下情景出现问题:
+
+- 容器环境下,每次Broker的重启或升级都可能会导致IP发生变化,导致之前的`BrokerAddress`留下的记录没办法和重启后的Broker联系起来,比如说`ReplicaInfo`, `SyncStateSet`等数据。
+## 改进方案
+在Controller侧采用`BrokerName:BrokerId`作为唯一标识,不再以`BrokerAddress`作为唯一标识。并且需要对`BrokerId`进行持久化存储,由于`ClusterName`和`BrokerName`都是启动的时候在配置文件中配置好的,所以只需要处理`BrokerId`的分配和持久化问题。
+Broker第一次上线的时候,只有配置文件中配置的`ClusterName`和`BrokerName`,以及自身的`BrokerAddress`。那么我们需要和`Controller`协商出一个在整个集群生命周期中都唯一确定的标识:`BrokerId`,该`BrokerId`从1开始分配。当Broker被选为Master的时候,它会在Name Server中重新注册,此时为了兼容之前的无HA的Master-Slave架构,那么需要在这一步暂时更改为`BrokerId`为0(之前的逻辑里面id为0代表着Broker是Master身份)。
+### 上线流程
+
+![](../image/controller/persistent_unique_broker_id/register_process.png)
+
+#### 1. GetNextBrokerId Request
+这时候发起一个`GetNextBrokerId`的请求到Controller,为了拿到当前的下一个待分配的`BrokerId`(从1开始分配)。
+#### 1.1 ReadFromDLedger
+此时Controller接收到请求,然后走DLedger去获取到状态机的`NextBrokerId`数据。
+#### 2. GetNextBrokerId Response
+Controller将`NextBrokerId`返回给Broker。
+#### 2.1, 2.2 CreateTempMetaFile
+Broker拿到`NextBrokerId`之后,创建一个临时文件`.broker.meta.temp`,里面记录了`NextBrokerId`(也就是期望应用的`BrokerId`),以及自己生成一个`RegisterCode`(用于之后的身份校验)也持久化到临时文件中。
+#### 3. ApplyBrokerId Request
+Broker携带着当前自己的基本数据(`ClusterName`、`BrokerName`和`BrokerAddress`)以及此时期望应用的`BrokerId`和`RegisterCode`,发送一个`ApplyBrokerId`的请求到Controller。
+#### 3.1 CASApplyBrokerId
+Controller通过DLedger写入该事件,当该事件(日志)被应用到状态机的时候,判断此时是否可以应用该`BrokerId`(若`BrokerId`已被分配并且也不是分配给该Broker时则失败)。并且此时会记录下来该`BrokerId`和`RegisterCode`之间的关系。
+#### 4. ApplyBrokerId Response
+若上一步成功应用了该`BrokerId`,此时则返回成功给Broker,若失败则返回当前的`NextBrokerId`。
+#### 4.1, 4.2 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进行相应的身份转变。
+### 注册状态轮转
+
+![](../image/controller/persistent_unique_broker_id/register_state_transfer.png)
+
+### 故障容错
+> 如果在正常上线流程中出现了各种情况的宕机,则以下流程保证正确的`BrokerId`分配
+
+#### 正常重启后的节点上线
+若是正常重启,那么则已经在双方协商出唯一的`BrokerId`,并且本地也在`broker.meta`中有该`BrokerId`的数据,那么就该注册流程不需要进行,直接继续后面的流程即可。即从`RegisterBrokerToController`处继续上线即可。
+
+![image.png](../image/controller/persistent_unique_broker_id/normal_restart.png)
+
+#### CreateTempMetaFile失败
+
+![image.png](../image/controller/persistent_unique_broker_id/fail_create_temp_metadata_file.png) 
+
+如果是上图中的流程失败的话,那么Broker重启后,Controller侧的状态机本身也没有分配任何`BrokerId`。Broker自身也没有任何数据被保存。因此直接重新按照上述流程从头开始走即可。
+#### CreateTempMetaFile成功,ApplyBrokerId未成功
+若是Controller侧已经认为本次`ApplyBrokerId`请求不对(请求去分配一个已被分配的`BrokerId`并且该	`RegisterCode`不相等),并且此时返回当前的`NextBrokerId`给Broker,那么此时Broker直接删除`.broker.meta.temp`文件,接下来回到第2步,重新开始该流程以及后续流程。
+
+![image.png](../image/controller/persistent_unique_broker_id/fail_apply_broker_id.png)
+
+#### ApplyBrokerId成功,CreateMetaFileFromTemp未成功
+上述情况可以出现在`ApplyResult`丢失、CAS删除并创建`broker.meta`失败,这俩流程中。
+那么重启后,Controller侧是已经认为我们`ApplyBrokerId`流程是成功的了,而且也已经在状态机中修改了BrokerId的分配数据,那么我们这时候重新直接开始步骤3,也就是发送`ApplyBrokerId`请求的这一步。
+
+![image.png](../image/controller/persistent_unique_broker_id/fail_create_metadata_file_and_delete_temp.png)
+
+因为我们有`.broker.meta.temp`文件,可以从中拿到我们之前成功在Controller侧应用的`BrokerId`和`RegisterCode`,那么直接发送给Controller,如果Controller中存在该`BrokerId`并且`RegisterCode`和请求中的`RegisterCode`相等,那么视为成功。
+### 正确上线后使用BrokerId作为唯一标识
+当正确上线之后,之后Broker的请求和状态记录都以`BrokerId`作为唯一标识。心跳等数据的记录都以`BrokerId`为标识。
+同时Controller侧也会记录当前该`BrokerId`的`BrokerAddress`,在主从切换等时候用于通知Broker状态变化。
+## 升级方案
+4.x版本升级遵守5.0升级文档流程即可。
+5.x非持久化BrokerId版本升级到持久化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对齐,否则可能导致数据被截断而丢失。
+
+### 测试
+> 启动一个namesrv
+
+```bash
+nohup sh bin/mqnamesrv &
+```
+> 启动一个旧版controller
+
+```bash
+nohup sh bin/mqcontroller -c ./conf/controller/controller-standalone.conf &
+```
+> 查看controller是否被正确启动
+
+```bash
+sh bin/mqadmin getControllerMetaData -a localhost:9878

Review Comment:
   测试相关内容去掉吧



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@rocketmq.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org