面试题答案
一键面试基于分布式锁设计订单处理一致性机制
- 订单创建:
- 系统接收到创建订单请求,首先获取分布式锁。只有获取到锁的节点才能继续处理订单创建。
- 在创建订单过程中,插入订单记录到数据库,同时记录订单状态为“未支付”。完成后释放锁。
- 支付处理:
- 当支付请求到达,获取分布式锁。
- 验证订单状态为“未支付”,然后更新订单状态为“支付中”,调用支付接口进行支付操作。支付成功后,更新订单状态为“已支付”,释放锁。
- 库存变更:
- 支付成功后,获取分布式锁。
- 检查订单状态为“已支付”,从库存表中扣减相应商品库存。完成后释放锁。
不同分布式锁方案优劣及适用场景
- 基于Redis的分布式锁:
- 优点:
- 性能高:Redis基于内存操作,读写速度快,加锁和解锁操作性能优越,适合高并发场景。
- 实现简单:通过SETNX(SET if Not eXists)命令即可实现基本的分布式锁,并且可以利用Lua脚本来保证操作的原子性。
- 缺点:
- 可靠性问题:Redis单节点部署时,如果节点故障,锁会丢失。即使是集群部署,在主从切换过程中可能会出现锁的短暂不一致。
- 锁的过期时间:如果业务处理时间超过锁的过期时间,锁会自动释放,可能导致其他节点获取锁而产生数据一致性问题。
- 适用场景:适用于性能要求极高,对锁的短暂不一致有一定容忍度的场景,例如抢购活动等。
- 优点:
- 基于Zookeeper的分布式锁:
- 优点:
- 可靠性高:Zookeeper采用树形结构存储数据,通过临时顺序节点实现分布式锁,节点的创建和删除都有可靠的通知机制。即使部分节点故障,只要半数以上节点存活,集群就能正常工作,锁的可靠性高。
- 避免死锁:由于锁是基于节点的,节点的创建和删除有明确的逻辑,不会出现死锁情况。
- 缺点:
- 性能相对较低:Zookeeper的写操作需要半数以上节点确认,相比Redis基于内存的操作,性能会低一些。
- 实现复杂:需要处理节点的创建、监听、删除等复杂逻辑。
- 适用场景:适用于对数据一致性和可靠性要求极高,对性能要求相对不那么苛刻的场景,例如金融交易等。
- 优点:
处理锁的可靠性、容错性及性能之间的平衡
- 可靠性:
- Redis:可以采用Redlock算法,使用多个独立的Redis实例来获取锁,只有在大多数实例都成功获取锁时,才认为获取锁成功,提高可靠性。
- Zookeeper:利用Zookeeper自身的集群特性,通过增加节点数量来提高可靠性。同时,合理设置节点的选举机制和数据同步策略。
- 容错性:
- Redis:配置主从复制和哨兵机制,当主节点故障时,哨兵可以自动将从节点提升为主节点,保证系统的可用性。
- Zookeeper:通过半数以上节点存活即可正常工作的机制,天然具备较好的容错性。同时,可以设置节点的故障检测和自动恢复机制。
- 性能:
- Redis:合理设置锁的过期时间,避免业务处理时间过长导致锁过期问题。同时,可以采用缓存预热等技术,减少锁竞争。
- Zookeeper:优化节点的配置和网络拓扑,减少写操作的延迟。对于读多写少的场景,可以利用Zookeeper的读负载均衡特性提高性能。