Redis 事务

Redis操作时支持事务的。事务具有原子性atomic,包含在事务中的操作要么都执行成功,要么都执行失败。但是redis不支持回滚,但是可以在测试开发环节避免错误操作。可以说原子性上是半支持的,看后面原因。

很多时候我们需要进行事务操作。

翻译官档:https://redis.io/topics/transactions

实际操作:python版使用参考

https://github.com/7Edge/redis-demo/blob/master/redis_pipeline.py

事务

MULTI, EXEC, DISCARD 和 WATCH 操作都是redis事务的基础操作。这些操作可以让一组操作看作一个操作原子执行。之所以能做到,是因为一下两个重要的保障:

1. 命令有序

在事务中的所有命令都是有序的,且执行是顺序执行的。当另一个客户端连接发生错误,是不可能影响到当前正在执行的事务的。这点就保证了命令执行时是相互隔离的操作。因为是单线程,且redisserver利用i/o多路复用来处理并发连接。

2. 始终原子

在事务中无论全部命令执行了,还是一个命令都没执行,redis的事务都是原子的。EXEC命令开启事务中所有命令的执行,如果在调用multi命令前没有,client到server端的连接断开,没有任何操作会被执行;如果EXEC命令被执行了, 所有的操作都会被执行。如果配置时使用了append-only file ,redis会使一个single write(2) syscall写入到aof文件中。然而,如果redis server crashes 或者被管理员强制kill掉,这时可能只有一部分操作被注册了,这种情况下,redis在重启的时候会发现这种情况,并且启动失败退出,报一个错误。 这时就要使用 redis-check-aof 工具,该工具将会修复aof文件,删除只有部分的事务,然后再重启redis即可。

开启使用事务

1. 执行MULTI  # 开启事务, 返回OK或者其它
2. 执行多个命令 # 事务中的操作, 返回QUEUED,表明加入事务命令队列
3. EXEC # 执行,返回每个事务中命令的返回结果列表 4. DISCARD 如果在EMULTI之后EXEC之前要关闭事务,再EXEC之前执行即可flush所有事务命令队列中的命令并关闭事务

Redis事务中出现错误

在事务中,有些操作可能或遇到执行出错,大致有两种命令执行错误:

1. EXEC前的错误

有一个错误在执行EXEC命令前,即命令没有成功的加入到队列中。如:执行的命令参数个数错误,命令名使用错误等。

对于这种错误,client是可以感知到的,因为执行命令时,其实是加入到命令队列中的,如果返回QUEUED说明加入成功,其它返回都是错误。这种错误,大多数client将会中断事务并自动DISCARD事务。(python得redis模块中,由于pipeline和multi/exec结合,redis.exceptions.ResponseError异常,但是没有异常得命令还是会执行,就是由于与pipeline结合)

然而,在Redis 2.6.5 后,server将会记录错误在累积命令到命令队列中时,这时执行EXEC,server将会拒绝事务的执行并返回一个错误,自动discard.

而在Redis2.6.5之前,对于这种错误,server行为是,只会执行成功加入到队列中的命令,相当于命令集中的一个子集被执行一次,尽管有错误发生。Redis 2.6.5 server没有了这种处理逻辑,而是将逻辑加入到新的命令中,就是pipeline管道命令,管道可以实现之前的行为,管道会返回命令的返回结果的列表。

2. EXEC后的错误

错误在EXEC执行后,如key冲突。对于这种错误,没有handle方法,所有的其它命令都会被执行,即使一新命令出错在事务期间。

为什么出错了不支持roll backs?

像关系型数据库,事务都是支持回滚的,而在redis事务中竟然支持错误的发生。redis之所以有这种行为是因为一下两点:

  1. redis 命令失败只会是语法错误或者 存在的key修改成了错误的数据类型。这些错误是非常容易在开发或者测试阶段被发现的。
  2. redis本应该是简单且快速的,不需要roll back能力。

Redis事务所指的原子性仅仅只针对将命令加入执行队列的过程,Redis事务不支持在命令执行过程中的错误回滚。

Redis的乐观锁实现check-and-set

并发事务,都会有修改同一数据的时候,虽然redis事务因为读线程时隔离了的,但是有时候我们需要锁定数据,独占使用,就只有使用redis提供的乐观锁来锁定我们的数据,这个乐观锁只能配合事务使用,检查行为是在事务执行EXEC时,如果有变化,那么EXEC执行回失败。WATCH 被用于提供CAS行为用于redis事务中。CAS即是我们常说的乐观锁。

乐观锁的事务执行失败,必须检测结果,失败就要重试。

我们知道事务的4特性ACID:

Atomic原子性: 事务中操作集,要么都成功,要么都失败回滚。
Redis事务所指的原子性仅仅只针对将命令加入执行队列的过程,Redis事务不支持在命令执行过程中的错误回滚。 Consistency 一致性: 事务前后,数据库是从一个一致性状态到另一个一致性状态。如转账前后总数是一致的。 Isolation 隔离性: 并发事务时,事务之间都不会由于访问同一数据而被干扰。在这个隔离层面讲,就有多种隔离级别,因为隔离级别时影响并发事务效率和数据安全性的,要在效率和安全间平衡是关键。隔离级别太严格,并发效率低,数据安全;隔离级别太低,又怕数据不安全。 Durability 持久性:事务一旦被提交,改变时永久的,即要持久化。很多都会将事务操作完后追加到操作日志文件中,数据者写入磁盘文件系统持久化。

WATCH 命令用于监控key的改变,如果被监控时的key发生了修改在执行EXEC之前,那么这个事务将aborts,并且返回一个Null,表明事务失败。可用在要锁定数据的事务前。WATCH 配合MULTI和EXEC

使用UNWATCH可以flush掉所有WATCHED keys。

小结

  1. Redis事务所指的原子性仅仅只针对将命令加入执行队列的过程,Redis事务不支持在命令执行过程中的错误回滚
  2. 利用watch可以乐观锁数据。乐观cas,悲观让别人等。

05. redis事务的更多相关文章

  1. Redis学习笔记~Redis事务机制与Lind.DDD.Repositories.Redis事务机制的实现

    回到目录 Redis本身支持事务,这就是SQL数据库有Transaction一样,而Redis的驱动也支持事务,这在ServiceStack.Redis就有所体现,它也是目前最受业界认可的Redis ...

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

    1. Redis事务 Redis中的事务(transaction)是一组命令的集合,一个事务中的命令要么都执行,要么都不执行.事务的原理是先将属于一个事务的命令发送给Redis,然后再让Redis依次 ...

  3. REDIS 事务机制

    基本事务操作: 任何数据库都必须要保证一种原子执行操作:最基本的原子执行操作肯定是需要提供: 举一个例子来说明: 当对某个Key 做一个统计: 可能不同的Client做它那部分的统计,一段时间后,服务 ...

  4. redis 事务

    概述 相信学过MySQL等其他数据库的同学对事务这个词都不陌生,事务表示的是一组动作,这组动作要么全部执行,要么全部不执行.为什么会有这样的需求呢?看看下面的场景: 微博是一个弱关系型社交网络,用户之 ...

  5. (6)redis 事务

    redis对事务的支持目前还比较简单.redis只能保证一个client发起的事务中的命令可以连续的执行,而中间不会插入其他client的命令. 由于redis是单线程来处理所有client的请求的所 ...

  6. Redis事务的分析及改进

    Redis事务的分析及改进 Redis的事务特性 数据ACID特性满足了几条? 为了保持简单,redis事务保证了其中的一致性和隔离性: 不满足原子性和持久性: 原子性 redis事务在执行的中途遇到 ...

  7. Spring Framework 中启动 Redis 事务操作

    背景: 项目中遇到有一系列对Redis的操作,并需要保持事务处理. 环境: Spring version 4.1.8.RELEASE Redis Server 2.6.12 (64位) spring- ...

  8. 2016022612 - redis事务命令集合

    参考地址:http://www.yiibai.com/redis/redis_transactions.html Redis事务由指令 MULTI 启动,以EXEC结束. 1.multi 用途:事务开 ...

  9. 2016022606 - redis事务

    Redis事务 Redis事务让一组命令在单个步骤执行.事务中有两个属性,说明如下: 1.在一个事务中的所有命令按顺序执行作为单个隔离操作.通过另一个客户端发出的请求在Redis的事务的过程中执行,这 ...

随机推荐

  1. nwjs-简介

    nwjs是基于nodejs的,它支持nodejs所有的api,主要用于跨平台轻量级桌面应用开发,运行环境包括32位和64位的Window.Linux和Mac OS nwjs是在英特尔开源技术中心创建的 ...

  2. CF1163E Magical Permutation(线性基,构造)

    虽然做起来有一点裸……但是就是想不到啊…… 首先令 $d_i=p_i\oplus p_{i-1}$,那么 $d_i$ 都是 $S$ 中的数,$a_i=d_i\oplus d_{i-1}\oplus \ ...

  3. QLayout及其子类 清除添加的widget

    起初,我的思路是,先取得Layout的items数量, 然后通过索引来移除每一个items,代码如下: QHBoxLayout * hly = new QHBoxLayout; ; i < ; ...

  4. 微信企业号SDK

    1. 微信企业号SDK class class_wxqiye { var $corpid = CorpID; var $corpsecret = CorpSecret; var $agentid = ...

  5. docker 安装 apollo

    apollo作为携程开源的配置中心,很多大厂在使用,在此记录下安装历程 服务器环境: 安装mysql 1.拉取镜像 docker pull idoop/docker-apollo 2.新建3个数据库, ...

  6. C++ 类中的3种访问权限和继承方式

    访问权限:public 可以被任意实体访问,protected 只允许子类(无论什么继承方式)及本类的成员函数访问,private 只允许本类的成员函数访问.三种继承方式分别是 public 继承,p ...

  7. python read readline readlines区别

    file 对象使用 open 函数来创建,下表列出了 file 对象常用函数read.readline.readlines区别: 1.从文件读取指定的字节数,size如果未给定或为负则读取所有. fi ...

  8. jq数字翻页效果,随机数字显示,实现上下翻动效果

    最近在做一个项目,需要实时展示一串数字,要有类似于日历翻页的效果,在网上找寻了一番,发现dataStatistics这个插件http://www.jq22.com/jquery-info8141能实现 ...

  9. 从URL重写中学习正则表达式

    起因: 最近因为业务上的需求,老板要求改写网站的域名.要求把所有的二级域名中的内容放到主域名下,增加资源集中程度,有利于搜索引擎的优化. so.网站中所有的URL定向都要重写,也就是我们所说的伪静态的 ...

  10. 订单1:n支付单 设计讨论

    方法一:订单1:1支付单,下单时生成1订单,并生成1支付单(这个支付单是微信需要的相关信息),设置超时时间2小时,如果订单超时,则提示用户,订单已超时,重新下单即可: 方法二:订单1:N支付单,下单时 ...