
1) 【一句话结论】采用“分布式事务(Saga模式)+ 消息队列异步同步 + 分布式锁/版本号保障强一致性”的混合方案,通过本地事务写入数据后,先发送同步消息,接收方通过事务检查版本/锁,确保跨校区排课、成绩数据最终一致且无冲突。
2) 【原理/概念讲解】
老师:咱们先讲核心概念,分布式事务是解决跨节点数据一致性的关键。比如“两阶段提交(2PC)”,但实际复杂,所以常用Saga模式——把业务流程拆成多个本地事务,失败时用补偿事务回滚,像多人写日记,每步同步后失败就撤销。
再比如消息队列,异步解耦,校区A写入排课后,先存队列再派送,允许延迟但最终送达,像快递中转站。
还有分布式锁(如Redis锁)和版本号,本地事务写入后加锁,更新时检查版本是否一致,避免并发冲突,像抢票时加锁,确保同一时间只有一个校区修改。
类比:分布式事务像多人写同一本日记,每写一句都要同步步骤,失败就撤销;消息队列像快递,先存中转站,再派送,允许延迟但最终送达。
3) 【对比与适用场景】
| 模型 | 定义 | 特性 | 适用场景 | 注意点 |
|---|---|---|---|---|
| 分布式事务(Saga) | 通过本地事务+补偿事务保证最终一致性 | 强一致性保障,失败可回滚 | 业务流程可拆分(如排课:创建→通知→更新状态) | 补偿逻辑复杂,可能出错 |
| 消息队列(最终一致性) | 异步消息传递数据,接收方处理 | 最终一致性,延迟低 | 数据量大异步处理(如成绩上报) | 需幂等性,避免重复处理 |
| 分布式锁+版本号 | 本地事务写入后加锁,更新时检查版本 | 强一致性,避免并发冲突 | 高并发场景(如同时修改排课) | 锁竞争,网络分区死锁风险 |
4) 【示例】
伪代码(校区A写入排课+校区B消费):
校区A写入排课:
def write_schedule(teacher_id, class_id, time):
with db.transaction():
db.execute("INSERT INTO schedule (teacher_id, class_id, time) VALUES (?, ?, ?)", (teacher_id, class_id, time))
send_message("schedule_sync", {"action": "update", "data": {"teacher_id": teacher_id, "class_id": class_id, "time": time}})
return "success"
校区B消费消息:
def consume_schedule_message(message):
data = message["data"]
with db.transaction():
version = db.query("SELECT version FROM schedule WHERE teacher_id = ? AND class_id = ?", (data["teacher_id"], data["class_id"]))
if version and version["version"] == data["version"]:
db.execute("UPDATE schedule SET ... WHERE ...", (data["teacher_id"], data["class_id"],))
else:
# 版本冲突,重试或忽略
pass
5) 【面试口播版答案】
面试官,您好。针对跨校区排课和成绩数据同步,我设计的方案是采用“分布式事务(Saga模式)结合消息队列异步同步,并辅以分布式锁和版本号机制”来保证数据一致性。具体来说,当校区A需要更新排课信息时,首先通过本地事务将数据写入本地数据库,然后发送一条同步消息到消息队列;校区B消费消息时,会先检查数据的版本号或加分布式锁,确保同一时间只有一个校区处理同一数据,避免冲突。如果消息处理失败,可以重试或通过补偿事务回滚,最终确保排课和成绩数据在多校区间同步且无冲突。
6) 【追问清单】
7) 【常见坑/雷区】