一、事务

一般来说,事务必须满足4个条件,也就是我们常说的ACID:

1)Atomicity 原子性:一个事务中的所有操作要么全部完成,要么全部不完成,不会结束在中间的某个环节。事务在执行过程中发生错误,会被回滚到事务开始前的状态,就像是这个事务从来没有执行一样。

2)Consistency 一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须符合所有预设原色,者包含资料的精确度、串联性以及后续的数据库可以自发性地完成预定工作。

3)Isolation 隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括未提交、读提交、可重复读和串行化。

4)Durability 持久性:事务处理以后,对数据的修改就是永久的,即便系统故障也不会丢失。

二、redis事务

从本质上来说,redis的事务其实不能算是事务,或者说它不遵循ACID原则,只是将一组命令置入队列,然后像执行一个命令一样执行一组命令。可是它并不保证所有命令完整执行,也不支持事务回滚。因此,当一个事务中其中一个命令发生错误,其它命令还是会被执行。这听起来有些奇怪,不过redis给出了相应的解释。后面我们会提到。

redis事务有两个原则:

1)一个事务包含一组命令,当事务在执行期间不会有其它客户端的命令穿插执行。这意味着,这组命令在执行期间类似于一个隔离的命令操作。

2)事务通过multi命令创建,multi之后的命令将会进入执行队列,当exec命令执行的时候,会将进入队列的命令全部按顺序执行,并返回顺序的结果。这里要注意:1)如果redis在multi执行之前发生如硬件崩溃等错误,那么所有东西都不会被执行。2)如果redis在exec执行之后发生崩溃等错误,那么所有都洗都会被执行。3)当使用AOF持久化策略的时候,会将事务写入日志文件,如果写入过程发生崩溃等错误,那么redis重新启动加载日志的时候会发生错误并退出(可以使用redis-check-aof)工具解决。

三、使用

我们看一个简单的示例

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set age 23
QUEUED
127.0.0.1:6379> set name lay
QUEUED
127.0.0.1:6379> exec
1) OK
2) OK

multi: 开启一个事务

set age 23 命令入队

set name lay 命令入队

exec: 事务执行

返回数据结果

四、错误

在一个事务开始到执行结束期间可能发生很多问题,主要分为如下两种:

1)exec执行之前发生错误,如发生语法错误。

2)exec执行期间发生错误,如操作的值类型错误。

一般上,如果exec执行之前发生错误,那么客户端会将当前的事务取消、队列的命令清除。如果在exec执行期间发生错误,那么其它命令还会继续执行,并不会回滚。

五、为什么redis不支持事务回滚?

熟悉关系型数据库的你应该很清楚事务回滚,当看到redis不支持回滚肯定会觉得很奇怪。redis官方给出解释原文如下:

  • Redis commands can fail only if called with a wrong syntax (and the problem is not detectable during the command queueing), or against keys holding the wrong data type: this means that in practical terms a failing command is the result of a programming errors, and a kind of error that is very likely to be detected during development, and not in production.
  • Redis is internally simplified and faster because it does not need the ability to roll back.

主要是两点:

1)redis官方认为,导致redis出错的情况一般是在开发期间就可以发现的,如语法错误,操作的值类型不对。而不应当把研发上的错误在生产环境里检查,而真的在生产环境出现的错误,其实通常是事务回滚也无法解决的。

2)事务带来的开销是性能的损失,redis本身是单线程架构,追求内存的高效,所以事务回滚并不符合它的宗旨。

总结一下:redis容许发生一些影响不大的错误(如空值什么的),虽然产生使用上的限制,但减少了开销,提高了性能。

六、事务执行条件

redis中有一个watch命令,它可以监听key的变化,如果事务在执行之前key的值由其它客户端改变,那么当前事务将会被取消、队列命令也会被清除。

如:

client1开启事务:

127.0.0.1:6379> watch age
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set age 25
QUEUED

client2改变数据:

127.0.0.1:6379> set age 27
OK

client1执行exec:

127.0.0.1:6379> exec
(nil)
127.0.0.1:6379>

返回nil,当前事务已经被取消了

七、事务命令

discard: 取消

exec: 执行

multi: 开启

unwatch: 取消监听

watch: 监听

详细参考官方文档:https://redis.io/topics/transactions

八、lua

redis内嵌了lua模块,这里简单提一下lua的执行也是事务性的,在redis中可以用lua来实现事务,并且通常lua更加的简单和快速。

redis(4)事务的更多相关文章

  1. Redis的事务

    Redis对事务的支持是部分支持,不想oracle,要么都成功要么都失败,Redis可以部分成功部分失败 1 是什么: 可以一次执行多个命令,本质是一组命令的集合.一个事务中的所有命令都会序列化,按顺 ...

  2. Redis笔记(五)Redis的事务

    >>关系型数据库的事务 事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消. Atomic(原子性): 一个事务(transaction)中的 ...

  3. redis的事务(简单介绍)

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

  4. Redis的事务功能详解

    Redis的事务功能详解 MULTI.EXEC.DISCARD和WATCH命令是Redis事务功能的基础.Redis事务允许在一次单独的步骤中执行一组命令,并且可以保证如下两个重要事项: >Re ...

  5. Redis的事务和watch

    redis的事务 严格意义来讲,redis的事务和我们理解的传统数据库(如mysql)的事务是不一样的. redis中的事务定义 Redis中的事务(transaction)是一组命令的集合. 事务同 ...

  6. spring中jedis对redis的事务使用注意总结

    spring的@Transactional不支持redis的事务,并且redis的事务和其它关系型数据库的事务概念不是太一样,redis事务不支持回滚,并且一条命令出错后,后面的命令还会执行. 所以不 ...

  7. Redis保证事务一致性,以及常用的数据结构

    reids命令可以参考中文官网:http://redis.cn/commands.html 关于reids的使用,可以封装到工具类进行调用: Redis的工具类:JedisAdapter 除了数据结构 ...

  8. Redis(十一):Redis的事务功能详解

    相关命令 1. MULTI 用于标记事务块的开始.Redis会将后续的命令逐个放入队列中,然后才能使用EXEC命令原子化地执行这个命令序列. 这个命令的运行格式如下所示: MULTI 这个命令的返回值 ...

  9. 第四章· Redis的事务、锁及管理命令

    一.事务介绍 二.Redis乐观锁介绍 三.Redis管理命令 一.事务介绍 Redis的事务与关系型数据库中的事务区别 1)在MySQL中讲过的事务,具有A.C.I.D四个特性 Atomic(原子性 ...

  10. $Django python中使用redis, django中使用(封装了),redis开启事务(管道)

    一 Python操作Redis之普通连接 #先安装 pip3 install redis import redis r = redis.Redis(host='127.0.0.1', port=637 ...

随机推荐

  1. Windows server 2008 R2安装MySQL 32位ODBC驱动!

    在Windows server 2008 R2安装MySQL 32位ODBC驱动,总是提示错误,我安装了DOTNET4的库,同时安装了VC2008.VC2012.VC2013的支持库,怎么还不行呢?M ...

  2. [ActionScript 3.0] 对数组中的元素进行排序Array.sort()的方法

    对数组中的元素进行排序. 此方法按 Unicode 值排序. (ASCII 是 Unicode 的一个子集.) 默认情况下,Array.sort()按以下方式进行排序: 1. 排序区分大小写(Z优先于 ...

  3. spring框架里面的注入?

    在Spring框架里面注入可以通过1.setter方法注入:2.构造器注入:3.注入对象 在配置文件中配置如下: 前面两者不能同时注入: 入 如果前两者同时注入将会报错 将注入修改以后,如下图: 修改 ...

  4. 运算符重载入门demo

    #include "pch.h" #include <iostream> using namespace std; class A { public: A(int x, ...

  5. BZOJ1688 Disease Manangement 疾病管理

    Disease Manangement 疾病管理   Description Alas! A set of D (1 <= D <= 15) diseases (numbered 1..D ...

  6. 【转】JavaWeb之Session的序列化和反序列化 && Session的活化和钝化

    应用场景: 1.一般来说,服务器启动后,就不会再关闭了,但是如果逼不得已需要重启,而用户会话还在进行相应的操作,这时就需要使用序列化将session信息保存起来放在硬盘,服务器重启后,又重新加载.这样 ...

  7. java.math.BigDecimal cannot be cast to java.lang.Integer

    问题来源: 在数据库中查询一个列表的长度时,需要转换为Integer类型,我刚开始直接转就报错了.因为在数据库中用count(*) 聚合函数返回的值类型为BigDecimal,不能直接转换为Integ ...

  8. ZOJ - 3946-Highway Project(最短路变形+优先队列优化)

    Edward, the emperor of the Marjar Empire, wants to build some bidirectional highways so that he can ...

  9. odoo 的一些orm 操作

    1.基础文件及目录结构 在认识odoo ORM框架前,先介绍一下odoo中模块目录结构.     data:存放模块预制数据 i18n:存放国际化文件 models:存放模型等py代码 securit ...

  10. Java使用占位符拼接字符串-String.format()的使用

    String domain = "www.ykmaiz.com"; int iVisit = 0; String info = String.format("该域名%s被 ...