
采用微服务拆分订单、库存、支付模块,通过消息队列解耦,结合最终一致性(Saga模式)保证交易一致性,利用缓存+分布式锁优化性能,数据库分库分表提升吞吐,并设计多级容灾方案(主备切换、数据同步)。
老师:设计高并发支付系统,核心是解耦与一致性。首先,订单、库存、支付属于不同业务逻辑,需拆分为独立微服务(如订单服务、库存服务、支付服务),避免单点故障。
| 方案 | 定义 | 特性 | 使用场景 | 注意点 |
|---|---|---|---|---|
| 2PC | 两阶段提交 | 强一致性,阻塞调用 | 需强一致性(如核心金融交易) | 阻塞问题,单点故障风险 |
| Saga | 最终一致性+补偿 | 非阻塞,可恢复 | 高并发,允许短暂不一致 | 补偿逻辑复杂,可能死锁 |
| TCC | 尝试-确认-取消 | 最终一致性,低阻塞 | 需原子性(如库存扣减) | 业务逻辑复杂,需幂等性保证 |
(注:高并发场景优先选Saga/TCC,避免2PC阻塞。库存扣减用TCC模式:Try扣减库存,Confirm释放,Cancel回滚。)
用户下单流程(伪代码):
订单服务:
def create_order(user_id, product_id, amount):
order_no = generate_order_no()
# 分布式锁保证库存扣减原子性
lock = redis.setnx(f"stock_lock_{product_id}", user_id, ex=10) # 超时10秒
if lock:
inventory = get_inventory_from_cache(product_id) # 从缓存查库存
if inventory >= amount:
set_inventory(product_id, inventory - amount) # 扣减库存
# 发送支付消息
send_message("payment_queue", order_no, amount)
save_order(order_no, user_id, product_id, amount, "待支付")
return order_no
else:
release_lock(f"stock_lock_{product_id}", user_id)
return "库存不足"
else:
return "并发冲突"
支付服务:
def process_payment(order_no):
order = get_order_from_cache(order_no) # 从缓存查订单
if order.status == "待支付":
payment_result = call_payment_gateway(order.amount) # 调用支付网关
if payment_result == "success":
update_order(order_no, "已支付")
# 发送库存补偿消息
send_message("inventory_queue", order_no, order.product_id)
else:
update_order(order_no, "支付失败")
库存服务(补偿逻辑):
def release_inventory(order_no):
order = get_order_from_cache(order_no)
if order.status == "支付失败":
add_inventory(order.product_id, order.amount) # 补偿加回库存
(约80秒)
面试官您好,设计高并发支付系统,核心思路是微服务拆分+消息队列解耦+最终一致性保障。具体来说:
订单服务创建订单后,调用库存服务扣减库存(Redis分布式锁保证原子性),成功后发送支付消息;支付服务消费消息后调用支付网关,成功则更新订单并通知库存释放库存。关键技术包括Redis分布式锁(解决并发库存冲突)、消息队列(削峰填谷)、缓存(提升读性能),数据库分库分表提升吞吐。容灾方面,主库故障时自动切换备库,数据通过日志同步,消息队列持久化确保不丢失。这样既能保证秒级响应,又能保证订单-库存-支付的一致性。
问:分布式事务具体怎么实现?比如Saga模式的具体补偿流程?
回答:Saga模式通过消息队列传递补偿指令,每个步骤失败后触发补偿(如支付失败则库存加回,订单状态回滚)。
问:库存扣减的原子性如何保证?如果分布式锁超时怎么办?
回答:用Redis SETNX加超时时间,超时后释放锁并通知重试;若超时导致库存扣减失败,补偿机制会回滚。
问:消息队列的可靠性如何保障?比如消息丢失或重复消费?
回答:消息队列持久化存储(如RocketMQ事务消息),消费端幂等处理(如根据订单号判断是否重复消费)。
问:缓存雪崩如何处理?比如库存缓存全过期?
回答:设置合理缓存过期时间,并采用热点数据预热;若缓存雪崩,本地缓存+数据库双写保证可用性。
问:数据库分库分表后,分布式事务如何处理?比如Seata的实现?
回答:使用Seata的AT模式,将本地事务和全局事务结合,保证跨服务事务的原子性(如订单创建与库存扣减)。