配置同步
节点 A 改了一条记录,节点 B、C、D 多久能看见?答:通常 < 1 秒。
同步流程
节点 A 写入数据库
↓
GORM 回调自动捕获变更
↓
写入 sync_events 临时表
↓
Pusher 协程批量推送到每个存活节点
↓
节点 B/C/D 的 Applier 收到事件并应用任一节点改数据,其他节点通常 < 1 秒内可见。
同步哪些表
users/tokens:账号与 Tokenchannels/abilities:渠道options:系统设置redemptions:兑换码plans/user_plans/plan_usages:套餐 / 订阅 / 用量channel_counters:渠道限流计数logs:调用日志(可通过CLUSTER_SYNC_LOGS=false关掉)
不同步:cluster_nodes / sync_events(内部表,由发现机制维护)。
冲突怎么处理
如果两个节点几乎同时改同一条记录,系统按「最后写入胜出」:
A 改记录的 updated_at = 10:00:01.100
B 改记录的 updated_at = 10:00:01.050
→ A 的版本最终保留规则:
- 接收方收到事件,比较入站记录的
updated_at与本地 - 入站更新才覆盖;本地更新则丢弃入站
所有节点的系统时钟必须基本一致(建议启用 NTP)。漂移过大会导致本应被采纳的更新被错误丢弃。
节点离线期间产生的变更
不会自动回填。比如节点 B 离线 1 小时,期间节点 A 改了 100 条记录;B 恢复后只能看到恢复后的新变更,看不到离线期间的。
修复方法:从存活节点手工 mysqldump 同步一次。
节点间推送的请求头
每次推送会带:
X-Cluster-Secret:目标节点的 secret(校验通过才接收)X-Cluster-Node-Id:发送方节点 ID- 超时 5 秒
同步出问题了怎么排查
- A 改了 B 没收到:
- 看 B 后端日志是否有 sync 事件
- 在 A 端手动 Ping B,看是否通
- 检查两边的
secret_key是否一致
- 数据冲突,丢了一条更新:
- 检查两节点时钟是否同步(开启 NTP)
- 看数据库
sync_events表是否有积压(pushed=0太多 = 推送阻塞)
- 同步延迟很大(> 几秒):
- 看
sync_events积压 - 看 Pusher 协程是否在运行(看进程监控)
- 看节点间网络延迟
- 看
哪些场景关掉同步更快
- 日志表巨大:在节点环境变量设
CLUSTER_SYNC_LOGS=false,日志只存在本地节点 - 节点只读:把当前节点的 secret 设为随机值(拒绝接收)