Odoo stock.quant 与 RFID:真正的产品是那道网关
Odoo stock.quant 与 RFID:真正的产品是那道网关
Odoo 集成

Odoo stock.quant 与 RFID:真正的产品是那道网关

读写器每秒吐出成千上万条重复的标签事件,而 Odoo 每写一次就是一行 quant,并发下直接死锁。可靠的答案是中间那道网关:确定性解析 EPC、按时间窗去重、聚合成增量、幂等地写入。含架构、字段映射,以及没人写进文档的故障模式。

12 min· By SpidersRFID Editorial Team

每一套 RFID 与 Odoo 集成的第一版都长得一样。读写器被配置成把每一次标签读取都 POST 给一个控制器,控制器直接去写 stock.quant,然后一周之内数据库开始锁表、Odoo worker 被占满,而库存以一种谁也无法复现的方式变错了。

错误是架构性的,不是技术性的。读写器是传感器,不是交易来源。在一个每秒上报成千上万次的传感器,与一个期待「经过思考的业务事件」的 ERP 之间,必须有一个会思考的东西。那个东西就是网关,而在能跑起来的部署里,它才是你维护、版本化、监控的那部分——它是产品,不是胶水。

为什么把读写器直接接进 Odoo 是个反模式

在写任何代码之前,数字已经说明了问题。

  • 门口一台固定式读写器,在托盘通过时每秒会吐出几百条 TagRead 事件。
  • 同一枚标签在一秒内通常会被读到五到二十次,信号强度各不相同。
  • Odoo 的 ORM 会按「产品 / 库位 / 批次」计算并写入一行 quant,每次写入都带行锁与缓存失效。
  • 同一行 quant 上的并发写入会退化成锁等待,而多行更新顺序不对就会死锁。
  • 读写器一旦断线再恢复,会重放一个突发,而这个突发恰好落在 ERP 最吞不下它的时候。

网关的三个职责:解析、去重、聚合

把这三件事做好的网关可以是两百行代码;做不好的,会被重写两次。

  • 解析:把原始 EPC 变成产品、批次与序列号,且不在热路径上查数据库。
  • 去重:每枚标签每个时间窗只保留一次观测,而不是二十次,并保留其中信号最强的一次。
  • 聚合:把观测变成按库位与产品的带符号增量——这是 Odoo 唯一应该看到的东西。
  • 缓冲:增量落在可持久化的队列里,重启不丢,重试安全。
  • 写入:批量写 Odoo,并带一个幂等键,使重复写入成为空操作。

从 EPC 到产品:确定性映射

EPC 解析是集成悄悄崩掉的地方,因为它常常是靠字符串截取而不是靠模式完成的。

  • 96 位 SGTIN 编码了公司前缀、物品参考号与序列号;切分点取决于前缀长度,而不取决于字符串。
  • 先解头部,再解分区,最后解字段;靠猜字段宽度,能一直撑到它撑不住的那天。
  • 维护一张「物品参考号 → 产品与批次」的缓存映射,按定时器刷新,而不是每次读取都查。
  • 未知 EPC 要进一条显式队列,而不是变成 null;一枚未知标签是贴标或写标缺陷,值得被看见。
  • 给映射规则做版本,因为供应商改变标签编码不应该要求一次代码发布。

写入 stock.quant 而不死锁

写入路径是大多数项目丢掉一个周末的地方。规则很简单,主要关乎顺序。

  • 每个数据库只跑一个写入进程;这里的并发买不到你需要的吞吐,却买得到死锁。
  • 优先用 ORM 里那个带正确锁的原子数量更新方法,绝不要在 Python 里做「读—改—写」。
  • 如果必须用 SQL,就按确定性顺序加锁——先产品、再库位、再批次——让两个事务无法交叉。
  • 按库位批量,而不是按标签批量:一条货道里的五十个增量属于一个事务,不是五十个。
  • 每一次调整都要写上业务原因,因为在审计里,一笔没有解释的数量变化与一个 bug 无法区分。

两个真相冲突时怎么办

读写器与 ERP 一定会不一致,设计问题是:谁被允许赢,以及在什么时候。

  • 一次读取是关于「现在」的证据;ERP 记录是关于「过去」的主张。它们不是同一类事实。
  • 绝不要让单次读取覆盖数量;只在观测完整、区域关闭时应用增量。
  • 用读写器的事件时间,而不是到达网关的时间,否则一批延迟数据会被看成一次新的移动。
  • 在事件重复的情况下,最后写入者获胜是不安全的;更稳妥的是每个读写器一个单调序号,并拒绝比已应用更旧的记录。
  • 当分歧是结构性的——整个区域差了 10%——应该报异常,而不是悄悄修正。

每天 10 万事件的吞吐工程

十万事件意味着平均每秒一次,而在装卸口可能每秒两百次,所以平均值没有意义。

  • 按峰值设计,再验证均值;峰值决定系统会不会坏,均值只决定演示时好不好看。
  • 以 0.5 到 2 秒的窗口批量;再短就是白付事务开销,再长就是白付延迟。
  • 热路径上不要有 ORM 计算字段、onchange 逻辑与邮件线程;它们都不属于一次库存写入。
  • 让写入 worker 跑在作业队列的专用通道上,这样 ERP 变慢不会拖死面向读写器的那一侧。
  • 测量去重比;如果低于十倍,说明时间窗太短,Odoo 在做无谓的工作。

可观测性:该记什么、该告什么

一条无法观测的库存管道,会被信任到第一次审计,然后就不再被信任。

  • 抽样记录每一条原始事件,全量记录每一条已应用的增量,并附上幂等键。
  • 按天线统计读取量,这样一根天线坏掉会表现为曲线上的跌落,而不是安静的一周。
  • 对写入延迟超阈值、队列深度持续增长、事件拒绝率上升这三件事告警。
  • 每日对账:把网关增量与 Odoo 数量变化对比,凡超过阈值的差异都要解释。
  • 保留可重放的事件归档,因为最常见的故障不是崩溃,而是某条错误规则悄悄跑了三天。

上线顺序与回滚

把一条写入路径引入 ERP 的安全方式,是让它先挣得写入的资格。

  • 第一阶段:影子模式。只计算增量、只记录、不写入,用两周时间与预期结果对比。
  • 第二阶段:用生产流量写沙箱数据库,并在上面跑对账报表。
  • 第三阶段:用功能开关只对一个区域开启写入,同时保留旧流程并行。
  • 第四阶段:逐区域扩大,盯异常率而不是成功率。
  • 回滚不是恢复数据库:停掉写入进程,用修正后的规则重放队列,再幂等重写一遍。
Odoo RFID 集成一站式方案

我们使用 Cookie 来提升您的浏览体验、分析网站流量并个性化内容。点击“接受全部”即表示您同意我们使用所有 Cookie,您也可以选择“仅必要 Cookie”。详情请参阅我们的 隐私政策 以了解更多详情。