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<Object> 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<Object> 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代码 +++++++++++

Jedis jedis = new Jedis("192.168.1.53", 6379);
jedis.watch( "foo");
Transaction tx = jedis.multi();
tx.incr( "foo"); List<Object> result = tx.exec(); //运行时在这边打断点,然后通过命令行改变foo的值
if (result == null || result.isEmpty()) {
System. err.println( "Transaction error...");
return;
}
for (Object rt : result) {
System. out.println(rt.toString());
}

如果在WATCH 执行之后,EXEC 执行之前,有其他客户端修改了 mykey 的值,那么当前客户端的事务就会失败。程序需要做的,就是不断重试这个操作,直到没有发生碰撞为止。
这种形式的锁被称作乐观锁,它是一种非常强大的锁机制。并且因为大多数情况下,不同的客户端会访问不同的键,碰撞的情况一般都很少,所以通常并不需要进行重试。

【Redis】5、Redis事务处理的更多相关文章

  1. 使用redis 中的事务处理实现商品秒杀

    redis中的事务处理: redis中的事物事物处理是指能够批量的执行一组命令(当事务开始执行时,事务中的命令能够按照按照规定好的顺序执行而不会被插队或打断): 与mysql事务的区别在于:mysql ...

  2. Java Spring mvc 操作 Redis 及 Redis 集群

    本文原创,转载请注明:http://www.cnblogs.com/fengzheng/p/5941953.html 关于 Redis 集群搭建可以参考我的另一篇文章 Redis集群搭建与简单使用 R ...

  3. CentOS下安装Redis及Redis的PHP扩展

    1.安装Redis 1.1 如果没有安装wget,安装wget yum install wget 1.2 在http://redis.io/download页面查看redis版本,并下载安装 wget ...

  4. redis/php redis扩展 安装

    作者:silenceper 日期:2013-10-03 原文地址: http://silenceper.com/archives/952.html 我是在CentOS 6.3 中进行的. 使用到的软件 ...

  5. windows下与linux下安装redis及redis扩展

    1.        Redis的介绍 Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API.从2010年3月15日起 ...

  6. redis系列-redis的使用场景

    redis越来越受大家欢迎,提升下速度,做下缓存,完成KPI之利器呀.翻译一篇文章<<How to take advantage of Redis just adding it to yo ...

  7. 搭建LNAMP环境(五)- PHP7源码安装Redis和Redis拓展

    上一篇:搭建LNAMP环境(四)- 源码安装PHP7 一.安装Redis 1.创建redis用户组和用户 groupadd redis useradd -r -g redis -s /sbin/nol ...

  8. redis配置文件redis.conf参数说明

    redis配置文件redis.conf参数说明 (2013-01-09 21:20:40)转载▼ 标签: redis配置 redis.conf 配置说明 杂谈 分类: nosql # By defau ...

  9. 【Redis】Redis的基本安装及使用

    在Linux上安装Redis Redis的安装很简单.基本上是下载.解压.运行安装脚本.我用的Redis版本是3.2.1. [nicchagil@localhost app]$ wget -q htt ...

  10. vagrant系列教程(四):vagrant搭建redis与redis的监控程序redis-stat(转)

    上一篇php7环境的搭建 真是火爆,仅仅两天时间,就破了我之前swagger系列的一片文章,看来,大家对搭建环境真是情有独钟. 为了访问量,我今天再来一篇Redis的搭建.当然不能仅仅是redis的搭 ...

随机推荐

  1. 2019swpuj2ee作业一:C/S,B/S的应用的区别

    1.硬件环境不同: C/S 一般建立在专用的网络上, 小范围里的网络环境, 局域网之间再通过专门服务器提供连接和数据交换服务.B/S 建立在广域网之上的, 不必是专门的网络硬件环境,例与电话上网,  ...

  2. Html5与Css3知识点拾遗(三)

    文本 small:包括免责申明.注意事项.法律限制.版权信息,只适用于短于,常包含在页面级的footer里 H5对i和b的重新定义 b:提醒文字.不传达任何额外的语气.文档摘要关键词.评论中的产品名. ...

  3. 让用户输入一个日期字符串,将其转换成日期格式, 格式是(yyyy/MM/dd,yyyyMMdd,yyyy-MM-dd)中的一种, 任何一种转换成功都可以; 如果所有的都无法转换,输出日期格式非法。

    第三种方法 while(true) {             Date d;        System.out.println("正在进行第一次匹配,请稍后~—~");     ...

  4. 解决eclipse运行内存溢出方案

    1.在工具栏找到Window -> Preference 2.双击选择的jdk 3.在VM输入以下设置运行的内存的大小即可(具体内存大小可以根据项目进行设置) -Xms800m -Xmx800m ...

  5. Pycharm2018的激活方法或破解方法

    1.授权服务器激活 优点:方便快捷 缺点:激活的人数多了就容易被封杀,所以可能经常需要去激活 选择License server激活,然后填入: idea.qmanga.com或http://xidea ...

  6. Request参数值自动去空格

    /// <summary> /// TypeTrimHelper /// </summary> public static class TypeTrimHelper { /// ...

  7. 机器学习随笔01 - k近邻算法

    算法名称: k近邻算法 (kNN: k-Nearest Neighbor) 问题提出: 根据已有对象的归类数据,给新对象(事物)归类. 核心思想: 将对象分解为特征,因为对象的特征决定了事对象的分类. ...

  8. grid布局笔记学习一之父元素(容器)

    HTML代码: <div id="box"> <div class="lbox box1" style="background: # ...

  9. 教你用python打造WiFiddos

    本文来源于i春秋学院,未经允许严禁转载. 0x00 前言因为在百度上很难找到有关于用python打造WiFidos的工具的,而且不希望大家成为一名脚本小子,所以我打算写一篇,需要的工具有scapy,i ...

  10. typescript handbook 学习笔记3

    概述 这是我学习typescript的笔记.写这个笔记的原因主要有2个,一个是熟悉相关的写法:另一个是理清其中一些晦涩的东西.供以后开发时参考,相信对其他人也有用. 学习typescript建议直接看 ...