• 技术文章 >数据库 >mysql教程

    Redis事务处理

    2016-06-07 16:33:40原创564

    Redis 在事务失败时不进行回滚,而是继续执行余下的命令 ,Redis 命令只会因为错误的语法而失败(并且这些问题不能在入队时发现)

    当前使用的redis版本

    #redis-cli -v
    redis-cli 2.6.4

    MULTI 、EXEC 、DISCARD 和WATCH 是 Redis 事务的基础

    1.MULTI 命令用于开启一个事务,它总是返回 OK 。
    MULTI 执行之后,客户端可以继续向服务器发送任意多条命令,这些命令不会立即被执行,而是被放到一个队列中

    2.EXEC 命令被调用时,所有队列中的命令才会被执行。

    +++++++++++命令 +++++++++++

    redis 192.168.1.53:6379> multi
    OK
    redis 192.168.1.53:6379> incr foo
    QUEUED
    redis 192.168.1.53:6379> set t1 1
    QUEUED
    redis 192.168.1.53:6379> exec
    1) (integer) 2
    2) OK

    +++++++++++对应的java代码 +++++++++++

    Jedis jedis = new Jedis("192.168.1.53", 6379);
    Transaction tx = jedis.multi();
    tx.incr( "foo");
    tx.set( "t1", "2");
    List result = tx.exec();

    if (result == null || result.isEmpty()) {
    System. err.println( "Transaction error...");
    return ;
    }

    for (Object rt : result) {
    System. out.println(rt.toString());
    }

    使用事务时可能会遇上以下两种错误:
    1.事务在执行EXEC 之前,入队的命令可能会出错。比如说,命令可能会产生语法错误(参数数量错误,参数名错误,等等),或者其他更严重的错误,比如内存不足

    (如果服务器使用 maxmemory 设置了最大内存限制的话)。

    2.命令可能在EXEC 调用之后失败。举个例子,事务中的命令可能处理了错误类型的键,比如将列表命令用在了字符串键上面,诸如此类。

    第一种错误的情况:
    服务器端:
    在 Redis 2.6.5 以前,Redis 只执行事务中那些入队成功的命令,而忽略那些入队失败的命令

    不过,从 Redis 2.6.5 开始,服务器会对命令入队失败的情况进行记录,并在客户端调用EXEC 命令时,拒绝执行并自动放弃这个事务。
    +++++++++++命令 +++++++++++

    redis 192.168.1.53:6379> multi
    OK
    redis 192.168.1.53:6379> incr foo
    QUEUED
    redis 192.168.1.53:6379> set ff 11 22
    (error) ERR wrong number of arguments for 'set' command
    redis 192.168.1.53:6379> exec
    1) (integer) 4

    因为我的版本是:2.6.4,所以Redis 只执行事务中那些入队成功的命令,而忽略那些入队失败的命令

    客户端(jredis):

    客户端以前的做法是检查命令入队所得的返回值:如果命令入队时返回 QUEUED ,那么入队成功;否则,就是入队失败。如果有命令在入队时失败,

    那么大部分客户端都会停止并取消这个事务。

    第二种错误的情况:

    至于那些在EXEC 命令执行之后所产生的错误,并没有对它们进行特别处理:即使事务中有某个/某些命令在执行时产生了错误,事务中的其他命令仍然会继续执行。

    +++++++++++命令+++++++++++

    redis 192.168.1.53:6379> multi
    OK
    redis 192.168.1.53:6379> set a 11
    QUEUED
    redis 192.168.1.53:6379> lpop a
    QUEUED
    redis 192.168.1.53:6379> exec
    1) OK
    2) (error) ERR Operation against a key holding the wrong kind of value

    +++++++++++对应的java代码 +++++++++++

    Jedis jedis = new Jedis("192.168.1.53", 6379);
    Transaction tx = jedis.multi();
    tx.set( "t1", "2");
    tx.lpop( "t1");
    List result = tx.exec();

    if (result == null || result.isEmpty()) {
    System. err.println( "Transaction error...");
    return ;
    }

    for (Object rt : result) {
    System. out.println(rt.toString());
    }

    Redis 在事务失败时不进行回滚,而是继续执行余下的命令
    这种做法可能会让你觉得有点奇怪,以下是这种做法的优点:
    1.Redis 命令只会因为错误的语法而失败(并且这些问题不能在入队时发现),或是命令用在了错误类型的键上面:这也就是说,从实用性的角度来说,,失败的命令是由编程错误造成的,而这些错误应该在开发的过程中被发现,而不应该出现在生产环境中。
    2.因为不需要对回滚进行支持,所以 Redis 的内部可以保持简单且快速。

    鉴于没有任何机制能避免程序员自己造成的错误,并且这类错误通常不会在生产环境中出现,所以 Redis 选择了更简单、更快速的无回滚方式来处理事务。

    3.DISCARD 命令时,事务会被放弃,事务队列会被清空,并且客户端会从事务状态中退出
    +++++++++++命令 +++++++++++

    redis 192.168.1.53:6379> set foo 1
    OK
    redis 192.168.1.53:6379> multi
    OK
    redis 192.168.1.53:6379> incr foo
    QUEUED
    redis 192.168.1.53:6379> discard
    OK
    redis 192.168.1.53:6379> get foo
    "1"

    4.WATCH 命令可以为 Redis 事务提供 check-and-set (CAS)行为
    被WATCH 的键会被监视,并会发觉这些键是否被改动过了。如果有至少一个被监视的键在EXEC 执行之前被修改了,那么整个事务都会被取消
    +++++++++++第一条命令 +++++++++++

    redis 192.168.1.53:6379> watch foo
    OK
    redis 192.168.1.53:6379> set foo 5
    OK
    redis 192.168.1.53:6379> multi
    OK
    redis 192.168.1.53:6379> set foo 9
    QUEUED

    +++++++++++暂停(执行完第二条命令才执行下面的)+++++++++++

    redis 192.168.1.53:6379> exec
    (nil)
    redis 192.168.1.53:6379> get foo
    "8"

    +++++++++++第二条命令+++++++++++

    redis 192.168.1.53:6379> set foo 8
    OK

    +++++++++++对应的java代码 +++++++++++

    php入门到就业线上直播课:查看学习

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。

    千万级数据并发解决方案(理论+实战):点击学习

    Mysql单表千万级数据量的查询优化与性能分析

    Mysql主从原理及其在高并发系统中的应用

      相关课程推荐

    • 独孤九贱(3)_JavaScript视频教程

      javascript是运行在浏览器上的脚本语言,连续多年,被评为全球最受欢迎的编程语言。是前端开发必备三大法器中,最具杀伤力。如果前端开发是降龙十八掌,好么javascript就是第18掌:亢龙有悔。没有它,你的前端生涯是不完整的。《php.cn独孤九贱(3)-JavaScript视频教程》课程特色:php中文网原创幽默段子系列课程,以恶搞,段子为主题风格的php视频教程!轻松的教学风格,简短的教学模式,让同学们在不知不觉中,学会了javascript知识。

      JavaScript教程139704次播放


    • 独孤九贱(6)_jQuery视频教程

      jQuery是一个快速、简洁的JavaScript框架。设计的宗旨是“write Less,Do More”,即倡导写更少的代码,做更多的事情。它封装JavaScript常用的功能代码,提供一种简便的JavaScript设计模式,优化HTML文档操作、事件处理、动画设计和Ajax交互。 核心特性可以总结为:具有独特的链式语法和短小清晰的多功能接口;具有高效灵活的css选择器,并且可对CSS选择器进行扩展;拥有便捷的插件扩展机制和丰富的插件。兼容各种主流浏览器,如IE 6.0+、FF 1.5+、Safari 2.0+、Opera 9.0+等,是全球最流行的前端开发框架之一。PHP中文网根据最新版本,独家录制jQuery最新视频教程,回馈PHP中文网的新老用户。

      jQuery教程114801次播放


    • jQuery与Ajax基础与实战

      jQuery是最流行的JS函数库,封装了许多实用的功能,其中最引人入胜的就是Ajax。 jQuery中的Ajax操作,语法简单,操作方便,使Ajax从未如此轻松,前端人员从此不再为与服务器异步交互而发愁,本套课程,精选了最常用的几个方法,从基本的语法到每个参数,再到具体实例进行了全面的讲解。

      AJAX教程14466次播放


    • Git教程(60分钟全程无废话版)

      Git 是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。 Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。 Git 与常用的版本控制工具 CVS, Subversion 等不同,它采用了分布式版本库的方式,不必服务器端软件支持

      JavaScript教程12454次播放


    1/1