Redis篇5-redis事务

概述

  • 官方说明:https://redis.io/topics/transactions
  • redis“部分”支持事务(部分回滚)
  • 关键命令
    • MULTI 开始事务
    • EXEC 开始执行事务内命令s
    • DISCARD 取消事务并放弃事务内命令s的执行
    • WATCH 监视一个或多个key,开始乐观锁CAS的事务操作
    • UNWATCH 取消所有key监视
  • 从Redis2.2开始支持用于乐观锁的check-and-set (CAS)

开始使用

multi-exec正常提交

mset k1 v1 k2 v2 k3 v3
multi
set k1 vv1
get k1
set k4 v4
get k4
exec
keys *

multi-exec异常1-注意

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k5 v5
QUEUED
127.0.0.1:6379> set k1 11 12
QUEUED
127.0.0.1:6379> exec
1) OK
2) (error) ERR syntax error
127.0.0.1:6379> get k5
"v5"
127.0.0.1:6379> get k1
"vv1"
127.0.0.1:6379> keys *
1) "k5"
2) "k1"
3) "k2"
4) "k3"
5) "k4"

可以看出,multi后加入事务命令OK,但exec执行时出错时,并没有全部回滚。。

multi-exec异常2-说redis“部分支持事务”的原因

127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> getset k3
(error) ERR wrong number of arguments for 'getset' command
127.0.0.1:6379> getset k3 v3
QUEUED
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> keys *
(empty list or set)

可以看出,exec之前出错,整个事务回滚,即DISCARD。

主动 DISCARD

127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> get k2
QUEUED
127.0.0.1:6379> discard
OK
127.0.0.1:6379> keys *
(empty list or set)

discard比较好理解,就是主动退出/回滚事务,取消命令的执行。

乐观锁-WATCH-CAS

  • 乐观锁一般相对于悲观锁理解,优点是不阻塞,缺点是失败率变高
  • 事务开始前(multi),watch目标key,如果提交前目标key被其他会话改动(即CAS过程),则事务回滚(DISCARD)
  • client1,session1
127.0.0.1:6379> get k1
"vv1"
127.0.0.1:6379> watch k1
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k1 0v1
QUEUED
127.0.0.1:6379> get k1
QUEUED
127.0.0.1:6379> exec
(nil)
127.0.0.1:6379> get k1
"v1"
127.0.0.1:6379> get k1
"v1"
127.0.0.1:6379> get k2
"v2"
127.0.0.1:6379> watch k1
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set k1 vv1
QUEUED
127.0.0.1:6379> set k2 vv2
QUEUED
127.0.0.1:6379> exec
(nil)
127.0.0.1:6379> mget k1 k2
1) "vvvv1"
2) "v2"
  • client2,session2,在session1 watch k1后exec前执行以下
127.0.0.1:6379> get k1
"vv1"
127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> set k1 vvvv1
OK
127.0.0.1:6379> get k1
"vvvv1"

可以看到结果是全部回滚。


关于redis“部分支持事务”

由上面使用可以看出redis事务并不像传统数据库事务那么“纯粹”——出错便全体回滚。
大部分场景都是“部分事务回滚”,表现有点类似spring配置事务传播行为的 RequiredNew

redis事务操作出错是否全部回滚,本身也“看情况”

  • exec之前出错
    multi到exec之间可以看成是批量收集命令的过程,这个过程中出错(没有QUEUED),exec执行就会全体回滚,相当于主动DISCARD,比如命令的语法错误。
  • exec之后出错
    命令全部收集OK了(QUEUED),此时出错则不会全体回滚,比如对键做了错误操作,类似spring配置事务传播行为的 RequiredNew,提交一个算一个。
  • 官方关于为什么不支持传统回滚的原因(说白了就是redis很快,不需要)
    https://redis.io/topics/transactions#why-redis-does-not-support-roll-backs

    Why Redis does not support roll backs?

当然,使用 watch-multi-cas-exec 不一样,这会DISCARD,代表全部回滚。

综上,结合与传统数据库事务特点的对比,redis“部分支持事务”:

  • exec执行与提交
    redis在exec之前,只是先攒着命令,并没有执行过(传统的数据库是执行了,事后通过undo日志来回滚),exec之后就是批量命令顺序执行,执行多少就多少,提交一个算一个。
  • 不保证原子性
    即上面说的,exec之后,“事务”中的命令,如果有一个出错,其后的命令会继续执行,不受影响。exec之前的话,有点像我们进行编程时的操作前校验,“校验”(指加入命令队列)不通过,便不再继续,也就是redis所谓的回滚(DISCARD)。

原文地址:https://www.cnblogs.com/noodlerkun/p/11503655.html

时间: 2024-10-11 01:37:11

Redis篇5-redis事务的相关文章

《【面试突击】— Redis篇》-- Redis哨兵原理及持久化机制

能坚持别人不能坚持的,才能拥有别人未曾拥有的.关注编程大道公众号,让我们一同坚持心中所想,一起成长!! <[面试突击]— Redis篇>-- Redis哨兵原理及持久化机制 在这个系列里,我会整理一些面试题与大家分享,帮助年后和我一样想要在金三银四准备跳槽的同学.我们一起巩固.突击面试官常问的一些面试题,加油!! <[面试突击]— Redis篇>--Redis数据类型?适用于哪些场景? <[面试突击]— Redis篇>--Redis的线程模型了解吗?为啥单线程效率还这么

【Redis篇】Redis持久化方式AOF和RDB

一.前述 持久化概念:将数据从掉电易失的内存存放到能够永久存储的设备上. Redis持久化方式RDB(Redis DB)   hdfs:    fsimageAOF(AppendOnlyFile)   hdfs :    edit logs    默认关闭的 二.RDB方式 在默认情况下,Redis 将数据库快照保存在名字为 dump.rdb的二进制文件中 在RDB方式下,有两种方式, 1.一种是手动执行持久化数据命令来让redis进行一次数据快照,而手动执行持久化命令,你依然有两种选择,那就是

【Redis篇】Redis集群安装与初始

一.前述 本文将单台节点不同端口模拟集群方式. 二.具体搭建 前提是安装好redis具体可参考http://www.cnblogs.com/LHWorldBlog/p/8463269.html 1.规划 redis集群 3.x版本物理节点1个指定3个主节点端口为7000.7001.7002对应的3个从节点端口为7003.7004.7005 2.创建配置 mkdir cluster-testcd cluster-testmkdir 7000 7001 7002 7003 7004 7005在700

Redis学习笔记(7)-事务

package cn.com; import java.util.List; import redis.clients.jedis.Jedis; import redis.clients.jedis.Transaction; public class Redis_Transactions { public static Jedis redis = new Jedis("localhost", 6379);// 连接redis /** * 基本事务用法 * 默认给user1,user2都

Redis 发布订阅、事务、脚本、连接、HyperLogLog

欢迎大家加入 459479177QQ群进行交流 本次主要介绍Redis的发布订阅.事务.脚本.连接.HyperLogLog 一.发布订阅 1>psubscribe,订阅一个或多个指定的频道 Reading messages... (press Ctrl-C to quit) 1) "psubscribe" 2) "tv1" 3) (integer) 1 127.0.0.1:6379> psubscribe tv2 tv3                \

[转至云风的博客]谈谈陌陌争霸在数据库方面踩过的坑( Redis 篇)

« 谈谈陌陌争霸在数据库方面踩过的坑(芒果篇) | 返回首页 | linode 广告时间 » 谈谈陌陌争霸在数据库方面踩过的坑( Redis 篇) 注:陌陌争霸的数据库部分我没有参与具体设计,只是参与了一些讨论和提出一些意见.在出现问题的时候,也都是由肥龙.晓靖.Aply 同学判断研究解决的.所以我对 Redis 的判断大多也从他们的讨论中听来,加上自己的一些猜测,并没有去仔细阅读 Redis 文档和阅读 Redis 代码.虽然我们最终都解决了问题,但本文中说描述的技术细节还是很有可能与事实相悖

Redis资料汇总(四) 事务

edis对事务的支持目前还比较简单.redis只能保证一个client发起的事务中的命令可以连续的执行,而中间不会插入其他client的 命令. 由于redis是单线程来处理所有client的请求的所以做到这点是很容易的.一般情况下redis在接受到一个client发来的命令后会立即处理并 返回处理结果,但是当一个client在一个连接中发出multi命令有,这个连接会进入一个事务上下文,该连接后续的命令并不是立即执行,而是先放到一 个队列中.当从此连接受到exec命令后,redis会顺序的执行

redis深入学习(三)-----事务、主从复制、jedis

reids事务 概念 可以一次执行多个命令,本质是一组命令的集合.一个事务中的所有命令都会序列化,按顺序地串行化执行而不会被其它命令插入,不许加塞 作用 一个队列中,一次性.顺序性.排他性的执行一系列命令 常用命令 正常操作事务: 放弃事务: 其实redis对于事务是部分支持: 例如incr k1虽然是错误的(类似于java的运行时异常),但是其他几个结果依然可以成功操作. watch监控 悲观锁/乐观锁/CAS(Check And Set) 1.悲观锁 悲观锁(Pessimistic Lock

java之redis篇(spring-data-redis整合) (转)

redis的知识:官网 1,利用spring-data-redis整合 项目使用的pom.xml: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apach

Redis-cluster集群【第一篇】:redis安装及redis数据类型

Redis介绍: 一.介绍 redis 是一个开源的.使用C语言编写的.支持网络交互的.可以基于内存也可以持久化的Key-Value数据库. redis的源码非常简单,只要有时间看看谭浩强的C语言,在去看redis的源码能看懂50-60%. redis目前最大的集群应该是新浪的应该. redis目前是vmvaer来支持的,很多的开源软件都需要某些组织来支持的.如果一个开源软件没有金钱来支持的话很难走的持久 二.Redis和Memcache对比 持久化:以电商举例,session用memcache