You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@rocketmq.apache.org by do...@apache.org on 2021/12/01 09:57:41 UTC

[rocketmq] branch 5.0.0-alpha-static-topic updated: Polish doc for static topic

This is an automated email from the ASF dual-hosted git repository.

dongeforever pushed a commit to branch 5.0.0-alpha-static-topic
in repository https://gitbox.apache.org/repos/asf/rocketmq.git


The following commit(s) were added to refs/heads/5.0.0-alpha-static-topic by this push:
     new e002c74  Polish doc for static topic
e002c74 is described below

commit e002c74c3eb71f548f1f5815a5909bd32afac686
Author: dongeforever <do...@apache.org>
AuthorDate: Wed Dec 1 17:57:19 2021 +0800

    Polish doc for static topic
---
 ..._Topic_Logic_Queue_\350\256\276\350\256\241.md" | 88 +++++++++++++++++-----
 1 file changed, 70 insertions(+), 18 deletions(-)

diff --git "a/docs/cn/statictopic/RocketMQ_Static_Topic_Logic_Queue_\350\256\276\350\256\241.md" "b/docs/cn/statictopic/RocketMQ_Static_Topic_Logic_Queue_\350\256\276\350\256\241.md"
index b33f72e..1ad9183 100644
--- "a/docs/cn/statictopic/RocketMQ_Static_Topic_Logic_Queue_\350\256\276\350\256\241.md"
+++ "b/docs/cn/statictopic/RocketMQ_Static_Topic_Logic_Queue_\350\256\276\350\256\241.md"
@@ -3,6 +3,8 @@
 | --- | --- | --- |
 | 2021-11-01 | 初稿,包括背景、目标、SOT定义与持久化、SOT生命周期、SOT的使用、API逻辑修改、问题与风险 | dongeforever |
 | 2021-11-15 | 修改 LogicQueue 的定义,不要引入新字段,完全复用旧的MessageQueue; RemappingStaticTopic时,不要迁移『位点』『幂等数据』等,而是采用Double-Check-Read 的机制| dongforever |
+| 2021-12-01 | 更新问题与风险,增加关于一致性、OutOfRange、拉取中断的详细说明| dongforever |
+
 
 中文文档在描述特定专业术语时,仍然使用英文。
 
@@ -211,16 +213,8 @@ Leader Completeness,避免了数据的切割,对于后续其它操作有极
 - 写入旧 Leader,禁写旧 Leader
 - 更新新 Leader,确定 logicOffset
 
-
-切换的要点是:
-
-- 切换期间,是否要给客户端返回当前offset
-- 如果要返回当前offset,且保证连续,则需要先等待旧Broker全部处理完毕,不可用时间可能会比较长
-- 如果要返回当前offset,但可以不连续,则可以采取blockSequeue的原则,一次跳跃特定步长,先返回offset
-
-
 切换失败处理:
-- 不管哪种方式,数据存储至少2份,后续可以手工恢复
+- 不管哪种方式,数据存储至少成功了1份,后续可以手工恢复
 
 
 #### 清除
@@ -292,7 +286,7 @@ UpdateStaticTopic 命令会自动计算预期的分布情况,包括但不限
 
 
 #### RemappingStaticTopic
-对应 RequestCode.REMAPPING_STATIC_TOPIC=517,迁移动作比较重,还是单独搞命令比较好。
+迁移动作不引入新命令,计算好之后,执行UPDATE_AND_CREATE_STATIC_TOPIC即可.
 主要参数:
 
 - -t, topic 名字
@@ -352,16 +346,74 @@ Offset的存储,无需转换,直接存储在 LogicQueue 所对应的最新 P
 如果要使用StaticTopic,则需要升级Client、Broker、Nameserver。
 
 ### 问题与风险
-#### 数据不一致问题
-非中心化的存储,这个问题比较关键
-#### 队列重复映射的问题
-一个物理队列,禁止同时分多段映射给多个逻辑队列
-一个物理队列,其startOffset必须从0开始
-增加这两个约束,同时增加一个清除队列的能力
+#### 数据一致性问题
+RocketMQ 没有引入中心化的存储组件,那么如何保证 SOT 的全局一致性呢?
+主要利用两个信息
+* TopicQueueMapping 带上的 epoch
+* TopicQueueMapping 带上 totalQueues
+在更新或者切换时,获取所有Broker上的 TopicQueueMapping,校验 epoch 和 totalQueues,并且根据 TopicQueueMapping 可以完整地构建出对应的Logic Queue,则说明数据是完整一致的。
+如果发现数据不一致,可能是以下因素引入的:
+* 集群中有Broker宕机
+* 上次更新没有完全成功
+
+应该要先修复数据,再执行 更新或切换 操作
+
+#### No Target Brokers
+Target Brokers 是指拥有 LogicQueue 的 Broker。
+考察1个场景,如果某个Topic 只有1个 LogicQueue,而拥有这个 LogicQueue 的 Broker 正好宕机了。此时去更新 Topic,会不会误认为该 Topic 不存在?
+解决这个问题的办法是引入 No Target Brokers,也即集群中除去『Target Brokers』之外的 Broker。
+对于 No Target Broker,依然需要写入一份 TopicQueueMapping,带上 epoch 和 totalQueues,但不拥有任何 LogicQueue。
+有了这个信息之后,在进行一致性校验时,就可以识别出上述场景。
+
+尤其要注意,如果 Nameserver 中没有任何信息,则需要主动去所有 Broker 拉取一遍。
+
+#### 切换时最新 LogicQueueMappingItem 的 logicOffset 决策问题
+logicOffset的决策,依赖于上一个 PhysicalQueue 的最大位点。
+此时,要么跳跃位点,要么等待上一个 PhysicalQueue 确保已经禁写。
+
+当前实现,为了保障高可用,采用『切新禁旧再切新』的方式,同时跳跃位点。
+
+#### logicOffset 为 -1 时的处理
+此时,可以写,但返回给 客户端的 offset 也是-1
+此时,不可以读最新 PhysicalQueue。
+需要确保,相关查找  MappingItem 的操作,忽略 logicOffset 为-1的Item,否则可能触发位点被重置!
+
+#### 队列重复映射
+如果允许1个 PhysicalQueue 被重复利用,也即多段映射给多个 LogicQueue,或者从非0开始映射。
+会带来以下麻烦:
+* 所有位点相关的API,需要考虑 MappingItem endOffset,因为超过了 endOffset 可能已经不属于 当前 LogicQueue 了
+* 新建 MappingItem,需要先获取 旧 MappingItem 的 endOffset
+
+当前实现,为了保证简洁,禁止 PhysicalQueue 被重复利用,每次更新映射都会让物理层面的 writeQueues++ 和 readQueues++
+后续实现,可以考虑复用已经被清除掉的Physical,也即已经没有数据,位点从0开始。
+
+
+#### 备机更新映射
+当前,admin操作都是要求在Master操作的。因此,没有这个问题。
+Command操作时,提前预判Master是否存在,如果不存在,则提前报错,减少中间失败率。
+
+#### 拉取消息时 OutOfRange 的判断
+以下情况会影响 OutOfRange 的判断
+* 从备机拉取消息(默认不会返回OFFSET_MOVED)
+* 中间 MappingItem 因为Commitlog的提前删除导致 PhysicalQueue Offset Truncation
+
+所以,OutOfRange 的判断,遵循以下原则:
+* 从 Leader Item 拉取,只有requestOffset > maxOffset,尊重 OFFSET_MOVED
+* 从 Earliest Item 拉取,只有 requestOffset < minOffset,尊重 OFFSET_MOVED
+* 其它情况,都忽略 OFFSET_MOVED
+
+如果没有恰当地处理 OFFSET_MOVED,可能造成位点被重置。
+
+需要注意,这个地方,产生了对 PullMessageResponseHeader 中 minOffset 和 maxOffset 的强依赖。
+在次此之前,这两个信息,只对客户端的限流有作用,对业务没有实际的影响。
+
+#### 拉取消息时的 中断问题
+当1个 PhysicalQueue 被拉取干净时,需要修正 nextBeginOffset 到下一个 PhysicalQueue。
+如果没有处理好,则直接会导致拉取中断,无法前进。
+
+
 #### pullResult 位点由谁设置的问题
 类似于Batch,由客户端设置,避免服务端解开消息。
-#### 切换时的offset决策问题
-默认保障高可用。
 #### 远程读的性能问题
 从实战经验来看,性能损耗几乎不计。
 #### 使用习惯的改变