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. .NET 内存泄漏的争议

    前几天发布了几篇关于要小心使用 Task.Run 的文章,看了博客园的所有评论.发现有不少人在纠结示例中的现象是不是属于内存泄漏,本文分享一下我个人的看法,大家可以保留自己的意见. 在阅读本文前,如果 ...

  2. 封装事件订阅来进行非父子组件的传值(React)

    const list={} // 将事件名和事件函数装进事件池里 function $on(name,func) { if(!name || !func) return; if(!Object.key ...

  3. vue 分支结构

    分支循环结构 分支循环结构指令 v-if v-else v-else-if v-show v-if 指令 可以直接在元素中添加指令,添加判断的值 最后运行可以得到结果是:  v-show v-show ...

  4. vue第十单元(动态组件 keep-alive(钩子函数) 递归组件(name) 组件命名约定)

    第十单元(动态组件 keep-alive(钩子函数) 递归组件(name) 组件命名约定) #课程目标 熟练掌握动态组件的实现 掌握keep-alive缓存组件,以及相应的钩子函数 熟练掌握递归组件, ...

  5. [日常摸鱼]Luogu2521[HAOI2011]防线修建-set维护凸包

    https://www.luogu.org/problemnew/show/2521 题意:维护一个上凸包:删点,查询周长 很容易想到把问题转换为离线:先读入全部操作,记录下最后剩下的点,倒着加点来维 ...

  6. MybatisPlus_01

    目录 1.1 简介 1.1.1 特性 1.1.2 框架结构 2.1 快速开始 2.1.1 2.1.2 yaml文件配置 2.1.3 编码 2.1.4 测试 3.1 思考 1.1 简介 MyBatis- ...

  7. 54 个官方 Spring Boot Starters 出炉!别再重复造轮子了…….

    在之前的文章,栈长介绍了 Spring Boot Starters,不清楚的可以点击链接进去看下. 前段时间 Spring Boot 2.4.0 也发布了,本文栈长再详细总结下最新的 Spring B ...

  8. 同一个UITextField 根据不同状态下弹出不同类型键盘遇到的坑

    一,需求:有多个选项按钮,点击不同的按钮,textfield内容需求不同弹出对应需求的键盘类型. 二,问题:1.刚开始在按钮状态改变后设置 self.textField.keyboardType属性完 ...

  9. Jquery Ajax如何添加header参数

    转自网络 1 $.ajax({ 2 type: "POST", 3 url: "http://192.168.0.88/action.cgi?ActionID=WEB_R ...

  10. Java:利用BigDecimal类巧妙处理Double类型精度丢失

    目录 本篇要点 经典问题:浮点数精度丢失 十进制整数如何转化为二进制整数? 十进制小数如何转化为二进制数? 如何用BigDecimal解决double精度问题? new BigDecimal(doub ...