
ScyllaDB 基于大小的 Tablet 负载均衡原理、配置参数与 tablet 尺寸对账机制【免费下载链接】scylladbNoSQL data store using the Seastar framework, compatible with Apache Cassandra and Amazon DynamoDB项目地址: https://gitcode.com/GitHub_Trending/sc/scylladbScyllaDB 的 tablet 负载均衡器从按磁盘容量均分 tablet 数量演进为按 tablet 实际磁盘大小均衡磁盘利用率这一演进由仓库中的设计文档 size-based-load-balancing.md 完整描述其核心实现位于 tablet_allocator.cc 与 load_sketch.hh。读完本文你将掌握 size-based load balancing 的信息采集流程load_stats、tablet 尺寸的迁移/拆分/合并对账机制、关键配置参数的默认值与生效方式以及滚动升级期间通过集群特性优雅回退到容量均衡的设计。背景从磁盘容量均衡到按大小均衡在引入 size-based load balancing 之前ScyllaDB 执行的是基于磁盘的均衡disk based balancing按节点磁盘容量与 tablet 数量进行分配其隐含假设是每个 tablet 占用相同的磁盘空间。也就是说某节点上的 tablet 数量与该节点的磁盘总容量gross disk capacity成正比。问题在于不同 tablet 实际占用的磁盘空间可能差异巨大——热点 tablet 可能远大于平均水平冷门 tablet 可能几乎为空。在这种假设下做数量均衡会造成集群内磁盘利用率失衡。Size-based load balancing 的目标正是让集群内各节点的磁盘利用率趋于一致负载均衡器持续收集所有节点的可用磁盘空间与 tablet 大小信息并据此增量地计算 tablet 迁移计划将 tablet 从负载最高的节点/分片迁移到负载最低的节点/分片。基本运行机制load_stats 的采集与使用负载均衡器以后台任务形式运行且与拓扑协调者topology coordinator运行在同一个 shard 上。协调者负责周期性地从集群所有节点采集均衡决策所需的信息这一信息就是数据结构的load_stats。文档中与负载均衡直接相关的部分是其成员tablet_stats包含两个字段tablet_sizes该节点上所有 tablet 的磁盘大小字节effective_capacity该节点可用磁盘空间与所有 tablet 大小之和。在源码中这两个字段对应 locator/tablets.hh 中的tablet_load_stats结构体// This is defined as final in the idl layer to limit the amount of encoded data sent via the RPC struct tablet_load_stats { // Sum of all tablet sizes on a node and available disk space. uint64_t effective_capacity 0; // Contains tablet sizes per table. // The token ranges must be the form (a, b] and only such ranges are allowed std::unordered_maptable_id, std::unordered_mapdht::token_range, uint64_t tablet_sizes; ... };完整的load_stats结构locator/tablets.hh还包括按表的统计tables、按节点的原始磁盘容量capacity、关键磁盘利用率标记critical_disk_utilization以及按节点聚合的tablet_stats。节点上报的采集周期由配置项tablet_load_stats_refresh_interval_in_seconds控制定义于 db/config.cc默认值为60 秒即文档中提到的1 分钟采集间隔支持 LiveUpdate 热更新。协调者拿到这些信息后计算每个节点、每个 shard 的磁盘负载磁盘利用率然后把 tablet 从最繁忙迁移到最空闲的节点与 shard。从源码结构看这一计算由 locator/load_sketch.hh 中的load_sketch完成disk_usage以used / capacity0.0 到 1.0 的因子表示利用率load_sketch内部按节点组织node_load每个node_load再按 shard 组织shard_load并用有序集合_shards_by_load按负载升序索引所有 shard以便快速定位最忙/最闲的 shard。值得注意的是load_sketch在计算负载时乐观地把已发起、尚未完成的 tablet 迁移视为已经发生locator/load_sketch.hh 中注释明确写道optimistically assuming that they will succeed这保证了一轮决策中不会反复挑选同一个迁移目标。Table balance均衡的次级目标负载均衡器的次级目标是达成 table balance表级均衡即需要让以下两个比值在各 shard 之间趋于相等某 shard 上某表占用的磁盘 / 该表在整 rack 内占用的磁盘总量某 shard 的有效容量 / 整个 rack 的有效容量。如果不做这一层均衡可能出现某个 shard 承载了某张表的大部分数据。一旦该表是热表访问集中就会让该 shard 的 CPU 过载。换言之size-based 均衡不仅在节点间摊平磁盘也在 shard 间摊平每表数据份额与容量份额的比例关系。load_stats 对账迁移与 split/merge 后的尺寸一致性由于load_stats的采集周期为 1 分钟均衡器开始使用这些信息时其中记录可能已经过期。过期的原因主要有两类tablet 迁移和表 resizesplit 或 merge。解决办法是在迁移或 resize 发生时同步更新load_stats中的 tablet 尺寸信息迁移对账已发出的 tablet 迁移会在load_stats中把 tablet 尺寸从一个 host 迁移到另一个 host。这一步对账在 tablet 迁移流程的end_migration阶段完成。源码中end_migration作为 tablet 状态机的一个阶段出现在 service/tablet_allocator.cc与文档描述一致。split 对账在 tablet resize 确认resize finalization阶段进行。对于 split对账会把原 tablet 的尺寸一分为二用两个新 tablet 替换 split 前的原 tablet 尺寸记录。merge 对账对 merge则累加 merge 前各 tablet 的尺寸生成合并后的 tablet 尺寸记录并从load_stats中移除 merge 前各 tablet 的尺寸。这套对账机制保证load_stats中记录的尺寸始终追着tablet 拓扑的实际变化而不必等待下一个采集周期。强制容量均衡force_capacity_based_balancing均衡器具备回退到容量均衡capacity based balancing的能力可通过配置参数force_capacity_based_balancing强制启用。开启后均衡器不再从load_stats查询真实 tablet 尺寸而是假定每个 tablet 的大小都等于default_target_tablet_size容量计算改用原始磁盘容量gross disk capacity即load_stats结构中的capacity成员而非有效容量effective_capacity。在 db/config.cc 中可以看到该参数定义, force_capacity_based_balancing(this, force_capacity_based_balancing, liveness::LiveUpdate, value_status::Used, false, Forces the load balancer to perform capacity based balancing, instead of size based balancing.)即默认值为false支持 LiveUpdate。load_sketch侧用一个布尔标志_force_capacity_based_load实现该回退locator/load_sketch.hh为真时get_disk_capacity_for_node回落到capacityget_tablet_size直接返回_default_tablet_size。default_target_tablet_size定义于 service/tablet_allocator_fwd.hh值为5 * 1024 * 1024 * 1024即5 GiB这也是 tablet 自动拆分/合并的目标尺寸基准。此外force_capacity_based_balancing还承担一个兜底角色在集群特性尚未开启时均衡器会自己切到容量均衡模式见下文集群特性一节。测试用例中也直接验证了这一回退逻辑例如 test/boost/tablets_test.cc 中通过cfg.db_config-force_capacity_based_balancing.set(true)构造容量均衡场景。排除 tablet 尺寸不完整的节点即便有迁移与 resize 对账load_stats中的 tablet 尺寸信息仍可能与 tablet map 中的当前 tablet 信息不一致。为避免均衡器基于不完整或错误的数据做决策size-based load balancing不会去平衡那些 tablet 尺寸不完整的节点这些节点既不会被选为迁移源也不会被选为迁移目标均衡器会等待拓扑协调者下一次刷新load_stats后待正确的尺寸数据到达再参与决策。唯一的例外是被排除出集群excluded的节点这类节点已下线无法再上报新鲜的load_stats但它们仍需要被排干——通过 tablet rebuild 把 tablet 迁走。因此均衡器必须在 tablet 数据不完整的情况下也对其执行迁移。源码中load_sketch的node_load用_has_valid_disk_capacity与_has_all_tablet_sizes两个标记追踪节点数据完整性locator/load_sketch.hh与不完整则不参与均衡的行为相呼应。集群特性SIZE_BASED_LOAD_BALANCING 与滚动升级滚动升级期间集群全部升级完成可能需要数小时甚至数天。未升级的旧节点上报的load_stats不带 tablet 尺寸。结合上一条规则均衡器忽略尺寸不完整的节点如果不加处理这些节点会在相当长的时间内得不到负载均衡。因此size-based load balancing 只在对应集群特性cluster feature开启后才真正生效特性开启之前均衡器回退到容量均衡。该特性在 gms/feature_service.hh 中声明gms::feature size_based_load_balancing { *this, SIZE_BASED_LOAD_BALANCINGsv };而回退逻辑可以直接在 service/tablet_allocator.cc 中确认构造时读取force_capacity_based_balancing配置随后若集群特性size_based_load_balancing未开启且未强制容量均衡则把_force_capacity_based_balancing置为true。也就是说滚动升级期间自动容量均衡、全量升级后自动切换为按大小均衡这一行为由特性开关与配置项共同决定无需人工干预。Minimal tablet size避免对未 flush tablet 的过早迁移表创建后开始接收数据时可能有一段时期某些 tablet 的数据已经 flush 到磁盘而其他 tablet 还没有。此时若按真实尺寸决策均衡器会把那些看起来为空其实只是还没 flush的 tablet 从创建节点迁走等所有 tablet 都 flush 之后又得重新迁移产生无谓的早期迁移。为此引入minimal tablet size概念均衡器把小于该阈值的 tablet 一律按 minimal tablet size 计。这显著减少了早期无谓迁移。对应配置项为minimal_tablet_size_for_balancing定义于 db/config.cc, minimal_tablet_size_for_balancing(this, minimal_tablet_size_for_balancing, liveness::LiveUpdate, value_status::Used, service::default_target_tablet_size / 100, Sets the minimal tablet size for the load balancer. For any tablet smaller than this, the balancer will use this size instead of the actual tablet size.)默认值为default_target_tablet_size / 100即 5 GiB 的百分之一约 51.2 MiB同样支持 LiveUpdate该值最终注入到load_sketch的_minimal_tablet_size成员参与尺寸计算locator/load_sketch.hh。Balance threshold percentage何为已均衡均衡器判断一组节点是否已经均衡的方法是计算负载最高与负载最低节点之间的磁盘负载差除以最高负载delta (most_loaded - least_loaded) / most_loaded若该值低于阈值则认定这些节点已处于均衡状态无需再发起迁移。阈值通过size_based_balance_threshold_percentage配置项设置定义于 db/config.cc, size_based_balance_threshold_percentage(this, size_based_balance_threshold_percentage, liveness::LiveUpdate, value_status::Used, 1.0, Sets the maximum difference in percentages between the most loaded and least loaded nodes, below which the load balancer considers nodes balanced.)默认值为1.0百分比支持 LiveUpdate。在均衡器构造时该百分比被除以 100 转为比例存入_size_based_balance_thresholdservice/tablet_allocator.cc。调低该值会追求更严格的均衡迁移更频繁调高则减少迁移量但容忍更大的利用率差异。相关配置参数汇总以下参数均定义于 db/config.cc且均为 LiveUpdate可在线修改、无需重启配置项默认值作用tablet_load_stats_refresh_interval_in_seconds60load_stats采集刷新周期秒决定均衡信息的最大滞后force_capacity_based_balancingfalse强制容量均衡假定所有 tablet 等大小5 GiB、使用原始磁盘容量而非有效容量size_based_balance_threshold_percentage1.0最高与最低负载节点差值相对最高负载的百分比阈值低于该值视为已均衡minimal_tablet_size_for_balancingdefault_target_tablet_size / 100约 51.2 MiB小于该值的 tablet 按该值计避免未 flush tablet 的过早迁移源码与测试索引想进一步深入实现时可以从以下入口切入均衡算法主体service/tablet_allocator.cc其中TabletLoadBalancer构造时读取上述配置并决定均衡模式负载模型locator/load_sketch.hhload_sketch维护节点/shard 两级负载视图并提供容量回退_force_capacity_based_load与在途迁移的乐观记账数据结构locator/tablets.hh 的table_load_stats、tablet_load_stats、load_stats集群特性声明gms/feature_service.hh单元/集成测试test/boost/tablets_test.cc容量均衡回退场景与 test/boost/tablets_test.cc阈值参数场景性能测试入口见 test/perf/tablet_load_balancing.cc。小结ScyllaDB 的 size-based load balancing 是一套围绕磁盘利用率的均衡机制以拓扑协调者周期性采集的load_statstablet 尺寸 有效容量为输入通过迁移与 split/merge 对账保证输入的新鲜度通过不完整节点除外 excluded 节点例外保证决策安全通过集群特性SIZE_BASED_LOAD_BALANCING保证滚动升级期间的平滑过渡并通过 minimal tablet size 与 balance threshold percentage 两个参数控制迁移的触发时机与收敛标准。配合force_capacity_based_balancing的显式回退能力整套机制在异构容量、混合版本集群中都能保持行为可预测。【免费下载链接】scylladbNoSQL data store using the Seastar framework, compatible with Apache Cassandra and Amazon DynamoDB项目地址: https://gitcode.com/GitHub_Trending/sc/scylladb创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考