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事务与关系型数据库事务比较的更多相关文章

  1. Cassandra事务与关系型数据库事务有何区别

    Cassandra不会使用回滚和锁机制来实现关系型数据的ACID事务,相比较于提供原子性,隔离性和持久化,Cassandra提供最终(可调节的)一致性,让用户决定为每个事务提供强一致性或者最终一致性. ...

  2. Java Redis系列1 关系型数据库与非关系型数据库的优缺点及概念

    Java Redis系列1 关系型数据库与非关系型数据库的优缺点及概念 在学习redis之前我们先来学习两个概念,即什么是关系型数据库什么是非关系型数据库,二者的区别是什么,二者的关系又是什么? ** ...

  3. 数据库事务隔离级ORACLE数据库事务隔离级别介绍

    本文系转载,原文地址:http://singo107.iteye.com/blog/1175084 数据库事务的隔离级别有4个,由低到高依次为Read uncommitted.Read committ ...

  4. Spring的事务管理和数据库事务相关知识

    1 初步理解 理解事务之前,先讲一个你日常生活中最常干的事:取钱.         比如你去ATM机取1000块钱,大体有两个步骤:首先输入密码金额,银行卡扣掉1000元钱:然后ATM出1000元钱. ...

  5. Spring事务传播及数据库事务操作

    从Spring 事务配置说起 先看看Spring 事务的基础配置 <aop:aspectj-autoproxy proxy-target-class="true"/> ...

  6. Redis 01: 非关系型数据库 + 配置Redis

    数据库应用的发展历程 单机数据库时代:一个应用,一个数据库实例 缓存时代:对某些表中的数据访问频繁,则对这些数据设置缓存(此时数据库中总的数据量不是很大) 水平切分时代:将数据库中的表存放到不同数据库 ...

  7. 关系型数据库事务遵循ACID原则

    事务在英文中是transaction,和现实世界中的交易很类似,它有如下四个特性: 1.A (Atomicity) 原子性 原子性很容易理解,也就是说事务里的所有操作要么全部做完,要么都不做,事务成功 ...

  8. Redis(1.3)Redis的基本特性(事务、多数据库)

    [1]两大特性 (1)多数据库 1个redis实例 可以有16个数据库,默认下标为0~15,默认连接到的是 0 下标的数据库. (2)事务 [2]多数据库 [2.1]概念 1个redis实例 可以有1 ...

  9. Redis 如何与数据库事务保持一致

    考虑一个问题,redis 如何 与 数据库保持一致性的问题. 举栗子:如果我们在开发过程中遇到这样的一种情况,我们删除 redis中token 的同时 也需要修改数据库中 储存的 token 的状态为 ...

随机推荐

  1. Okhttp3 网络请求框架与 Gson

    Maven环境 : <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>o ...

  2. 启动Eclipse提示找不到虚拟机

    由于硬盘坏了,把所有东西都清光了,今天重新安装Eclipse,出现了一点小插曲 安装的时候出现了这个画面,以前安装也是照着[软件安装管家]的发布装的,幸好还懂得几个英文单词,看了一下提示信息,直译:[ ...

  3. java 遍历map的四种方法

    16:21:42 Map.entrySet() 这个方法返回的是一个Set<Map.Entry<K,V>>,Map.Entry 是Map中的一个接口,他的用途是表示一个映射项( ...

  4. 喜大普奔 | 微信小程序支持PC端打开了

    微信小程序可以在PC端打开啦 微信PC版发布了v2.7.0测试版,其中一个重磅的功能就是:支持打开聊天中分享的小程序 咖啡君这么喜欢尝鲜的人自然是在第一时间下载进行了体验 安装成功,会有功能更新说明 ...

  5. Maven多模块项目打包前的一些注意事项(打包失败)

    一. 最近在打包Maven项目时遇到了点问题,这个项目是Maven多模块项目,结构如下: projectParent├── xxxx-basic├── xxxx-web1├── xxxx-collec ...

  6. 算法与数据结构基础 - 折半查找(Binary Search)

    Binary Search基础 应用于已排序的数据查找其中特定值,是折半查找最常的应用场景.相比线性查找(Linear Search),其时间复杂度减少到O(lgn).算法基本框架如下: //704. ...

  7. koa2+vue实现登陆以及是否登陆控制

    这里我们先说说登陆以及登陆状态控制需要的插件jsonwebtoken,jsonwebtoken就可以实现token的生成与反向解密出用户数据.安装步骤: npm install jsonwebtoke ...

  8. str类型转json,str类型转list

    python str类型与json格式转换或者list格式转换 str转list: import ast #####方法一##### datas = '{"carname":&qu ...

  9. LoRaWAN_stack移植笔记 (二)_GPIO

    stm32相关的配置 由于例程使用的主控芯片为STM32L151C8T6,而在本设计中使用的主控芯片为STM32L051C8T6,内核不一样,并且Cube库相关的函数接口及配置也会有不同,所以芯片的驱 ...

  10. d3.js V5版本在vue里使用 自定义节点图片

    var width = this.$refs.topInfo.offsetWidth; var height = this.$refs.topInfo.offsetHeight; var img_w ...