弃之如可惜,食之无所得
一.Redis事务简述
Redis的事务是下面4个命令来实现
1.multi,开启Redis的事务,置客户端为事务态。
2.exec,提交事务,执行从multi到此命令前的命令队列,置客户端为非事务态。
3.discard,取消事务,置客户端为非事务态。
4.watch,监视键值对,作用时如果事务提交exec时发现监视的监视对发生变化,事务将被取消。
将是否有watch命令分为普通类型事务和CAS(Check And Set)类型事务,无watch命令的为普通类型事务,有watch命令的为CAS类型事务,下面为普通类型事务演示
事务失败的原因可以分为静态错误(如不存在的命令)和运行时错误(如cas错误、对string用lpop操作)。静态错误会在提交exec时返回错误信息,使事务不能执行,而除cas以外的运行时错误不会阻止事务继续执行。
为方便后面的理解,可以勉强将Redis状态分为四种,普通状态、正常事务状态、CAS错误事务状态和静态错误事务状态,这四种状态在Redis源码中用3个状态位(REDIS_MULTI、REDIS_DIRTY_CAS、REDIS_DIRTY_EXEC)来标识,下面是个状态转换图。
当Redis处于事务态时,除multi、exec、discard和watch以外的所有命令皆会放到事务队列,向客户端返回QUEUED。
二.Redis事务实现
1.普通类型事务
Redis的事务实现比较简单,真的可以理解为"一个打包的批量执行脚本"。
当用户输入multi命令时,用户将本客户端标识位REDIS_MULTI置为1,所有的命令将会检查这个标识位,如果为1则将命令放到本客户端的命令队列中,如果非1则将命令直接执行。
每个客户端redisClient中皆有一个结构体存储着本客户端命令队列的状态,结构体如下:
typedef struct multiState {
/*命令组成的数组*/
multiCmd *commands;
/*命令的个数*/
int count;
} multiState;
每个命令有下面的结构体标识
typedef struct multiCmd {
/*命令的参数*/
robj **argv;
/*命令的参数个数*/
int argc;
/*命令的指针*/
struct redisCommand *cmd;
} multiCmd;
我们上面演示事务的例子在Redis中的示例
当客户端输入exec,将commands数组执行一边,整个事务就完成了,是不是简单的快哭了。
如果用户在正常事务态输入错误的命令,Redis会将对应客户端置为静态错误事务状态,在代码中表现为将用户端redisClient的REDIS_DIRTY_EXEC标识位置为1;如果用户watch的key变化,将变为CAS错误事务状态,在代码中表现为将用户端redisClient的REDIS_DIRTY_CAS标识位置为1。当用户exec提交事务时,Redis首先检测用户这两个标志位,任何一个被置为1,则不执行队列中的命令,直接给用户返回错误。
exec提交事务以后,会调用discard进行清理,包括重置标志位,释放所有事务状态相关的资源(释放命令队列、参数等)。
2.CAS类型事务
CAS类型事务整个的事务执行逻辑和普通类型事务一样,只不过在普通类型事务增加watch功能而已。
watch功能相当于乐观锁,用户在进入事务态之前,监控任意数量的数据库键,当提交事务时,检测这些键是否被更改。如果被更改则拒绝用户的事务,并返回用户空数据。
在代码中实现即为事务提交前会检测用户端redisClient的REDIS_DIRTY_CAS标识位。
每个RedisDB都保存一个watched_keys的字典,key为数据库键,value为用户端redisClient,当“触碰”一个key时,此key对应的value(即redisClient)的REDIS_DIRTY_CAS将置为1,value中存储的这个/这些客户端在执行 exec 时事务将失败,下图为watched_keys在Redis中的示例。
当其他客户端更新此数据库的year时将导致客户端clientA和clientC的事务提交失败,代码实现即为遍历year的value链表,将链表中的redisClient的REDIS_DIRTY_CAS将置为1。
三.总结
Redis的事务还比较原始,加之Redis的持久化容忍数据丢失,阻挡利用事务来达到精确数据操作的业务。
Redis的不支持回滚更是硬伤,这也导致很多人认为Redis的事务并不满足事务原子性。
- 大小: 18.4 KB
- 大小: 41 KB
- 大小: 27.8 KB
- 大小: 19.7 KB
分享到:
相关推荐
redis64-2.6.12.1.rar redis64-2.6.12.1.rar redis64-2.6.12.1.rar
redis-5.0.5.redis-5.0.5.redis-5.0.5.redis-5.0.5.redis-5.0.5.redis-5.0.5.redis-5.0.5.redis-5.0.5.redis-5.0.5.redis-5.0.5.redis-5.0.5.redis-5.0.5.redis-5.0.5.redis-5.0.5.redis-5.0.5.redis-5.0.5.redis-...
redis-5.0.14-1.el7.remi.x86_64.rpm安装包(含有部署手册) redis-5.0.14-1.el7.remi.x86_64.rpm安装包(含有部署手册) redis-5.0.14-1.el7.remi.x86_64.rpm安装包(含有部署手册) redis-5.0.14-1.el7.remi.x86_64.rpm...
tomcat-redis-session-manager-1.2-tomcat-7-java-7tomcat-redis-session-manager-1.2-tomcat-7-java-7tomcat-redis-session-manager-1.2-tomcat-7-java-7tomcat-redis-session-manager-1.2-tomcat-7-java-7tomcat-...
redis2-nginx-module-0.15
tomcat-redis-session-manager-2.0.0.jar jedis-2.5.2.jar commons-pool2-2.2.jar 2.修改 conf 目录下的 context.xml 文件 host="localhost" port="6379" database="0" maxInactiveInterval="60" /> ...
redis-stack-server-7.2.0-v9.arm64.snap redis-stack-server-7.2.0-v9.bionic.arm64.tar.gz redis-stack-server-7.2.0-v9.bionic.x86_64.tar.gz redis-stack-server-7.2.0-v9.bullseye.x86_64.tar.gz redis-stack-...
redis校验工具redis-full-check,配合redis-shake使用!!!
redis++使用说明,windows下编译redis-plus-plus
jizq-redis-mqjizq-redis-mqjizq-redis-mqjizq-redis-mqjizq-redis-mqjizq-redis-mqjizq-redis-mqjizq-redis-mqjizq-redis-mqjizq-redis-mqjizq-redis-mqjizq-redis-mqjizq-redis-mqjizq-redis-mqjizq-redis-mqjizq-...
windows系统redis安装文件,Redis-x64-3.0.504(稳定版);Redis-x64-3.2.100(预发行版);redis-desktop-manager-0.9.3.817(redis界面工具)。具体安装方法详见:...
tomcat-redis-session-manager-2.0.0.jar
根据《Redis笔记-尚硅谷周阳V1.3》整理,脑图、思维导图xmind
RedisPlus是为Redis可视化管理开发的一款开源免费的桌面客户端软件,支持Windows 、Linux、Mac三大系统平台,RedisPlus提供更加高效、方便、快捷的使用体验,有着更加现代化的用户界面风格。该软件支持单机、集群...
windows环境 redis服务免安装 附带redis客户端 redis-desktop-manager-0.8.8.384
该包中包括 linux 环境的安装包; 桌面管理工具 redis-desktop-manager ; 学习笔记; redis.conf 中文文档
Redis-x64-5.0.10.msi
压缩文件包括tomcat-redis-session-manager-master-2.0.0.jar、jedis-2.7.3.jar、commons-pool2-2.3.jar三个jar包使用方法请参照https://github.com/jcoleman/tomcat-redis-session-manager。apache-tomcat-8.5.33....
Tomcat8亲测可用 tomcat-redis-session-manager的jar包 修改了tomcat-redis-session-manager源码进行的编译生成的jar包