Redis学习笔记3--Redis事务

Redis对事务的支持目前还比较简单。redis只能保证一个client发起的事务中的命令可以连续的执行,而中间不会插入其他client的命令。 由于redis是单线程来处理所有client的请求的所以做到这点是很容易的。一般情况下redis在接受到一个client发来的命令后会立即处理并 返回处理结果,但是当一个client在一个连接中发出multi命令有,这个连接会进入一个事务上下文,该连接后续的命令并不是立即执行,而是先放到一 个队列中。当从此连接受到exec命令后,redis会顺序的执行队列中的所有命令。并将所有命令的运行结果打包到一起返回给client.然后此连接就 结束事务上下文。

下面可以看一个例子:


redis 127.0.0.1:6379> multi
OK
redis 127.0.0.1:6379> incr a
QUEUED
redis 127.0.0.1:6379> incr b
QUEUED
redis 127.0.0.1:6379> exec
1. (integer) 1
2. (integer) 1

从这个例子我们可以看到incr a ,incr b命令发出后并没执行而是被放到了队列中。调用exec后俩个命令被连续的执行,最后返回的是两条命令执行后的结果。
       我们可以调用discard命令来取消一个事务。接着上面例子:


redis 127.0.0.1:6379> multi
OK
redis 127.0.0.1:6379> incr a
QUEUED
redis 127.0.0.1:6379> incr b
QUEUED
redis 127.0.0.1:6379> discard
OK
redis 127.0.0.1:6379> get a
"1"
redis 127.0.0.1:6379> get b
"1"

可以发现这次incr a incr b都没被执行。discard命令其实就是清空事务的命令队列并退出事务上下文。
       虽说redis事务在本质上也相当于序列化隔离级别的了。但是由于事务上下文的命令只排队并不立即执行,所以事务中的写操作不能依赖事务中的读操作结果。很可能有两个client同时做这个操作,也就是说如果我们要实现一个类似incr命令的功能,先get a取出我的值,再将a++,然后set a,我们期望是加两次a从原来的1变成3. 但是很有可能两个client的get a,取到都是1,造成最终加两次结果却是2。主要问题我们没有对共享资源a的访问进行任何的同步。也就是说redis没提供任何的加锁机制来同步对a的访问。

还好redis 2.1后添加了watch命令,可以用来实现乐观锁。看个正确实现incr命令的例子,只是在前面加了watcha :


redis 127.0.0.1:6379> watch a
OK
redis 127.0.0.1:6379> get a
"1"
redis 127.0.0.1:6379> multi
OK
redis 127.0.0.1:6379> set a 2
QUEUED
redis 127.0.0.1:6379> exec
1. OK
redis 127.0.0.1:6379> get a
"2"

watch 命令会监视给定的key,当exec时候如果监视的key从调用watch后发生过变化,则整个事务会失败。也可以调用watch多次监视多个key.这 样就可以对指定的key加乐观锁了。注意watch的key是对整个连接有效的,事务也一样。如果连接断开,监视和事务都会被自动清除。当然了 exec、discard、unwatch命令都会清除连接中的所有监视.
       redis的事务实现是如此简单,当然会存在一些问题。第一个问题是redis只能保证事务的每个命令连续执行,但是如果事务中的一个命令失败了,并不回滚其他命令,比如使用的命令类型不匹配。


redis 127.0.0.1:6379> set a 5
OK
redis 127.0.0.1:6379> lpush b 5
(integer) 1
redis 127.0.0.1:6379> set c 5
OK
redis 127.0.0.1:6379> multi
OK
redis 127.0.0.1:6379> incr a
QUEUED
redis 127.0.0.1:6379> incr b
QUEUED
redis 127.0.0.1:6379> incr c
QUEUED
redis 127.0.0.1:6379> exec
1. (integer) 6
2. (error) ERR Operation against a key holding the wrong kind of value
3. (integer) 6

可以看到虽然incr b失败了,但是其他两个命令还是执行了。

还有一个问题是当事务的执行过程中,如果redis意外的挂了。很遗憾只有部分命令执行了,后面的也就被丢弃了。当然如果我们使用的append-only file方式持久化,redis会用单个write操作写入整个事务内容。即是是这种方式还是有可能只部分写入了事务到磁盘。发生部分写入事务的情况下,redis重启时会检测到这种情况,然后失败退出。可以使用redis-check-aof工具进行修复,修复会删除部分写入的事务内容。修复完后就能够重新启动了。

时间: 2024-10-14 06:52:27

Redis学习笔记3--Redis事务的相关文章

redis学习笔记 - Pipeline与事务

原文 Redis提供了5种数据结构,但除此之外,Redis还提供了注入慢查询分析,Redis Shell.Pipeline.事务.与Lua脚本.Bitmaps.HyperLogLog.PubSub.GEO等附加功能,这些功能可以在某些场景发挥很重要的作用. Pipeline 1. Pipeline概念 Redis客户端执行一条命令分为以下四个步骤: 1.发送命令2.命令排队3.命令执行4.返回结果 其中,第一步+第四步称为Round Trip Time(RTT,往返时间). Redis提供了批量

Redis学习笔记(三) Redis API与常用数据类型简介

一.Redis中常用数据类型 由上一篇博客可知,Redis目前提供五种数据类型:string(字符串).list(链表).Hash(哈希).set(集合)及zset(sorted set)  (有序集合).现在,我们一一来看看这五种数据类型的基本使用方法.在开始介绍之前,我们先使用刚刚引入的Redis API建立一个Redis客户端对象,有了这个客户端对象,我们才能和Redis服务端进行通信,且看下面的一行代码.我们需要事先指定好Redis服务端的IP地址和端口号,然后根据这两个信息建立一个Re

Redis学习笔记(4) Redis事务、生存时间及排序

1. Redis事务 Redis中的事务(transaction)是一组命令的集合,一个事务中的命令要么都执行,要么都不执行.事务的原理是先将属于一个事务的命令发送给Redis,然后再让Redis依次执行这些命令. 127.0.0.1:6379> multi OK 127.0.0.1:6379> sadd user:1:following 2 QUEUED 127.0.0.1:6379> sadd user:2:followers 1 QUEUED 127.0.0.1:6379>

Redis学习笔记(2) Redis基础类型及命令之一

1. 基础命令 (1) 获取符合规则的键名列表 格式为:KEYS pattern 其中pattern表示支持通配符 # 建立一个名为bar的键 127.0.0.1:6379> SET bar 1 OK # 获取Redis所有键 127.0.0.1:6379> KEYS * 1) "bar" 注意:KEYS命令需要遍历Redis中所有键,因此当键的数量较多时会影响性能. (2) 判断一个键是否存在 格式为:EXISTS key 如果存在则返回1,否则返回0. 127.0.0.

Redis学习笔记(3) Redis基础类型及命令之二

1. 集合类型 集合类型与列表类型有很多相似之处,但二者的区别在于:前者具有唯一性,但不具有有序性:后者具有有序性,但不具有唯一性.集合类型的常用操作是向集合中加入或删除元素.判断某个元素是否存在等,以及多个集合类型之间进行并集.交集和差集运算. (1) 命令 1) 增加/删除元素 格式为:SADD key member [member ...] SREM key member [member ...] SADD向集合中增加一个或多个元素,加入的元素若已存在语集合中,则会忽略该元素.命令返回成功

Redis学习笔记~StackExchange.Redis实现分布式Session

回到目录 对于多WEB的环境现在已经是必须的了,很难想像一台WEB服务器面对百万并发的响应,所以,我们需要多台WEB服务器集群合作,来缓解这种高并发,高吞吐的场景,而对于多WEB的场景又会有个问题出现,即session存储的问题,如一个用户登陆后,把一个状态信息存储到当前WEB服务器的session里,而你请求其它页面时,很可能就被路由到另一台服务器了,这时,session也就丢了,而对于这种情况,有人把redis这个存储中间件想了起来,对它进行了封装,就有了今天基于redis的session共

Redis学习笔记

Redis学习笔记:Redis是什么?redis是开源BSD许可高级的key-vlue存储系统可以用来存储字符串哈希结构链表.结构.集合,因此常用来提供数据结构服务. redis和memcache相比的独特之处:1.redis可以用来做存储,而memcache是用来做缓存 这个特点主要因为其有"持久化"的功能.2.存储的数据有"结构",对于memcache来说,存储的数据只有1种类型"字符串"而 redis则可以存储字符串.链表.哈希机构.集合.

Redis学习笔记4-Redis配置具体解释

在Redis中直接启动redis-server服务时, 採用的是默认的配置文件.採用redis-server   xxx.conf 这种方式能够依照指定的配置文件来执行Redis服务. 依照本Redis学习笔记中Redis的依照方式依照后,Redis的配置文件是/etc/redis/6379.conf.以下是Redis2.8.9的配置文件各项的中文解释. #daemonize no 默认情况下, redis 不是在后台运行的.假设须要在后台运行,把该项的值更改为 yes daemonize ye

Redis学习笔记~目录

redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(sorted set --有序集合)和hashs(哈希类型).这些数据类型都 支持push/pop.add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的.在此基础上,redis支持各种不同方式的排 序.与memcached一样,为了保证效率,数据都是缓存在内存中.区别的是redis会周期性的把更

Redis学习笔记4-Redis配置详解

原文:  http://blog.csdn.net/mashangyou/article/details/24555191 在Redis中直接启动redis-server服务时, 采用的是默认的配置文件.采用redis-server   xxx.conf 这样的方式可以按照指定的配置文件来运行Redis服务.按照本Redis学习笔记中Redis的按照方式按照后,Redis的配置文件是/etc/redis/6379.conf.下面是Redis2.8.9的配置文件各项的中文解释. 1 #daemon