面试题答案
一键面试相同点
- 目的一致:WATCH命令与其他常见分布式锁机制(如SETNX)的核心目的都是确保在分布式环境下,同一时间只有一个客户端能够执行特定的关键操作,防止并发冲突,保障数据的一致性和正确性。
- 基于共享资源:它们都依赖于Redis这样的共享资源来实现分布式协调,利用Redis的单线程模型和原子操作特性来保证锁的操作具有原子性。
不同点
- 实现方式
- WATCH命令:WATCH命令是通过乐观锁机制实现,它监控一个或多个键,在执行事务时,如果被监控的键在WATCH之后被其他客户端修改,事务将被打断不会执行。它不是传统意义上的加锁操作,更像是一种数据变化的监听机制。
- SETNX:SETNX(SET if Not eXists)是典型的悲观锁实现方式,通过在Redis中设置一个特定的键值对来表示锁,只有当这个键不存在时才能设置成功,以此获取锁。若键已存在则获取锁失败,后续操作需等待锁释放。
- 锁的粒度
- WATCH命令:锁的粒度相对较粗,它监控的是键,一旦键被修改,整个事务都会受到影响。如果多个事务操作不同的字段但属于同一个键,可能会出现不必要的事务回滚。
- SETNX:锁的粒度可以很细,通过设置不同的键来表示不同的锁,每个锁可以独立控制,适用于对不同资源分别加锁的场景。
- 死锁处理
- WATCH命令:本身不会产生死锁,因为它是基于乐观锁机制,只有在事务执行时发现数据变化才会回滚,不存在锁一直被持有不释放的情况。
- SETNX:如果获取锁的客户端出现异常崩溃等情况,没有主动释放锁,就可能导致死锁。通常需要设置锁的过期时间来避免死锁,但这又可能带来锁提前过期的风险。
- 并发性能
- WATCH命令:在高并发场景下,如果数据冲突较少,乐观锁机制的WATCH命令性能较高,因为它不需要等待锁,客户端可以先进行操作,只有在提交事务时才检查数据是否被修改。
- SETNX:由于是悲观锁,每次操作都需要先获取锁,在高并发场景下可能会出现大量的等待,性能相对较低。
适用场景
- 优先选择WATCH命令
- 读多写少场景:例如商品展示页面,大部分操作是读取商品信息,偶尔会有更新操作。在这种场景下,数据冲突概率低,使用WATCH命令可以提高并发性能,减少锁等待时间。
- 复杂事务操作:当需要对多个键进行关联操作,且操作具有一定的原子性要求,但又不想使用传统悲观锁带来的性能损耗时,WATCH命令可以在监控多个键的同时,保证事务执行的原子性。比如在电商库存和订单的关联操作中,先读取库存和订单信息,然后根据业务逻辑进行更新,若在读取后库存或订单信息被其他操作修改,事务回滚,确保数据一致性。
- 优先选择其他分布式锁机制(以SETNX为例)
- 写多读少场景:如电商的秒杀活动,主要是对库存进行减操作,写操作频繁。此时使用SETNX这种悲观锁可以有效防止多个客户端同时修改库存导致超卖等问题,虽然性能可能不如WATCH命令,但能保证数据的绝对一致性。
- 对锁粒度要求精细场景:在分布式文件系统中,每个文件或目录都需要独立的锁控制,SETNX可以为每个文件或目录设置独立的锁键,方便对不同资源进行细粒度的锁管理。