SQL CockroachDB 的 leaseholder 与 range 副本分布的 locality 优化

1次阅读

cockroachdb的leaseholder不会自动跨locality迁移,仅在副本健康且raft leader可达时做最小代价切换;需显式配置zone constraints、启用lease_preferences并确保locality参数严格一致。

SQL CockroachDB 的 leaseholder 与 range 副本分布的 locality 优化

leaseholder 为什么总在同一个节点上不动

leaseholder 不会自动跨 locality 迁移,哪怕你设置了 locality,CockroachDB 默认只在 range 副本健康、raft leader 可达的前提下做最小代价的 leaseholder 切换——它不主动“优化”,只被动响应故障或租约过期。

常见错误现象:SHOW RANGES 显示 leaseholder 长期卡在 us-east-1 节点,即使 us-west-2 有同副本且延迟更低;cockroach node status 显示所有节点都 healthy,但 lease 仍不漂移。

  • 确认是否启用了 --locality 启动参数(每个节点必须带,且 key/value 要一致,比如 --locality=region=us-east,datacenter=dc1
  • 检查 kv.raft_leader_lease_renewal_intervalkv.raft_leader_lease_expiration_interval 的值,太长(默认 9s/12s)会让 lease 持续更久,掩盖局部延迟问题
  • select * FROM [SHOW RANGES WITH DETAILS] WHERE table_name = 'your_table' 查看 lease_holderreplicas 字段,确认目标 locality 是否真有副本(不是只有 learner)

range 副本没按 locality 分布,add replica 失败

副本分布是异步触发的,依赖 rebalancer 工作,而 rebalancer 默认只在集群负载低、空间差异 >5%、且目标节点满足 locality 约束时才行动——它不会立刻响应你刚加的节点。

使用场景:你新增了 --locality=region=eu-central 的节点,想让某个表的 range 快速在欧洲落地副本,但 ALTER TABLE … CONFIGURE ZONE 后半天没变化。

  • 手动触发:cockroach sql -e "SELECT crdb_internal.force_replication_scan()"(仅限 v22.2+,v21.x 用 cockroach debug zip 后查日志确认 scan 是否运行)
  • zone config 必须显式指定 constraints,例如:ALTER TABLE t CONFIGURE ZONE using constraints='[+region=eu-central]',不能只靠启动时的 --locality
  • 注意约束语法:[+region=us-east] 表示“至少一个副本在此 region”,[+region=us-east, +region=us-west] 才能保证跨 region;单个 [+region=us-west] 可能导致无法满足(若当前无副本在该 region)

leaseholder 在跨 region 请求中明显变慢

当 leaseholder 和客户端不在同一 locality,每次写请求都要跨 region 走 raft log 复制 + lease renewal round-trip,延迟直接叠加两段公网 RTT,不是简单“慢一点”而是阶跃式升高。

性能影响:即使你配置了 locality=region=us-west 给客户端节点,CockroachDB 也不会把 lease 自动切过去——它只认节点自身的 --locality,不感知 client 连接来源。

  • 强制切换 leaseholder:用 cockroach sql -e "SELECT crdb_internal.force_leadership_transfer('your_table', 1)"(v22.2+),其中 1 是 target store_id,需先从 SHOW RANGES 查出对应节点的 store_id
  • 避免依赖自动策略:对延迟敏感的表,用 zone config 锁定 lease_preferences,例如:lease_preferences='[[+region=us-west]]'(注意双括号语法)
  • 确认 kv.range_lease_preferences.enabled 集群设置为 true(默认 true,但某些私有部署可能关掉)

locality key 写错导致副本拒绝加入

CockroachDB 对 locality key 是严格字符串匹配的,region=us-westregion=us-west-1 被视为两个完全无关的 locality,rebalancer 不会把前者副本迁去后者,哪怕它们物理上是同一个机房。

容易踩的坑:运维脚本里用不同格式生成 locality(有的带 AZ 后缀,有的不带),或者升级时节点重启漏传 --locality,导致新节点 locality 为空,副本拒绝调度过去。

  • 检查所有节点启动命令:必须含 --locality,且 key 名统一(推荐用 region/datacenter/rack 三级,避免自定义字段如 azzone
  • SELECT * FROM crdb_internal.gossip_liveness 查每节点上报的 locality 字段,确认无空值、无拼写差异
  • 副本数不足时,ADD REPLICA 报错 unable to find a store matching constraints,大概率是 locality key 不一致,不是磁盘满或节点 down

locality 不是标签,是调度契约;写错一个字符,整个分布逻辑就失效。最麻烦的不是配不上去,而是配错了还看起来“正常运行”。

text=ZqhQzanResources