Redis奇幻之旅(三)9. Redis事务

9. Redis事务

9.1 Redis事务基本原理

​ 基本上数据库都会有事务这个概念,像Mysql的事务就满足ACID特性,但是Redis的事务并不是这样。Redis事务的本质是一组命令的集合。事务支持一次执行多个命令,一个事务中所有命令都会被序列化。在事务执行过程,会按照顺序串行化执行队列中的命令,其他客户端提交的命令请求不会插入到事务执行命令序列中。

​ Redis事务没有隔离级别的概念,批量操作在发送 EXEC 命令前被放入队列缓存,并不会被实际执行,所以就不存在事务内的查询要看到事务里的更新,事务外查询不能看到。

​ Redis不保证事务原子性,且没有回滚。事务中任意命令执行失败,其余的命令仍会被执行。

​ Redis的事务包含三个阶段:事务开始,命令入队,执行事务。

9.2 事务开始

​ MULTI命令标志着事务的开始。这个命令在内部实现上来说就是将客户端的flags(在《3.1.1.2 客户端参数说明》章节中有提及)切换成事务状态。这时,对于Redis服务端来说,这个客户端已经进入了事务状态。

9.3 命令入队

​ 当客户端处于非事务状态时,客户端发送的命令会被Redis服务端立即执行。但客户端处于事务状态的时候,服务端只会立即执行EXEC、DISCARD、WATCH、MULTI这四个命令中的一个,至于其他命令则会以FIFO的方式放在一个multiCmd类型的数组里。

​ EXEC:提交本次入队的所有命令

​ DISCARD:删除所有入队的命令

​ WATCH:报错,(error) ERR WATCH inside MULTI is not allowed

​ MULTI:报错,(error) ERR MULTI calls can not be nested

9.4 执行事务

​ 当客户端执行EXEC的时候就回将数组内的所有命令执行,并全部返回执行情况。除此之外,EXEC还会释放客户端的事务状态(即:修改flags)、清空命令计数器、释放事务队列。

9.5 Watch机制

​ WATCH命令是一个乐观锁(CAS机制),它可以在EXEC命令执行前,监视Redis Key,如果在EXEC执行前,监视的key被修改了(哪怕只有一个被修改)那么服务器会拒绝执行此事务,并返回一个事务执行失败的空回复。

​ 当我们使用WATCH去监控一个Key的时候,其实是将这个Key放在了watched_keys字典里(在《1.4 Hash》章节中最前面有提及),这个字典的键是某个被WATCH命令监视的Key,值是一个链表结构记录了所有监视相应Key的客户端。

​ 当一些修改命令被执行,例如:SET、SADD、DEL等等,执行后都会对watched_keys字典进行检查,如果有客户端正在监视被修改的Key,那么客户端的flags将会从事务状态切换成键被修改状态,这时执行EXEC就会失败。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
禁止转载,如需转载请通过简信或评论联系作者。

推荐阅读更多精彩内容