Redis3.0.x 事务

基本概念

multi,exec,discard,watch 是 Redis 事务的基础,它们允许一步执行一组命令,有两个重要保证:

  • 事务中的所有命令都被序列化并顺序执行。在 Redis 事务的执行过程中,永远不会执行另一个客户端发出的请求。
  • 所有命令要么都被执行,要么都不被执行。

Redis 以 乐观锁的形式对这两个保证提供支持,其方式和 CAS(Check And Set,检查后设置)操作非常相似。

悲观锁:顾名思义,就是每次去拿数据的时候都认为会被修改,所以每次都会加上锁,这样再去拿数据的时候就会被阻塞,直到拿到锁。比如行锁、表锁、读写锁等,都是在操作之前先加上锁。

乐观锁:顾名思义,就是每次去拿数据的时候都认为不会被修改,所以都不会上锁,但是在更新的时候会判断在此期间有没有更新这个数据,可以使用版本控制等策略。一般使用于多读少写的应用。

版本控制策略:执行更新的前提是提交的版本必须大于当前记录的版本。

基本命令

  • MULTI:标记一个事务块的开始
  • EXEC:执行事务块内所有的命令
  • DISCARD:放弃执行事务块内所有的命令
  • WATCH key [key...]:监视一个或多个 key,如果在事务执行之前 这些 key 被其他命令改动,那么事务将被打断
  • UNWATCHL:取消 WATCH 对 所有 key 的监视

事务使用

正常执行

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> get k1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> exec
1) OK
2) "v1"
3) OK

放弃事务

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k3 v3
QUEUED
127.0.0.1:6379> get k3
QUEUED
127.0.0.1:6379> set k4 v4
QUEUED
127.0.0.1:6379> discard
OK
127.0.0.1:6379> get k3
(nil)
127.0.0.1:6379> get k4
(nil)

“编译”异常

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set name parzulpan
QUEUED
127.0.0.1:6379> get name
QUEUED
127.0.0.1:6379> set eamil
(error) ERR wrong number of arguments for 'set' command
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get name
(nil)

类似 Java 中的编译时异常,比如语法错误、内存不足等。这样情况下,命令无法排队,Redis 将拒绝执行事务,并且在 EXEC 期间还会返回错误并自动丢弃该事务。

“运行”异常

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k3 v3
QUEUED
127.0.0.1:6379> get k3
QUEUED
127.0.0.1:6379> set a 1
QUEUED
127.0.0.1:6379> get a
QUEUED
127.0.0.1:6379> incr k3
QUEUED
127.0.0.1:6379> exec
1) OK
2) "v3"
3) OK
4) "1"
5) (error) ERR value is not an integer or out of range

类似 Java 中的运行时异常,比如类型错误等。这种情况下,命令可以排序,Redis 将执行事务,只不过会对应的返回错误信息。

监控使用

初始化信用卡可用余额和欠额:

127.0.0.1:6379> set balance 1000
OK
127.0.0.1:6379> set debt 0
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby balance 100
QUEUED
127.0.0.1:6379> incrby debt 100
QUEUED
127.0.0.1:6379> exec
1) (integer) 900
2) (integer) 100
127.0.0.1:6379> get balance
"900"
127.0.0.1:6379> get debt
"100"

无监控键更改。先监控键在开启事务,保证交易金额变动在同一个事务里:

127.0.0.1:6379> watch balance
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby balance 100
QUEUED
127.0.0.1:6379> incrby debt 100
QUEUED
127.0.0.1:6379> exec
1) (integer) 800
2) (integer) 200

所有 监控键 都会具有从调用开始一直到调用EXEC为止 监视更改的效果。即执行完 EXEC,监控消失。


有监控键更改。开启多个终端,模拟更改监控键。

127.0.0.1:6379> get balance
"800"
127.0.0.1:6379> watch balance
OK
127.0.0.1:6379> set balance 900
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby balance 100
QUEUED
127.0.0.1:6379> incrby debt 100
QUEUED
127.0.0.1:6379> exec
(nil)
127.0.0.1:6379> get balance
"900"
127.0.0.1:6379> get debt
"200"

监控键受到监控,以检测其更改。如果在 EXEC 命令之前至少更改了一个监视键,则整个事务将中止,并且 EXEC 返回 Null 答复以通知该事务失败。


有监控键更改,但更改后解除监控。开启多个终端,模拟更改监控键。

127.0.0.1:6379> get balance
"800"
127.0.0.1:6379> get debt
"200"
127.0.0.1:6379> watch balance
OK
127.0.0.1:6379> set balance 900
OK
127.0.0.1:6379> unwatch
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set balance 700
QUEUED
127.0.0.1:6379> set debt 300
QUEUED
127.0.0.1:6379> exec
1) OK
2) OK
127.0.0.1:6379> get balance
"700"
127.0.0.1:6379> get debt
"300"

如果监控键受到监控,在更改之后,使用 UNAWTCH 解除监控,那么事务将正常执行。

为什么 Redis 不支持回滚

Redis 中不保证原子性,不支持回滚,即部分支持事务。主要有以下两个原因:

  • 仅当使用错误的语法(并且在命令排队期间无法检测到该问题)或针对包含错误数据类型的键调用 Redis 命令时,该命令才能失败。这实际上意味着失败的命令是编程错误的结果,还有一种很可能在开发过程中而不是生产过程中发现的错误。
  • Redis 在内部得到了简化和优化,所以它不需要回滚的能力。

Redis 脚本和事务

一个 Redis 的脚本是定义事务性的,所以可以用 Redis 的事务做的,也可以用一个脚本做,并且使用脚本会更简单,更快速。

练习和总结

【Redis3.0.x】事务的更多相关文章

  1. 【Redis3.0.x】NoSql 入门

    Redis3.0.x NoSql 入门 概述 NoSQL(Not Only SQL ),即不仅仅是 SQL,泛指非关系型的数据库.NoSQL 数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑 ...

  2. 【Redis3.0.x】实战案例

    Redis3.0.x 实战案例 简介 <Redis实战>的学习笔记和总结. 书籍链接 初识 Redis Redis 简介 Redis 是一个速度非常快的键值对存储数据库,它可以存储键和五种 ...

  3. Redis3.0 配置文件说明

    背景: 以前有篇文章已经结果过了,现在复习一下,对Redis3.0进行说明: 参数说明: #redis.conf # Redis configuration file example. # ./red ...

  4. redis3.0.6安装(linux和windows)

    官网上描述安装方法如下:$ wget http://download.redis.io/releases/redis-3.0.6.tar.gz$ tar xzf redis-3.0.6.tar.gz$ ...

  5. Redis3.0.1 Stable版本的集群部署(Mac)

    本文档基于如下原始文档(CentOS)创建: http://blog.csdn.net/xu470438000/article/details/42971091 修改了一些路径的错误,补全了一些命令执 ...

  6. Redis3.0.7 cluster/集群 安装配置教程

    1.前言 环境:CentOS-6.7-i386-LiveDVD 安装的CentOs系统 节点: 6个节点,3个主节点.3个从节点(由于redis默认需要3个主节点,如果想每个主节点有一个从节点,这是最 ...

  7. CentOS完美搭建Redis3.0集群并附测试

    线上的统一聊天和推送项目使用的是redis主从,redis版本2.8.6 redis主从和mysql主从目的差不多,但redis主从配置很简单,主要在从节点配置文件指定主节点ip和端口:slaveof ...

  8. redis3.0.0 集群安装详细步骤

    Redis集群部署文档(centos6系统) Redis集群部署文档(centos6系统) (要让集群正常工作至少需要3个主节点,在这里我们要创建6个redis节点,其中三个为主节点,三个为从节点,对 ...

  9. MAC air 安装redis-3.0.6

    redis版本: p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px Menlo; color: #c33720; background-colo ...

随机推荐

  1. Spring RestTemplate具备负载均衡功能

     在创建RestTemplate的Bean时使用@LoadBalanced注解, 就可以自动配置为使用ribbon.如下面的示例所示: @Configuration public class MyCo ...

  2. 【题解】「CF1182B」Plus from Picture

    这是一道超级水的模拟 + 简单搜索. 说说思路: 先找到中心点,就是自己和上下左右都为 * 的. 上下左右上的所有 * 都删掉,然后再看看有没有多余的 * 如果有输出 NO 否则输出 YES. 比如说 ...

  3. WindowsPhone8中LongListSelector的扩展解决其不能绑定SelectdeItem的问题

    微软在Wp8中集成了LongListSelector, 但是该控件在ViewModel中不能实现的SelectdeItem双向绑定,因为其不是DependencyProperty没办法只能实现扩展! ...

  4. DRF框架笔记

    序列化器类的定义格式? 继承serializers.Serializer:字段 = serializers.字段类型(选项参数) 序列化器类的基本使用? 序列化器类(instance=None, da ...

  5. Spark内核-部署模式

    Master URL Meaning local 在本地运行,只有一个工作进程,无并行计算能力. local[K] 在本地运行,有K个工作进程,通常设置K为机器的CPU核心数量. local[*] 在 ...

  6. SQL注入练习第一天

    MySQL 相关知识 在MySQL中,把[INFORMATION_SCHEMA] 看作是一个数据库,确切说是信息数据库.其中保存着关于MySQL服务器所维护的所有其他数据库的信息.如数据库名,数据库的 ...

  7. Core3.0使用Caching.Memory

    前言 参考链接: 使用缓存:https://www.cnblogs.com/gygg/p/11275417.html 过期时间:https://www.cnblogs.com/maijin/p/704 ...

  8. React组件的state和props

    React组件的state和props React的数据是自顶向下单向流动的,即从父组件到子组件中,组件的数据存储在props和state中.实际上在任何应用中,数据都是必不可少的,我们需要直接的改变 ...

  9. 时间盲注poc编写

    当测试注入漏洞时,页面没有返还结果,连报错都没有时,可以考虑延时. 比如这条语句 ?type=1 and if(length(database())=%d,sleep(5),1) 如果这条语句被服务器 ...

  10. [LeetCode]实现数学计算

    乘方 思路是:pow(x,n) = pow(x,n/2)*pow(x,n-n/2) 递归实现 public double myPow(double x, int n) { if (n==0) retu ...