【Redis】5、Redis事务处理
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事务处理的更多相关文章
- 使用redis 中的事务处理实现商品秒杀
redis中的事务处理: redis中的事物事物处理是指能够批量的执行一组命令(当事务开始执行时,事务中的命令能够按照按照规定好的顺序执行而不会被插队或打断): 与mysql事务的区别在于:mysql ...
- Java Spring mvc 操作 Redis 及 Redis 集群
本文原创,转载请注明:http://www.cnblogs.com/fengzheng/p/5941953.html 关于 Redis 集群搭建可以参考我的另一篇文章 Redis集群搭建与简单使用 R ...
- CentOS下安装Redis及Redis的PHP扩展
1.安装Redis 1.1 如果没有安装wget,安装wget yum install wget 1.2 在http://redis.io/download页面查看redis版本,并下载安装 wget ...
- redis/php redis扩展 安装
作者:silenceper 日期:2013-10-03 原文地址: http://silenceper.com/archives/952.html 我是在CentOS 6.3 中进行的. 使用到的软件 ...
- windows下与linux下安装redis及redis扩展
1. Redis的介绍 Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API.从2010年3月15日起 ...
- redis系列-redis的使用场景
redis越来越受大家欢迎,提升下速度,做下缓存,完成KPI之利器呀.翻译一篇文章<<How to take advantage of Redis just adding it to yo ...
- 搭建LNAMP环境(五)- PHP7源码安装Redis和Redis拓展
上一篇:搭建LNAMP环境(四)- 源码安装PHP7 一.安装Redis 1.创建redis用户组和用户 groupadd redis useradd -r -g redis -s /sbin/nol ...
- redis配置文件redis.conf参数说明
redis配置文件redis.conf参数说明 (2013-01-09 21:20:40)转载▼ 标签: redis配置 redis.conf 配置说明 杂谈 分类: nosql # By defau ...
- 【Redis】Redis的基本安装及使用
在Linux上安装Redis Redis的安装很简单.基本上是下载.解压.运行安装脚本.我用的Redis版本是3.2.1. [nicchagil@localhost app]$ wget -q htt ...
- vagrant系列教程(四):vagrant搭建redis与redis的监控程序redis-stat(转)
上一篇php7环境的搭建 真是火爆,仅仅两天时间,就破了我之前swagger系列的一片文章,看来,大家对搭建环境真是情有独钟. 为了访问量,我今天再来一篇Redis的搭建.当然不能仅仅是redis的搭 ...
随机推荐
- noip第20课资料
- Beta冲刺 (5/7)
Part.1 开篇 队名:彳艮彳亍团队 组长博客:戳我进入 作业博客:班级博客本次作业的链接 Part.2 成员汇报 组员1(组长)柯奇豪 过去两天完成了哪些任务 共享编辑文章的后端数据处理 部分代码 ...
- pwm互补输出 死区设置
void TIM8_PWM_Init(u16 arr,u16 psc){ GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitT ...
- 《大型网站系统与Java中间件实践》
读了一下,个人认为最好的部分,就是第四章了. CH04 服务框架 4.2 服务设计与实现 // 获取可用服务地址列表 // 确定调用服务目标机器 // 建立连接(Socket) // 请求序列化 // ...
- 我知道的nginx配置
1.nginx配置文件 2.配置访问域名 #京淘商品管理系统 server { listen 80; server_name manage.jt.com; location / { proxy_pas ...
- 第二十二节:Java语言基础-详细讲解位运算符与流程控制语句
位运算符(二进制位运算) 运算符 运算 例子 << 左移 3 << 2 = 12 --> 3 * 2 * 2 =12 >> 右移 3 >> 1 = ...
- struts2框架学习笔记2:配置详解
核心配置文件: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC ...
- jQuery应用实例3:全选、二级联动
全选: 这里是用JS实现的:http://www.cnblogs.com/xuyiqing/p/8378221.html 如果使用jQuery则会方便很多: <!DOCTYPE html> ...
- zookeeper常用指令
zk服务 bin 目录下常用的脚本解释 zkCleanup 清理 Zookeeper 历史数据,包括日志文件和快照数据文件 zkCli Zookeeper 的一个简易客户端 zkEnv 设置 Zook ...
- Shell-8--数值运算及处理
RANDOM 默认范围是 0~32767