WuKongIM Docs

Slot 元数据层

理解物理哈希槽、逻辑 Slot Raft Group、元数据路由和权威读写。

编辑此页报告文档问题

Slot 层是分布式元数据存储。用户、频道定义、订阅关系、UID-owned 普通/CMD membership 和 ChannelRuntimeMeta 等状态按稳定物理哈希槽分片,再由逻辑 Slot Raft Group 复制和提交。

两种 Slot 不要混用

名称默认数量作用
物理 Hash Slot256稳定的键空间 fence;UID、Channel ID 等先哈希到这里
逻辑 Slot Raft Groupinitial_slot_count 决定承载一个或多个物理哈希槽的 Raft 复制与元数据状态机

扩容通常迁移逻辑 Slot Group 的副本或 Leader,不改变 256 个物理哈希槽。只有显式启用并执行受控 Hash Slot migration 时,物理哈希槽到逻辑 Group 的映射才会变化。

从键到权威 Leader

key(UID / Channel ID / 业务元数据键)

  ├─ CRC32(key) % 256

physical hash slot

  ├─ versioned HashToSlot table

logical Slot Raft Group

  ├─ observed Raft status

LeaderNodeID + LeaderTerm + ConfigEpoch + RouteRevision

路由表是不可变快照并原子替换,热路径可以在同一个版本下批量解析多个键。路由失败、映射缺失或没有实际 Leader 时返回 not-ready/unknown,而不是回退到任意节点。

Slot 保存哪些元数据

  • 用户、设备和系统 UID;
  • 频道定义、订阅者、黑白名单与成员关系;
  • 普通 membership 的 join/hide/badge/activation 状态与独立 CMD binding;
  • Channel Leader、Replicas、ISR、epoch、写 fence 与 retention 边界;
  • Channel migration task、插件绑定和有界消息事件投影。

消息正文不属于 Slot;它们由 Channel 消息层 的独立频道日志保存。

元数据写入

  1. 调用方用 key 计算物理哈希槽,并从路由快照取得逻辑 Slot Group。
  2. 本地是当前 Leader 时进入 Runtime.Propose;否则通过有界 RPC 转发到解析出的 Leader。
  3. Multi-Raft 持久化并复制日志,在 quorum 后把已提交 entry 交给 Slot FSM。
  4. FSM 验证物理哈希槽确实归属该逻辑 Group,将一批命令写入一个 pkg/db/meta WriteBatch。
  5. WriteBatch 一次原子 commit,之后更新 durable applied boundary 并完成 Future。

这条路径在单节点集群中仍然存在;区别只是 quorum 由一个 voter 满足,而不是绕过 Raft 和 FSM。

权威读取与本地读取

本地副本可以提供明确允许的节点本地或已应用读取。需要当前权威的用户、频道或运行时元数据时,代理会定位逻辑 Slot Group,遍历其 peers 并跟随 not_leader 返回的最新 Leader 提示。

本地快照不是全局真相

一个节点的 Pebble 数据、Raft 日志或 Slot 状态只说明该节点本地看到的边界。Manager 汇总视图必须保留节点、term、配置 epoch 和新鲜度,不能把单节点读取包装成全局一致快照。

Preferred Leader 与实际 Leader

Controller 为每个逻辑 Group 保存 desired peers、配置 epoch 和 preferred leader。Slot Multi-Raft 的实时 status 才提供当前 Leader、term、voters、learners、commit 和 match 进度。

后台 preferred-leader 协调只有在意图仍然新鲜、成员完全匹配、目标最近活跃且追到 commit 时才尝试 transfer。任何 stale intent、joint config、落后或不活跃都保持现状,不会选择另一个候选节点“凑合”。

副本迁移与恢复

安全的副本迁移先把目标作为 learner 加入,等待其 catch-up,再提升并移除旧 voter,最后由 Controller 提交新的 assignment 和配置 epoch。Snapshot 允许新 learner 跨越已压缩日志;恢复时先安装 snapshot,再重放 snapshot index 之后的 committed entries。

每个阶段都必须保留实际 Raft 证明。任务失败时保留现有成员和可观察状态,不直接编辑 cluster-state.json 或节点本地元数据。

容量与背压

  • Multi-Raft 用有界 scheduler 和 worker 处理多个 Group;一个热 Group 不应获得无界队列。
  • FSM 批量应用以摊薄存储 commit,但 batch 仍受记录数、字节和等待时间限制。
  • 大 snapshot 在集群 transport 层分块,接收端重组后再交给 Slot runtime。
  • 队列满、Leader 变化或路由 revision 不匹配都应显式失败或重试,不能静默丢弃元数据写入。

源码入口

目标入口
路由表pkg/cluster/routing
Slot Multi-Raftpkg/slot/multiraft
元数据状态机与代理pkg/slot/fsm, pkg/slot/proxy
本地元数据库pkg/db/meta
Controller 到 Slot 的组合pkg/cluster/slots, pkg/cluster/propose

下一步阅读 Channel 消息层,理解 Slot 元数据如何约束每个频道的消息副本。

本页内容