1) 【一句话结论】
百万级QPS的银行支付系统需通过微服务拆分(支付网关、订单、支付、通知等)构建分布式架构,结合限流熔断保障稳定性,采用Saga模式(本地事务+幂等补偿事务)确保强一致性,并利用Redis锁、消息队列等实现数据一致性,同时强化资金安全与防重放机制。
2) 【原理/概念讲解】
- 架构设计:微服务拆分是核心,依据业务能力边界(如订单服务仅管理订单状态,支付服务仅负责银行扣款),通过API网关统一入口,负载均衡(如Nginx)分发请求,提升扩展性。类比:超市收银系统,各服务(收银台、支付机)独立,通过总台(API网关)协调,避免单点故障。
- 限流与熔断:限流控制请求速率,令牌桶算法(平滑流量波动,如电商需求周期性变化)和漏桶算法(防恶意攻击,如DDoS攻击)结合使用。熔断机制(如Hystrix):故障时快速失败,避免级联故障;恢复后通过健康检查检测服务是否正常。
- 分布式事务:银行支付需强一致性(订单与支付状态需同时成功/失败),Saga模式适用。拆分为本地事务(订单扣款、通知)和补偿事务(失败后退款),通过消息队列记录补偿任务,异步执行。
- 数据一致性:订单状态用Redis分布式锁(key=order:orderId,过期时间5秒)+数据库事务(确保原子性),支付结果通过消息队列(如Kafka)异步通知,避免阻塞,保证最终一致性。
3) 【对比与适用场景】
| 方案 | 定义 | 特性 | 使用场景 | 注意点 |
|---|
| Saga | 拆分为本地事务+补偿事务,异步执行,失败后补偿 | 最终一致性,性能高,适合高并发 | 银行支付(需强一致性,但可用性优先) | 补偿逻辑复杂,需保证补偿不丢失(如消息队列持久化) |
| 2PC | 两阶段提交,强一致性,阻塞高 | 严格ACID,但性能低 | 核心账务系统(如银行核心账本) | 事务失败时阻塞,影响性能 |
4) 【示例】
- 请求示例(JSON):
{
"requestId": "pay_20240101_001",
"userId": "user123",
"orderId": "order_20240101_001",
"amount": 100.00,
"payType": "alipay",
"notifyUrl": "https://example.com/notify"
}
- 支付服务伪代码:
- 验证请求参数(userId、orderId等)。
- 获取Redis分布式锁(key=order:order_20240101_001,过期时间5秒)。
- 检查订单状态(未支付),更新为“待支付”。
- 调用银行支付网关扣款(假设接口返回成功/失败)。
- 扣款成功:
- 更新订单状态为“已支付”。
- 通过消息队列(Kafka)发送通知(topic=order_notify,key=order_20240101_001)。
- 扣款失败:
- 释放锁(防止死锁)。
- 启动补偿事务:通过消息队列发送退款任务(topic=refund_task,key=order_20240101_001),消息头添加唯一标识(requestId)。
5) 【面试口播版答案】
“要设计百万级QPS的银行支付系统,核心是微服务拆分和分布式架构。首先,拆分为支付网关、订单服务、支付服务、通知服务,通过API网关统一入口,负载均衡分发。限流用令牌桶控制速率(平滑流量波动),漏桶算法防恶意攻击。熔断用Hystrix快速失败,避免级联故障。分布式事务用Saga模式,因为银行支付需强一致性,拆分为本地事务(订单扣款、通知)和幂等补偿事务(失败后退款),通过消息队列记录补偿任务。数据一致性上,订单状态用Redis分布式锁+数据库事务,支付结果异步通知。同时考虑资金安全(数据加密)、防重放(请求ID唯一),限流参数动态调整(根据系统负载实时修改令牌桶速率)。整体通过缓存、数据库分库分表提升性能,确保高可用和资金安全。”
6) 【追问清单】
- 问:微服务拆分时,如何确定服务边界?
答:根据业务能力,订单、支付、通知是独立业务,拆分为独立服务,避免职责交叉(如订单服务只管订单状态,支付服务只管银行扣款)。
- 问:限流参数如何动态调整?
答:根据系统负载(如CPU、内存使用率),实时计算令牌桶速率,比如负载低于80%时增加速率,高于90%时降低。
- 问:Saga补偿机制如何保证不重复执行?
答:消息队列消息头添加唯一标识(如requestId),补偿事务中检查该标识是否已处理,避免重复退款。
7) 【常见坑/雷区】
- 限流设置过松:导致系统过载,超卖或资源耗尽,影响资金安全。
- 熔断恢复策略错误:熔断后立即恢复,未检测服务是否恢复,故障持续,导致级联故障。
- 分布式事务选型不当:用2PC导致性能低,用Saga补偿逻辑复杂易丢失数据。
- 缓存未加锁:并发时重复扣款,资金错误(如两个请求同时获取锁,都扣款)。
- 消息队列积压未处理:导致延迟,用户等待时间过长,影响银行声誉。