Key Takeaways
- 为什么直连读写器到 Odoo 是反模式
- 网关架构:三层管道设计
- stock.quant 写入钩子与冲突处理
01为什么直连读写器到 Odoo 是反模式
RFID 读写器每秒可输出数百到数千条 TagRead 事件,其中充满重复(同一标签 1 秒内被读 5-20 次)。将这些事件直接写入 Odoo 会瞬间打挂数据库锁——并发写入 stock.quant 表时,PostgreSQL 行锁排队导致整个库存模块卡死。一个 4 天线读写器在传送带场景下每秒产生 2000+ 条原始事件,其中 95% 是重复读。正确做法是在读写器和 Odoo 之间部署网关中间件,完成去重、聚合、缓冲后再批量写入。
- 4 天线传送带:2000+ 事件/秒,95% 重复
- 直写 Odoo:PostgreSQL 行锁排队→库存模块卡死
- 网关中间件:去重→聚合→缓冲→批量写入
02网关架构:三层管道设计
SpidersRFID 网关采用三层管道:第一层是 LLRP 事件接收器,通过 TCP 长连接从读写器订阅 TagReadData 事件,维持 100ms 心跳。第二层是去重引擎,使用滑动窗口算法(默认 2 秒窗口)+ EPC+天线 ID 复合键去重,将 2000 事件/秒压缩到 50-80 事件/秒。第三层是 Odoo 写入器,通过 XML-RPC/JSON-RPC 调用 stock.quant 的 write 方法,采用批量提交(每 500ms 一批,每批最多 100 条)+ 乐观并发控制(OCC)处理冲突。三层之间用 Redis 队列解耦,确保读写器断线不影响已缓冲事件的最终写入。
EPC 解析是去重之后的关键步骤。EPC Gen2 标签的 96-bit EPC 编码包含 Header、Domain Manager、Object Class、Serial Number 四段。网关解析后将 EPC 映射到 Odoo 的 product.product.external_id 字段,通过 ir.model.data 查找对应的 product.product 记录。对于未映射的 EPC,网关会写入 stock.quant.production.lot 的待匹配队列,由管理员在后台手动绑定。实战中,首次部署时通常有 5-10% 的 EPC 未映射,需要 1-2 天的上线校准期完成全量绑定。
03stock.quant 写入钩子与冲突处理
Odoo 的 stock.quant 表是库存核心——每行代表一个库位+产品+批次的库存数量。网关通过自定义 write 钩子拦截 stock.quant 写入,实现三重保护:(1) 字段级锁——使用 SELECT FOR UPDATE 锁定目标行,避免并发覆盖;(2) 增量写入——不直接设置 quantity,而是通过 stock.move 创建库存移动记录,让 Odoo 的标准库存逻辑处理数量变更,确保库存日记账和会计分录正确生成;(3) 冲突重试——当 OCC 检测到版本冲突(__last_update 时间戳不匹配)时,网关重新读取最新值并重试,最多 3 次。实战中,10 万次/天的写入量下冲突率仅 0.3%,重试后全部成功。
- SELECT FOR UPDATE 行锁 → 防并发覆盖
- stock.move 增量写入 → 日记账/会计分录正确
- OCC 冲突重试 3 次 → 0.3% 冲突率全部成功



