3. 序列号生成与分配机制

序列号生成与分配机制决定了追溯系统的“发号权”放在哪里、号段如何切分、冲突如何避免,以及发号动作发生在生产节拍的哪一刻。它直接影响到产线能否在断网、抖动、并发写入等条件下持续赋码,也决定了后续追溯查询能否唯一定位到单件产品。本节围绕集中式与分布式两条技术路线展开,并给出号段管理、防冲突、批量预生成与实时生成的工程化做法。

一、集中式生成:单一权威源与号段租约

集中式生成把序列号的唯一性交给一个中心服务(数据库序列、Redis INCR、专用发号服务)来保证。它的核心优势是全局唯一性容易证明:只要中心服务的自增或序列机制正确,就不会出现重复号。典型实现是“号段租约”模式:发号服务一次从中心领取一段连续号(例如 1000 个),在本地内存中分配,用完再领下一段。这样既保留了集中式的唯一性,又把高频发号动作从中心服务下移到本地,降低中心压力。

集中式的代价是可用性依赖网络。若产线设备与中心服务之间断链,本地号段耗尽后无法继续发号。因此工程上通常要求:号段租约长度按“断网可支撑时长”反推。例如某产线节拍为 2 件/秒,要求断网后仍能连续生产 30 分钟,则单次租约至少应覆盖 2×60×30=3600 个号,考虑余量可取 5000 个。号段长度过小会导致频繁请求中心,过大则会造成号段浪费和回滚困难。

二、分布式生成:节点自治与冲突规避

分布式生成让每个产线节点、每条产线或每个工位独立发号,不依赖中心服务实时在线。常见做法是“节点标识 + 本地自增”:为每个发号节点分配一个固定节点号(如产线号、工位号或设备号),节点内维护本地计数器,最终序列号由“节点号 + 本地序号”拼接或组合而成。例如节点号占 4 位、本地序号占 8 位,则单节点可发 10^8 个号,节点数上限为 10^4。

分布式生成的关键风险是节点号重复或本地计数器回退。若两台设备被误配为同一节点号,或设备重启后本地计数器从 0 重新开始,就会产生重复序列号。因此必须配套防冲突策略:节点号由中心统一注册并持久化,设备重启后从持久化存储恢复计数器,或采用“时间戳 + 节点号 + 序列”的组合方式,使重启后不会回到旧号段。

三、号段管理与防冲突策略

号段管理要解决三个问题:号段边界、号段状态和号段回收。号段边界指每个号段的起止号,必须记录在可审计的存储中;号段状态包括“已分配、使用中、已耗尽、已作废”;号段回收用于处理设备报废、产线停用或号段误领的情况。一个可落地的号段表至少应包含:号段ID、节点号、起始序号、结束序号、当前指针、状态、领取时间、最后心跳时间。

防冲突策略可分为三层。第一层是“分配层防冲突”:节点号全局唯一注册,号段不重叠。第二层是“运行层防冲突”:发号时校验当前指针未越界,越界则拒绝发号并触发重新领段。第三层是“写入层防冲突”:在追溯数据库中,序列号字段建立唯一索引,任何重复写入都会被数据库拒绝,作为最后一道防线。三层叠加后,即使配置出错,也能在写入环节暴露问题而不是让重复号流入市场。

序列号生成与分配机制总览 集中式生成(号段租约) 中心发号服务 DB序列 / Redis INCR 本地号段缓存 一次领 5000 个 断网可支撑时长 = 号段长度 ÷ 节拍 示例:5000 ÷ 2 件/秒 ≈ 41 分钟 领段 分布式生成(节点自治) 节点A 节点号 0001 节点B 节点号 0002 节点C 节点号 0003 序列号 = 节点号(4位) + 本地序号(8位) 单节点容量 10^8,节点上限 10^4 防冲突三层防线 ① 分配层 节点号全局唯一注册 号段区间不重叠 中心统一分配,持久化 ② 运行层 发号前校验指针未越界 越界拒绝并重新领段 重启后从持久化恢复 ③ 写入层 追溯库序列号唯一索引 重复写入直接拒绝 最后一道兜底防线

四、批量预生成与实时生成的取舍

批量预生成指在产线开线前或换班前,一次性生成一批序列号并写入本地缓存或标签打印队列。它的优点是发号动作与生产节拍解耦,产线启动快、对中心服务瞬时压力小;缺点是号段可能被浪费,且预生成后若产品未实际生产,这些号会变成“空洞号”。实时生成指每生产一件产品、在赋码工位即时请求一个序列号。它的优点是号段利用率高、不会产生空洞;缺点是对发号服务的响应时间和可用性要求更高。

工程上常见的折中方案是“小批量预生成 + 实时补充”:本地缓存维持一个低水位线(如剩余 200 个号)和高水位线(如 1000 个号),当剩余量低于低水位线时异步向中心申请下一段,生产不中断。这样既避免了每件都请求中心,又不会一次性占用过多号段。判断参数是否合理,可以观察两个指标:一是“发号等待时间”,应远小于产线节拍;二是“号段空洞率”,即预生成但未使用的号占已领号段的比例,通常控制在 5% 以内较为健康。

五、一个可落地的号段配置示例

假设某工厂有 3 条产线,每条产线 2 个赋码工位,节拍为 1.5 件/秒,要求断网后仍能生产 20 分钟。按集中式号段租约设计:单工位断网需求量为 1.5×60×20=1800 个,取整为 2000 个;每个工位独立领段,则号段表可按“产线号-工位号-号段序号”组织。节点号编码可采用 2 位产线号 + 2 位工位号,共 4 位;本地序号 8 位,单工位容量 10^8,满足长期使用。

号段表(示例)
segment_id | node_code | start_seq | end_seq | cur_ptr | status  | lease_time
S-0001     | 0101      | 1         | 2000    | 1       | IN_USE  | 2025-06-01 08:00
S-0002     | 0102      | 1         | 2000    | 1       | IN_USE  | 2025-06-01 08:00
S-0003     | 0201      | 1         | 2000    | 1       | IN_USE  | 2025-06-01 08:00
S-0004     | 0202      | 1         | 2000    | 1       | IN_USE  | 2025-06-01 08:00
S-0005     | 0301      | 1         | 2000    | 1       | IN_USE  | 2025-06-01 08:00
S-0006     | 0302      | 1         | 2000    | 1       | IN_USE  | 2025-06-01 08:00

发号时,工位从 cur_ptr 取值并自增,生成完整序列号如“0101-00000001”。当 cur_ptr 超过 end_seq 时,状态置为 EXHAUSTED,并触发申请新号段。若设备重启,先从本地持久化文件恢复 cur_ptr,再继续发号;若恢复失败,则必须向中心申请全新号段,禁止从 1 重新开始,以避免与历史号重复。

判断发号机制是否健康,可以看三个信号:发号延迟是否稳定低于节拍、号段空洞率是否可控、以及唯一索引是否从未触发重复告警。三者同时正常,才说明生成与分配机制真正可靠。

集中式与分布式并非互斥。实际系统常采用“中心注册节点号 + 节点本地发号 + 数据库唯一索引兜底”的混合模式:中心只负责节点号和号段的权威分配,发号动作在产线本地完成,写入时再由数据库做最终校验。这样既保留了分布式的高可用和低延迟,又通过中心注册和唯一索引守住了唯一性底线。选择哪种机制,最终取决于产线对断网时长的容忍度、发号频率、以及追溯系统对号段浪费的接受程度。