一个节点出问题,能牵连集群里66.67%的节点。这不是压测跑出来的极端值,是Uber旧分片模型在特定配置下的真实影响范围。他们最近重新设计了M3DB的分片放置策略,办法是引入固定大小的子集群。
M3DB是Uber的分布式时序数据库,数据被切成多个分片,在多个节点间复制。放置算法决定谁拥有哪个分片,同时强制副本之间保持隔离——比如把副本放到不同机架或不同可用区。
![]()
旧模型的问题:一张越织越密的依赖网
旧模型里,只要副本没被塞进同一个隔离组,任意节点都可以拥有一个分片。这个规则在中小集群里跑得挺好,集群一大,麻烦就来了。
宽松的配置会织出一张依赖图,一次拓扑变更就能波及O(N)个节点。Uber给了一个具体场景:隔离组对应三个可用区、复制因子为3,一个节点仍可能与集群中多达66.67%的节点共享数据。
后果有两个。一是数据恢复的工作量被放大,二是运维操作只能串行执行,没法并行推进。
新模型:把节点切成互不重叠的子集群
新方案把节点划分成固定大小的子集群,每个子集群拥有互不重叠的分片空间。Uber举的例子是:一个12节点集群,复制因子为3,每个子集群6个节点,于是有两个子集群,各自拿一半分片。
子集群内部,M3DB依然会把副本分散到不同隔离组。隔离这件事没丢,只是被限制在了一个更小的范围里。
![]()
扩容时,分片需要从原有子集群迁移到新子集群。Uber用贪心算法评估:从源子集群移除每一个候选分片会带来什么影响,然后挑出能让剩余节点负载尽可能均匀的那个分片。
这样做的好处是省掉了额外的再平衡过程,也避免了分片被移动两次产生的额外网络传输和引导开销。算法的排序复杂度是O(S log S),模拟评估开销是O(S×N),S是候选分片数量,N是子集群内的节点数。
迁移不是免费的
M3DB现有的放置策略文档里写明了分片迁移流程:目标节点在接管所有权之前,要从现有对等节点流式传输数据。所以每一次不必要的分片移动,都是一笔实打实的运维开销。
子集群方案也不是没有代价,它带着一串约束条件:
- 要求所有实例权重相等
- 扩容必须以子集群规模为单位批量进行
- 子集群大小必须是副本因子的整数倍
- 不支持通过AddReplica接口修改复制因子
- 扩容期间会短暂出现跨子集群共享分片的情况
- 系统同一时刻只允许存在一个非完整子集群
Uber保留了M3DB现有的实例级放置操作,没有引入原子化的子集群操作。团队的说法是,这样保持了与现有工具的兼容性,也避免了触发大量分片同时迁移的大规模引导操作。
M3DB的放置策略配置里,现在多了用于子集群放置和每个子集群实例数量的字段。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.