1. Redis 事务介绍
Redis 的事务和 MySQL 的事务概念上是类似的,不过也有一定区别:
- 弱化的原子性:Redis 没有 “回滚机制”,只能批量执行操作,但如果其中一个操作失败,不会恢复到初始状态。
- 不保证一致性:不涉及 “约束” 也无回滚机制。与 MySQL 事务运行前后结果都合理有效、不会出现中间非法状态不同,Redis 在这方面没有类似严格保证。
- 不需要隔离性:由于 Redis 单线程处理请求,不会并发执行事务,所以不存在隔离级别相关问题。
- 不需要持久性:数据保存在内存中,是否开启持久化由 redis - server 自身决定,和事务无关。
Redis 事务通过 MULTI
命令开启,此后客户端发送的命令不会立即执行,而是被存入一个事务队列中。当客户端发送 EXEC
命令后,服务器才会顺序执行事务队列中的所有命令。在此期间,由于 Redis 是单线程处理请求,所以这些操作是连续执行的,不会被其他客户端的请求 “加塞”,保证了事务队列内操作执行的连贯性
2. 相关命令
MULTI:开启事务,标志着后续命令进入事务队列,暂不执行,返回OK
EXEC:执行事务队列中的所有命令,在 MULTI 之后、EXEC 之前入队的命令会顺序执行
DISCARD:取消事务,清除事务队列中的所有命令,客户端回到非事务状态,返回OK
执行 EXEC 之后事务中的命令才会被执行
WATCH:用于在事务开始前监控一个或多个键。若在 EXEC 执行前,被监控的键至少有一个被修改,事务将被取消
UNWATCH:取消所有被 WATCH 监控的键,一般在 EXEC 执行后或事务取消后使用,避免不必要的监控资源占用。
WATCH 的实现原理:Redis 为每个数据维护了一个watched_keys
字典,字典的键是被监视的键,值是一个链表,链表中记录了所有监视这个键的客户端,当某个客户端使用 WATCH 命令监视某个键的时候,如果键发生修改,对应的表示位也会被修改,当客户端执行 EXEC
命令时,Redis 会检查客户端的 REDIS_DIRTY_CAS
标志位,如果标志位为 1,说明被监视的键在事务开启后被修改过,Redis 会取消该事务,不执行事务队列中的任何命令,并返回 (nil)
给客户端