架构风格与模式58 条

Actor 模型

每个 Actor 拥有私有状态与邮箱,按顺序处理消息;Actor 之间只通过消息交互,可形成监督树实现故障隔离,适合高并发有状态场景。

Actor 模型怎么并发

Actor 模型把并发单元从线程换成 Actor:每个 Actor 拥有私有状态和自己的邮箱,消息按到达顺序串行处理,Actor 之间只通过异步消息交互。由于状态不共享,模型层面消除了数据竞争,并发控制收敛到消息顺序上。故障处理靠监督树:父 Actor 按策略决定重启、停止还是上报子 Actor 的失败,从而把故障限制在局部。

基本信息

核心约束状态不共享,消息异步传递,单 Actor 内串行处理
故障处理监督策略:重启、停止、上报
实现Akka、Erlang/OTP、Orleans 等
邮箱语义多数实现保证至少一次投递,跨节点不保证顺序,业务侧需幂等

典型使用场景

  • 高并发有状态服务:会话、设备连接与在线状态管理
  • 实时计算:事件流按实体分发到对应 Actor 串行处理
  • 电信与游戏后端:单实体高并发、低延迟且需局部故障隔离
  • 消息驱动的网关:把协议解析与业务处理拆成不同 Actor 层级
  • 长生命周期状态:Actor 常驻内存并在故障后由监督者重建

消息处理示意(伪代码)

消息处理示意(伪代码)
actor Counter {
  state n = 0            // 私有状态
  on Inc(delta) { n += delta; reply n }
  on Snapshot() { save(n) }
}
// 消息按到达顺序处理;跨 Actor 只发消息,不直接读其状态

与其他并发模型对照

模型并发控制手段主要风险
Actor消息顺序 + 监督树邮箱积压、消息协议不兼容
共享内存加锁互斥锁与原子操作死锁、竞态、锁粒度难调
CSP/通道通道传递数据,协程阻塞等待通道阻塞与泄漏
事件循环单线程串行 + 回调阻塞调用拖垮整个循环

使用要点

  • Actor 内部不要阻塞等待外部调用,否则邮箱迅速积压;改为异步消息加未来的回复路径
  • 消息协议要带版本,升级期间新旧 Actor 可能同时存在
  • 监督策略要分层设计:不同重要级别的 Actor 走不同的重启与升级策略
  • 按实体键路由消息,保证同一实体的处理落在同一个 Actor 上以维持顺序
Actor 模型把并发控制收敛到消息顺序上,避免了共享内存锁,但需要设计好消息协议与监督层级,这两件事的工作量常被低估。
跨节点消息通常只保证至少一次投递:重复消息、乱序与丢失都要在业务侧用幂等与对账兜底,不要假设传输层会替你保证。

易错点

  • Actor 内部阻塞等待外部调用,邮箱迅速积压,表现为延迟持续上升直到内存耗尽
  • 消息协议无版本管理,升级期间新旧 Actor 不兼容,出现难以复现的处理错误
  • 监督策略一律重启:故障根因未修复时反复重启,形成风暴并掩盖真实问题
  • 无限增长的邮箱:缺少背压与限流,上游变快时下游只能堆积
  • 按随机路由分发需要顺序的消息,同一实体的消息落到不同 Actor,顺序被打乱

数据来源与参考

  • Carl Hewitt Actor 模型论文(1973)
  • Akka 官方文档
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌