redis事务与关系型数据库事务比较
redis 是一个高性能的key-value 数据库。作为no sql 数据库redis 与传统关系型数据库相比有简单灵活、数据结构丰富、高速读写等优点。
本文主要针对redis 在事物方面的处理与传统关系型数据库(使用mysql)进行比对,所使用的环境为ubuntu 14.04.1,mysql 5.5.49,redis 3.2.3。
1操作事务命令
mysql 使用start transaction 开启事物,rollback 回滚事物,commit 提交事物。redis 使用multi 开始事物,discard 取消事物,exec 提交事物。开始实验前为mysql 和redis 准备测试数据,tom1 账户准备1000元,tom2 账户准备500元。

(图1-数据准备)
场景1:使用事务从tom1转100元到tom2 。
步骤如下:
|
mysql |
redis |
|
|
开启事物 |
start transaction |
multi |
|
tom1 - 100 |
update tom1 |
decrty tom1 100 queued |
|
查询tom1 余额 |
tom1余额减少了100 |
get tom1 queued |
|
tom2 + 100 |
update tom2 |
incrby tom2 100 queued |
|
查询tom2 余额 |
tom2余额增加了100 |
get tom2 queued |
|
提交事物 |
commit |
exec 执行queue中的语句。 1) (integer) 900 2) "900" 3) (integer) 600 4) "600" |
|
查询tom1,tom2余额 |
select * from account where name in (‘tom1’,’tom2’); tom1金额减少100,tom2账户增加了100 |
mget tom1 tom2 tom1金额减少100,tom2账户增加了100 |

(图2-mysql 事务执行过程)

(图3-redis 事务执行过程)
从场景1中可以看出mysql 开启事务后事务中的sql 语句在commit 之前就已经执行了sql 语句的,只是并未真正提交到数据库。redis 使用multi 开启事务后,编写的sql 语句都进入queue 队列中,待执行exec 提交事物时才一次性按进入queue 队列的顺序提交到数据库。同样针对回滚,mysql 执行rollback 会将提交的数据回滚,redis 因为没有提交到数据,使用discard 只是单纯取消在queue 中的sql 语句。
场景2: 在执行tom1 向tom2 转过程中100元的过程中使用了语法错误的sql。
步骤如下:
|
mysql |
redis |
|
|
开启事物 |
start transaction |
multi |
|
tom1 - 100 |
update tom1 |
decrty tom1 100 queued |
|
查询tom1 余额 |
tom1余额减少了100 |
get tom1 queued |
|
tom2 + 100 |
使用错误命令为tom2+100 |
使用错误命令为tom2+100 |
|
查询tom2 余额 |
tom2余额未变 |
get tom2 queued |
|
提交事物 |
commit |
exec 因为queue中存在语法错误的语句,直接discard事务中的语句 |
|
查询tom1,tom2余额 |
select * from account where name in (‘tom1’,’tom2’); tom1金额减少100,tom2账户金额未变 |
mget tom1 tom2 tom1,tom2金额未变 |

(图4-mysql 事务中存在语法错误语句)

(图5-redis 事务中存在语法错误语句)
从场景2中可以看出,mysql 事务即使遇到错误的语句也会提交正确的sql 到数据库,需要程序员控制当遇到语句异常时进行回滚,redis 与mysql 不同,提交事务时当queue 中有语法错误语句会discard 整个事务中的sql 语句。
场景3: 在执行tom1 向tom2 转过程中100元的过程中使用了错误的执行对象。
步骤如下:
|
mysql |
redis |
|
|
开启事物 |
start transaction |
multi |
|
tom1 - 100 |
update tom1 |
decrty tom1 100 queued |
|
查询tom1 余额 |
tom1余额减少了100 |
get tom1 queued |
|
tom2 + 100 |
使用错误对象命令为tom2+’hundrud’ |
使用错误命令为tom2+’hundred’ |
|
查询tom2 余额 |
tom2余额未变 |
get tom2 queued |
|
提交事物 |
commit |
exec 逐条执行 |
|
查询tom1,tom2余额 |
select * from account where name in (‘tom1’,’tom2’); tom1金额减少100,tom2账户金额未变 |
mget tom1 tom2 tom1金额减少100,tom2账户金额未变 |

(图6-mysql 中存在操作错误对象的sql 语句)

(图7-redis 中存在操作错误对象的sql语句)
从场景3中可以看出,mysql 和redis 事务当遇到操作对象类型不正确的时候都会提交执行事务。
2事务锁
在关系型数据库中主要通过乐观锁和悲观锁进行数据库事务的并发控制。而在redis 中是通过watch 加乐观锁对数据库进行并发控制。
mysql 悲观锁是通过select * from table where <condition> for update将数据加锁,导致其他线程或事务不能更新该数据。相对于悲观锁,在对数据库进行处理的时候,乐观锁并不会使用数据库提供的锁机制。一般的实现乐观锁的方式就是记录数据版本。数据版本为数据增加的一个版本标识。当读取数据时,将版本标识的值一同读出,数据每更新一次,同时对版本标识进行更新。当我们提交更新的时候,判断数据库表对应记录的当前版本信息与第一次取出来的版本标识进行比对,如果数据库表当前版本号与第一次取出来的版本标识值相等,则予以更新,否则认为是过期数据。
关系型数据库mysql 实现数据版本主要有两种方式,第一种是使用版本号,第二种是使用时间戳。使用版本号时,可以在数据初始化时指定一个版本号,每次对数据的更新操作都对版本号执行+1操作。并判断当前版本号是不是该数据的最新的版本号。

(图8-mysql乐观锁)
图8展示了mysql 乐观锁的示例,开启两个mysql 客户端,客户端1执行start transaction 查询数据,这时客户端2更新了客户端1查询到的数据及version 字段,然后客户端1在第3步试图更新在第一步中查询到的数据时因version 已改变因此更新失败。

(图9-redis 乐观锁(watch))
redis 是通过watch 命令监控数据是否发生变化实现乐观锁的。如图9所示打开两个redis 客户端,客户端1对数据tom2 进行watch,打开事务更改tom1,tom2,客户端2更改客户端1中watch 的对象,步骤3客户端1提交事务由于watch 的对象被更改了,导致事务放弃执行。
3事务的ACID 性质
下面讨论下事务的ACID 性质。传统关系型数据库事务具备ACID 性质,这里不做详细讨论。
针对Redis 事务具有原子性(Atomicity),一致性(Consistency),和隔离性(Isolation),当redis 在持久化模式运行时,也具备持久性(Durability)。在场景1~3和乐观锁示例中redis 全部执行事务队列中的sql 语句即使其中sql存在操作对象错误,要么全部discard放弃执行,因此redis 事务具有原子性(Atomicity)。
redis 事务在执行过程中发生错误或进程被终结,都能保证数据的一致性(Consistency)。因为redis 使用单线程串行方式来执行事务的,在执行事务期间不会对事务进行中断(一致性),因此redis 事务也具有隔离性(Isolation)。redis 可以只将运行结果保存在内存中,但当redis 服务器使用AOF 持久化模式并appendfsync 设置为always 时,程序执行sql 后会调用sync 函数将数据保存到硬盘里,因此redis 事务也可以具有持久性(Durability)。
通过下表对redis 事务和关系型数据库事务做一个简单的总结。
|
关系型数据库(mysql) |
redis |
|
|
开启事务 |
start transaction命令 |
multi命令 |
|
回滚事务 |
使用rollback命令可以回滚事务 |
不能回滚事务。但使用discard命令可以放弃事务queue中的sql |
|
提交事务 |
commit命令 即使遇到sql语法错误也会提交事务 |
exec命令 如果遇到sql语法错误会放弃事务中的sql |
|
悲观锁 |
使用select ... for update实现悲观锁 |
无 |
|
乐观锁 |
通常使用version或时间戳来实现乐观锁 |
使用watch监控对象变化来实现乐观锁 |
|
原子性(Atomicity) |
具备 |
具备 |
|
一致性(Consistency) |
具备 |
具备 |
|
隔离性(Isolation) |
具备 |
具备 |
|
持久性(Durability) |
具备 |
当redis服务器使用AOF持久化模式并appendfsync设置为always时具备 |
转自:http://www.sohu.com/a/111695683_464008
redis事务与关系型数据库事务比较的更多相关文章
- Cassandra事务与关系型数据库事务有何区别
Cassandra不会使用回滚和锁机制来实现关系型数据的ACID事务,相比较于提供原子性,隔离性和持久化,Cassandra提供最终(可调节的)一致性,让用户决定为每个事务提供强一致性或者最终一致性. ...
- Java Redis系列1 关系型数据库与非关系型数据库的优缺点及概念
Java Redis系列1 关系型数据库与非关系型数据库的优缺点及概念 在学习redis之前我们先来学习两个概念,即什么是关系型数据库什么是非关系型数据库,二者的区别是什么,二者的关系又是什么? ** ...
- 数据库事务隔离级ORACLE数据库事务隔离级别介绍
本文系转载,原文地址:http://singo107.iteye.com/blog/1175084 数据库事务的隔离级别有4个,由低到高依次为Read uncommitted.Read committ ...
- Spring的事务管理和数据库事务相关知识
1 初步理解 理解事务之前,先讲一个你日常生活中最常干的事:取钱. 比如你去ATM机取1000块钱,大体有两个步骤:首先输入密码金额,银行卡扣掉1000元钱:然后ATM出1000元钱. ...
- Spring事务传播及数据库事务操作
从Spring 事务配置说起 先看看Spring 事务的基础配置 <aop:aspectj-autoproxy proxy-target-class="true"/> ...
- Redis 01: 非关系型数据库 + 配置Redis
数据库应用的发展历程 单机数据库时代:一个应用,一个数据库实例 缓存时代:对某些表中的数据访问频繁,则对这些数据设置缓存(此时数据库中总的数据量不是很大) 水平切分时代:将数据库中的表存放到不同数据库 ...
- 关系型数据库事务遵循ACID原则
事务在英文中是transaction,和现实世界中的交易很类似,它有如下四个特性: 1.A (Atomicity) 原子性 原子性很容易理解,也就是说事务里的所有操作要么全部做完,要么都不做,事务成功 ...
- Redis(1.3)Redis的基本特性(事务、多数据库)
[1]两大特性 (1)多数据库 1个redis实例 可以有16个数据库,默认下标为0~15,默认连接到的是 0 下标的数据库. (2)事务 [2]多数据库 [2.1]概念 1个redis实例 可以有1 ...
- Redis 如何与数据库事务保持一致
考虑一个问题,redis 如何 与 数据库保持一致性的问题. 举栗子:如果我们在开发过程中遇到这样的一种情况,我们删除 redis中token 的同时 也需要修改数据库中 储存的 token 的状态为 ...
随机推荐
- UR机器人的位姿
一.Ur 移动命令 UR机器人移动,一共有三种移动指令,movej,movel,movep,分别是关节运动,线性运动,圆周运动. movej:6个关节的弧度 movel/movep:分别是x,y,z, ...
- Fork 多进程 模拟并行访问web service获取响应时间差
#include <ros/ros.h> #include <iostream> #include <string> #include <cstring> ...
- 富文本编辑器TinyMCE的使用(React Vue)
富文本编辑器TinyMCE的使用(React Vue) 一,需求与介绍 1.1,需求 编辑新闻等富有个性化的文本 1.2,介绍 TinyMCE是一款易用.且功能强大的所见即所得的富文本编辑器. Tin ...
- DevOps实施历程-v1.0
有AF项目的成功案例(DevOps实施历程-半自动化),公司新项目全部依此为模板,实现了从代码到安装的自动化流水线,为此我输出了Jenkins自动化指南.AF项目指南等文档,方便大家查阅和参 ...
- 微信公众平台注册及AppID和AppSecret的获取
一.注册公众平台 1.入口 浏览器搜索“微信公众平台”,进入官网,点右上角立即注册. 2.选择账号类型 注册前需要选择一个账号类型,共有4个账号类型可以选择,每种类型能提供不同的功能,功能区别见下图. ...
- 利用DoHome APP和音箱控制继电器通断电实验参考步骤
准备材料: Arduino Uno 一块 Arduino 扩展板 购买链接 DT-06模块一个 购买链接 安卓手机一个 小度音箱一个 继电器模块一个 杜邦线若干 1.DT-0 ...
- 【POJ - 2387】Til the Cows Come Home(最短路径 Dijkstra算法)
Til the Cows Come Home 大奶牛很热爱加班,他和朋友在凌晨一点吃完海底捞后又一个人回公司加班,为了多加班他希望可以找最短的距离回到公司.深圳市里有N个(2 <= N < ...
- 【I'm Telling the Truth】【HDU - 3729】 【匈牙利算法,DFS】
思路 题意:该题主要说几个同学分别说出自己的名次所处区间,最后输出可能存在的未说谎的人数及对应的学生编号,而且要求字典序最大. 思路:刚刚接触匈牙利算法,了解的还不太清楚,附一个专门讲解匈牙利算法的博 ...
- 如何彻底禁用 werfalut.exe
在程序中调用 控制台程序 的时候,一旦出现控制台出现 crash 往往会弹出 werfault 窗口, 这样往往会锁死线程,导致程序无法继续运行. 那如何禁止 werfault 窗口的弹出呢? 在 s ...
- springboot整合solr
上一篇博客中简要写了solr在windows的安装与配置,这一篇接上文写一下springboot整合solr,代码已经上传到github,传送门. 1.新建core并配置schema 上篇博客中已经有 ...