同一个源库被多个津梁连着、容器重启丢了本地状态、两个人都把任务叫 orders —— 全部不冲突
冲突其实有三种,混在一起才难解:
gc 把 B 实例正在用的书签当孤儿删了。| 层 | 由什么决定 | 干什么 | 不用于 |
|---|---|---|---|
| job_key | base32(sha256(源|目标|范围))[:10] | 任务身份、状态表主键、对象命名、租约排他 | 展示 |
| instance_id | 首次启动随机 26 位 base32(--instance 可指定) | 审计、租约持有者、对象所有权、MySQL server_id 派生 | 判断是否同一任务 |
| object name | jl_<job_key>_<n> | 源端 slot / publication / 临时快照 | 展示 |
job: 名字只做展示、允许重复;判断「是不是同一个任务」永远看指纹。| 场景 | 结果 |
|---|---|
| 两台机器:同一个源 → 不同目标 | 两个 job_key → 两个 slot(jl_aaa… / jl_bbb…),互不干扰 |
| 两台机器:同一个源 → 同一个目标 | 同一个 job_key → 租约排他,后启动的直接退出(E1005),不双写 |
| 两个任务在同一源上选了不同的表 | 两个 job_key → 两个 publication,互不覆盖 |
两个任务名字都叫 orders 但源不同 | 两个 job_key,名字重复无所谓 |
1. --instance <id> 或 JINLIANG_INSTANCE (容器集群显式指定) 2. 本地状态目录 ~/.config/jinliang/instance (0600) 3. 都没有 → 生成 26 位随机 ID,并登记 _jl_instance
容器重启导致 ID 变更是允许的:旧租约按 TTL 过期,旧对象靠 job_key 仍能找到,gc 用 _jl_object.instance_id 判断归属。
gc 要同时满足四条才动手:
jl_<job_key>… 且能在 _jl_object 找到登记;_jl_lease 里没有该 job_key 的有效租约;--force 且先打印对方实例信息;active=false)。| 问题 | 现在 |
|---|---|
MySQL server_id 撞号(会把真正的从库踢下线) | 由 (instance_id, job_key) 派生到 [2^20, 2^31),确定性且区间足够;不再需要报「请你手挑一个」 |
| 两个实例同时启动都想迁移状态表 | 数据库锁串行化:PG pg_advisory_lock / MySQL GET_LOCK,拿不到就等待并重读版本 |
internal/state/identity.go + 测试(已进 CI):
jl_<job_key>。server_id 落在区间内且确定性。