GeekIBLi

Redis操作为什么是原子性的?

2021-09-14

Redis原则性操作

对Redis来说,执行get、set以及eval等API,都是一个一个的任务,这些任务都会由Redis的线程去负责执行,任务要么执行成功,要么

执行失败,这就是Redis的命令是原子性的原因。

Redis本身提供的所有API都是原子操作,Redis中的事务其实是要保证批量操作的原子性。

事务命令

MULTI 、 EXEC 、 DISCARD 和 WATCH 是 Redis 事务相关的命令。事务可以一次执行多个命令, 并且带有以下两个重要的保证:

  • 事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
  • 事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。

Discard:Redis Discard 命令用于取消事务,放弃执行事务块内的所有命令。

1
2
3
4
5
6
如何开启一个事务
watch key1 key2 . . . (监听相关key)
multi (开启事务)
// 对监听key的一些操作
exec(执行事务)
discard(取消事务)

EXEC 命令负责触发并执行事务中的所有命令:如果客户端在使用 MULTI 开启了一个事务之后,却因为断线而没有成功执行 EXEC ,那么事务中的所有命令都不会被执行。

另一方面,如果客户端成功在开启事务之后执行 EXEC ,那么事务中的所有命令都会被执行。

如果redis备份采用的是AOF的方式,事务执行一半被终止,会怎样?

当使用 AOF 方式做持久化的时候, Redis 会使用单个 write(2) 命令将事务写入到磁盘中。

然而,如果 Redis 服务器因为某些原因被管理员杀死,或者遇上某种硬件故障,那么可能只有部分事务命令会被成功写入到磁盘中。

如果 Redis 在重新启动时发现 AOF 文件出了这样的问题,那么它会退出,并汇报一个错误。

使用 redis-check-aof 程序可以修复这一问题:它会移除 AOF 文件中不完整事务的信息,确保服务器可以顺利启动。

从 2.2 版本开始,Redis 还可以通过乐观锁(optimistic lock)实现 CAS (check-and-set)操作,具体信息请参考文档的后半部分。

如果是集群下,watch命令有没有什么局限性?

有没有想过为什么监听多个落在不同节点上的key,不同槽位的也不可以,会不被允许?在单节点下,Redis单线程执行,能够保证原子性,但在不同节点下,就是多进程多线程的问题,Watch自然就不能用。

参考资料

Tags: Redis