面试题答案
一键面试WATCH命令在保证数据一致性方面的作用
- 乐观锁机制:WATCH命令为Redis事务提供了乐观锁机制。在多客户端并发访问的场景下,它可以确保在事务执行期间,被监控的数据没有被其他客户端修改。如果在事务执行前,被监控的数据发生了变化,那么事务将不会执行,从而避免了数据冲突,保证了数据一致性。
- 多步操作一致性:在一些需要基于当前数据状态进行多步操作的场景中,例如先读取数据,然后根据读取的数据进行计算再写入新数据。使用WATCH可以保证在读取数据到事务执行这段时间内,数据没有被其他客户端修改,使得整个多步操作基于相同的数据状态,进而保证了数据一致性。
底层对数据监控的实现
- 数据结构:Redis使用了一个叫做
watched_keys
的字典来记录被监控的键。这个字典以客户端为键,以该客户端所监控的键的集合为值。当客户端执行WATCH key1 key2...
命令时,Redis会将这些键添加到该客户端对应的watched_keys
集合中。 - 触发监控:每次对数据库进行写操作(如SET、DEL等命令)时,Redis不仅会执行写操作,还会检查
watched_keys
字典。如果发现有客户端监控了即将被修改的键,那么Redis会将这些客户端标记为脏(dirty),意味着这些客户端的事务可能会因为数据变化而无法执行。
被监控数据变化时Redis对事务的处理
- 事务队列正常入队:当被监控的数据发生变化后,执行
MULTI
命令时,事务的命令仍然会正常入队,因为此时Redis还不知道事务最终是否能执行成功。 - EXEC执行判断:当执行
EXEC
命令时,Redis会检查客户端是否为脏状态。如果客户端被标记为脏,说明被监控的数据在事务开始后发生了变化,那么EXEC
命令将返回nil
,事务中的所有命令都不会被执行,从而保证了数据的一致性。而如果客户端没有被标记为脏,那么事务中的命令会按照顺序依次执行。