模块 7 · 写侧并发

同一天两笔交易
为什么还是一条预警?

进程内聚合锁原语(locks.py)把「同一客户、同一聚合 key」串行化;L3 监测画像写入服务(profile_l3.py)用 computed_at 乐观锁防丢更新。指挥 AI 改写路径时,先分清悲观锁(串行)和乐观锁(版本戳比对)各管哪一段。

两层锁 · 各管什么

职责代码入口机制
预警同日聚合串行 预警处置与聚合服务(alert_service.py)+ 锁原语(locks.py · run_locked) 单进程 threading.Lock;拿锁超时降级执行,冲突由锁内重查兜底
L3 写侧防覆盖 L3 写入(profile_l3.py)+ 仓储更新(risk_repository.update_l3) 乐观锁:WHERE computed_at = :expected,失败重读重试(最多 3 次)
处置 + 审计同事务 人工处置(handle_alert)+ 风控仓储(risk_repository) 状态变更与 audit 同连接提交(B7 挂账⑦ 已收口)
不做: 风控线不接 L1/L2 画像 Redis 热缓存(归客服/顾问);L3 读侧已有 profile:l3:{customer_id} cache-aside + 写后 DEL。
锁原语 · 预警聚合 key 示例
# alert_service:同日同客户事件类预警
run_locked(
  f"agg:event:{customer_id}:{today}",
  lambda locked: _merge_or_insert(...),
)

# profile_l3:同一客户 L3 upsert
run_locked(f"l3:{customer_id}", _write_with_optimistic_retry)
白话

想象收银台叫号器:同一客户、同一天的「首单聚合」必须排队进窗口,窗口里再查「今天是否已有单」——两笔并发进来也不会开出两张重复首单。

L3 则是贴便签前先对表上的时间戳:若别人刚改过,你的 UPDATE 打不中,就重读再合并(只升不降监测档)。

群聊:并发两笔 · 聚合与 L3

数据流:写侧三条线

🔒聚合锁
📋risk_alert
📊L3 + audit

点击「下一步」

指挥 AI「给风控加 L1 Redis 热读」合理吗?