第4章:并发模型与Akka
Akka 是 Scala 生态中最成熟的并发与分布式框架,面试官通过本章考察你对 Actor 模型的理解、消息传递的线程安全、监督树容错机制以及实际项目中的调优能力。本章结构化拆解高频试题与项目案例,帮助你在 30 分钟内掌握核心回答框架。
面试问答卡片
面试问题:Akka 中 Actor 模型与共享内存并发模型的本质区别是什么?
| 面试官考察点 | 是否理解消息驱动 vs 共享状态、线程安全来源、无锁编程思想 |
|---|---|
| 回答框架 |
|
| 示例回答 | Actor 模型每个实例拥有私有状态,外部只能通过不可变消息与其交互;内部串行处理消息,天然避免竞态条件。例如订单 Actor 只接收“创建/支付”消息,无需锁即可保证状态一致性。 |
| 可能追问 | “消息有序性如何保证?” “如果 Actor 处理消息速度慢于发送,如何背压?” |
| 避坑提醒 | 不要陷入“Actor 完全不需要锁”的误区 – 跨 Actor 查询可能需要 Future 和回调,仍要注意线程安全。 |
面试问题:tell 和 ask 的适用场景及性能差异?
| 面试官考察点 | 是否区分异步/同步通信、消息丢失处理、Future 开销 |
|---|---|
| 回答框架 |
|
| 示例回答 | 在实时推荐项目中,对用户行为日志使用 tell 记录,避免阻塞;当需要查询用户画像时使用 ask,设置超时 3s,配合 recover 降级兜底。 |
| 可能追问 | “ask 的超时如何设置?” “ask 内部临时 Actor 的生命周期如何管理?” |
| 避坑提醒 | 不要在 ask 的 Future 内直接访问 Actor 内部可变状态,容易引发线程安全问题。 |
面试问题:Akka 的监督策略有哪些?如何选择?
| 面试官考察点 | 容错设计思路、监督树层次、重启/停止/升级策略 |
|---|---|
| 回答框架 |
|
| 示例回答 | 支付系统中,交易 Actor 失败使用 Restart 重置状态,但日志 Actor 失败仅 Resume;如果数据库连接 Actor 崩溃,使用 AllForOne 停掉所有相关 Actor 并向上 Escalate 报警。 |
| 可能追问 | “Restart 时 Actor 的 preRestart 和 postRestart 如何用?” “Escalate 后父 Actor 如何处理?” |
| 避坑提醒 | 不要对临时异常启用 Stop,会导致消息丢失;尽量使用 Restart 保留邮箱。 |
项目案例模板:实时风控规则引擎
| 项目名称 | 实时风控规则引擎(基于 Akka Cluster) |
|---|---|
| 业务背景 | 为电商平台提供毫秒级交易风控检测,根据用户行为、设备指纹、历史订单等实时决策是否拦截交易。 |
| 规模指标 |
|
| 技术栈 | Scala 2.13、Akka Cluster / Persistence、Akka HTTP、Redis、Kafka、Prometheus + Grafana |
| 核心难点 |
|
| 面试高频追问 |
|
| 可迁移回答话术 | “我在风控项目中采用了层级监督+FSM状态机设计:父Actor负责路由,子Actor执行规则匹配;热更新通过集群PubSub广播新版FSM配置,每个Worker在安全点切换状态,延迟控制在10ms内。” |
大厂模拟面试
面试官:“你在项目中使用 Akka Cluster 时,如何解决跨节点 Actor 的消息可靠投递问题?”
候选人回答:
普通答案:“我们使用了 Akka Cluster 自带的远程通信机制,设置一定的重试次数,消息就不会丢。”
❌ 缺乏具体实现和边界情况分析。
优秀答案:“我们采用 Akka Cluster Sharding 搭配 At-Least-Once Delivery 模式。发送端使用带有确认的重试,接收端通过幂等性去重,业务层用 Akka Persistence 记录发送状态。同时设置了死信监控告警,发现丢失立即补偿。”
✅ 提到关键组件和去重保障。
专家答案:“我们分层设计:底层使用 Akka Cluster Sharding 保证消息路由到正确的 Actor;中间层封装了 Reliable Delivery 模块,基于事件溯源记录每个消息的 deliveryId,接收方确认后移除;超时未确认的重新投递,但业务侧必须幂等(以订单号+事件类型作为唯一键)。对于实时性要求高的场景(如支付),还引入了 Kafka 作为两者之间的缓冲,Akka 只处理状态机逻辑,Kafka 保证持久化与顺序。”
💡 给出分层架构 + 幂等 + Kafka 兜底,体现系统设计深度。
面试官追问:“这种方案里,如何保证消息顺序?如果重试时顺序错乱导致业务异常如何处理?”
专家回答思路:“使用同一个 Cluster Sharding 的消息单线程 Actor 保证顺序;如果重试消息到达时顺序错乱,Actor 内维护 version 或 sequence number 校验,乱序消息放入暂存队列等待补序,超时后视为异常并触发补偿事务。”