`
OrangeHolic
  • 浏览: 260734 次
  • 来自: 北京
社区版块
存档分类
最新评论

Redis事务---那鸡肋一样的存在

 
阅读更多
弃之如可惜,食之无所得

一.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
分享到:
评论

相关推荐

    redis-stack-server 7.2.0 安装包合集

    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-...

    redis2-nginx-module-0.15

    - **事务处理**:能够执行 Redis 的事务,确保多个操作的原子性。 - **管道**:使用 Redis 的 Pipeline 技术,批量发送命令,减少网络延迟。 3. **配置使用** 在 NGINX 的配置文件中,通过 `set $redis_key ...

    tomcat-redis-session-manager-1.2-tomcat-7-java-7

    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-...

    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安装包(含有部署手册) redis-5.0.14-1.el7.remi.x86_64.rpm...

    redis-5.0.5.tar.gz

    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校验工具redis-full-check

    **Redis 全面检查工具:redis-full-check** Redis 是一款高性能的键值存储系统,广泛应用于缓存、数据库和消息中间件等场景。在实际应用中,为了确保 Redis 的稳定性和数据一致性,需要定期对 Redis 实例进行健康...

    Redis-x64-5.0.14.msi和Redis-x64-5.0.14.zip

    解压后,你可以找到包括`redis-server.exe`、`redis-cli.exe`等在内的可执行文件,以及配置文件`redis.conf`。这种方式适合于需要自定义配置或手动管理服务的用户。通过编辑`redis.conf`,你可以调整Redis的各项参数...

    tomcat-redis-session-manager-master-2.0.0

    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" /> ...

    redis64-2.6.12.1.rar 亲测好用

    2. **redis-server.exe**:这是Redis服务器的执行程序,用于启动和管理Redis服务。当您运行此程序并指定配置文件时,Redis服务器将开始监听网络连接并处理客户端请求。 3. **redis-cli.exe**:Redis命令行界面工具...

    redis++使用说明,windows下编译redis-plus-plus

    "Redis++使用说明,windows下编译Redis-Plus-Plus" 在这篇文章中,我们将详细介绍如何在Windows平台下编译Redis++,包括编译hiredis.lib和Win32_Interop.lib静态库文件的过程,然后安装Cmake并编译Redis++,最后...

    tomcat-redis-session-manager的jar包-包含Tomcat7和Tomcat8

    《深入理解Tomcat-Redis-Session-Manager:在Tomcat7和Tomcat8中的应用》 在现代Web应用程序开发中,session管理是一个至关重要的环节,它涉及到用户会话的持久化和跨请求的数据共享。传统的session管理方式在高...

    PyPI 官网下载 | redis-py-cluster-1.1.0.tar.gz

    《Redis-Py-Cluster:Python中的Redis集群库详解》 Redis-Py-Cluster是一个Python库,专门用于在Python环境中操作Redis分布式集群。该库为开发者提供了便捷的方式与Redis集群进行交互,支持各种数据结构,如字符串...

    Redis-x64-3.2.100.zip

    redis-serviceinstall .cmd安装成服务脚本(redis设置成windows下的服务,redis-serviceinstall .cmd脚本内容如下) redis-server --service-install redis.windows-service.conf --loglevel verbose redis-server -...

    redis-py-cluster-1.3.5.tar.gz

    `redis-py-cluster`库是Python连接Redis集群的客户端,它提供了简单易用的API,允许开发者执行常见的Redis操作,如设置和获取键值、执行事务、操作哈希表等。该库实现了CLUSTER指挥,如`CLUSTER NODES`和`CLUSTER ...

    Redis-x64-5.0.14.1

    这个名为"Redis-x64-5.0.14.1"的压缩包是Redis针对Windows操作系统的64位版本,版本号为5.0.14.1。在Windows上运行Redis可能与Linux环境有所不同,但仍然提供了相同的核心功能。 1. **Redis的特性**: - **内存...

    tomcat-redis-session-manager包集合下载(tomcat8)

    【标题】"tomcat-redis-session-manager包集合下载(tomcat8)"涉及的主要知识点是将Redis集成到Tomcat中管理会话(session),以提高Web应用的性能和可扩展性。 【描述】中提到的"所需的tomcat-redis-session-...

    jizq-redis-mq

    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-...

    关于 phpredis2.2.5-5.5 ts-vc11-x64 的分享版本

    PHPRedis 提供了丰富的 API,使得开发者能够通过 PHP 代码直接调用 Redis 的各种命令,如设置和获取键值、执行事务、操作集合、有序集合、哈希表等。由于是 C 扩展,它的性能相对较高,延迟较低,适合处理大量数据...

    redis-windows-7.2.4.zip

    - 解压"redis-windows-7.2.4.zip",找到`redis-server.exe`启动文件。 - 运行`redis-server.exe`,默认情况下,Redis监听6379端口。 - 可以通过配置文件`redis.windows.conf`修改默认设置,如端口、内存限制、...

Global site tag (gtag.js) - Google Analytics