Redis事务提供了一种将多个命令请求打包,然后一次性、按照顺序地执行多个命令的机制,并且在事务执行的期间,服务器不会中断事务而去执行其他不在事务中的命令请求,它会把事务中所有的命令都执行完毕才会去执行其他的命令。

How

Redis中提供了multi、discard、exec、watch、unwatch这几个命令来实现事务的功能。

Redis的事务始于multi命令,之后跟着要在事务中执行的命令,终于exec命令或者discard命令。加入事务中的所有命令会原子的执行,中间不会穿插执行其他没有加入事务的命令。

multi、exec和discard

multi命令告诉Redis客户端要开始一个事物,然后Redis会返回一个OK,接下来所有的命令Redis都不会立即执行,只会返回QUEUED结果,直到遇到了exec命令才会去执行之前的所有的命令,或者遇到了discard命令,会抛弃执行之前加入事务的命令。

127.0.0.1:6379> get name

(nil)

127.0.0.1:6379> get gender

(nil)

127.0.0.1:6379> multi

OK

127.0.0.1:6379> set name Slogen

QUEUED

127.0.0.1:6379> set gender male

QUEUED

127.0.0.1:6379> exec

1) OK

2) OK

127.0.0.1:6379> mget name gender

1) "Slogen"

2) "male"

watch

watch命令是Redis提供的一个乐观锁,可以在exec执行之前,监视任意数量的数据库key,并在exec命令执行的时候,检测被监视的key是否至少有一个已经被修改,如果是的话,服务器将拒绝执行事务,并向客户端返回代表事务执行失败的空回复。

首先在client1执行下列命令:

127.0.0.1:6379> get name

(nil)

127.0.0.1:6379> watch name

OK

127.0.0.1:6379> multi

OK

127.0.0.1:6379> set name slogen

QUEUED

127.0.0.1:6379> set gender male

QUEUED

127.0.0.1:6379> get name

QUEUED

这个时候client还没有执行exec命令,接下来在client2下执行下面命令修改name:

127.0.0.1:6379> set name rio

OK

127.0.0.1:6379> get name

"rio"

接下来在client1下执行exec命令:

127.0.0.1:6379> exec

(nil)

127.0.0.1:6379> get name

"rio"

从执行结果可以看到,在client1中执行exec命令的时候,Redis会检测到name字段已经被其他客户端修改了,所以拒绝执行事务中所有的命令,直接返回nil表示执行失败。这个时候获取到的name的值还是在client2中设置的rio。

Why

multi

Redis的事务始于multi命令,那么就从multi命令的源代码开始分析。

当Redis接收到客户端发送过来的命令之后会执行multiCommand()这个方法,这个方法在multi.c文件中。

void multiCommand(client *c) {

// 1. 如果检测到flags里面已经包含了CLIENT_MULTI

// 表示对应client已经处于事务的上下文中,返回错误

if (c->flags & CLIENT_MULTI) {

addReplyError(c,"MULTI calls can not be nested");

return;

}

// 2. 开启flags的CLIENT_MULTI标识

c->flags |= CLIENT_MULTI;

// 3. 返回ok,告诉客户端已经成功开启事务

addReply(c,shared.ok);

}

从源代码中可以看到,multiCommand()主要完成下面三件事:

检测发送multi命令的client是否已经处于事务中,如果是则直接返回错误。从这里可以看到,Redis不支持事务嵌套执行。

给对应client的flags标志位中增加MULTI_CLIENT标志,表示已经进入事务中。

返回OK告诉客户端已经成功开启事务。

Redis 源码学习之 Redis 事务Nosql的更多相关文章

  1. Redis源码学习:字符串

    Redis源码学习:字符串 1.初识SDS 1.1 SDS定义 Redis定义了一个叫做sdshdr(SDS or simple dynamic string)的数据结构.SDS不仅用于 保存字符串, ...

  2. Redis源码学习:Lua脚本

    Redis源码学习:Lua脚本 1.Sublime Text配置 我是在Win7下,用Sublime Text + Cygwin开发的,配置方法请参考<Sublime Text 3下C/C++开 ...

  3. redis源码学习之slowlog

    目录 背景 环境说明 redis执行命令流程 记录slowlog源码分析 制造一条slowlog slowlog分析 1.slowlog如何开启 2.slowlog数量限制 3.slowlog中的耗时 ...

  4. 柔性数组(Redis源码学习)

    柔性数组(Redis源码学习) 1. 问题背景 在阅读Redis源码中的字符串有如下结构,在sizeof(struct sdshdr)得到结果为8,在后续内存申请和计算中也用到.其实在工作中有遇到过这 ...

  5. __sync_fetch_and_add函数(Redis源码学习)

    __sync_fetch_and_add函数(Redis源码学习) 在学习redis-3.0源码中的sds文件时,看到里面有如下的C代码,之前从未接触过,所以为了全面学习redis源码,追根溯源,学习 ...

  6. Spring5.0源码学习系列之事务管理概述

    Spring5.0源码学习系列之事务管理概述(十一),在学习事务管理的源码之前,需要对事务的基本理论比较熟悉,所以本章节会对事务管理的基本理论进行描述 1.什么是事务? 事务就是一组原子性的SQL操作 ...

  7. redis源码学习之工作流程初探

    目录 背景 环境准备 下载redis源码 下载Visual Studio Visual Studio打开redis源码 启动过程分析 调用关系图 事件循环分析 工作模型 代码分析 动画演示 网络模块 ...

  8. redis源码学习之lua执行原理

    聊聊redis执行lua原理 从一次面试场景说起   "看你简历上写的精通redis" "额,还可以啦" "那你说说redis执行lua脚本的原理&q ...

  9. 玩一把redis源码(一):为redis添加自己的列表类型

    2019年第一篇文档,为2019年做个良好的开端,本文档通过step by step的方式向读者展示如何为redis添加一个数据类型,阅读本文档后读者对redis源码的执行逻辑会有比较清晰的认识,并且 ...

随机推荐

  1. 在vue中使用pug

    安装pug npm i pug pug-loader pug-cli pug-filters -D pug :安装pug pug-loader:pug的loader pug-cli:pug 编译工具 ...

  2. 高德地图定位不到 报错 location Error, ErrCode:7, errInfo:KEY错误 请到http://lbs.amap.com/api/android-location-sdk/abouterrorcode/查看错误码说明.

    出现该问题的可能是高德地图的配置不准确: 仔细配对一下 看sha1 是否是通过应用签名生成的  要区分发布版的sha1 跟调试版的sha1  是不相同的 (小编我第一次反这种错误的时候 是因为我把高得 ...

  3. walle(瓦力)部署系统的安装和简单使用

    Walle(瓦力):一套软件开发的部署系统.提供了清晰的日志记录,支持数据的回滚.用于解决大型团队在软件开发中的测试.预测试和上线的统一部署管理. 系统环境:CentOS6.8-A CentOS-6. ...

  4. 威胁快报|Solr dataimport成挖矿团伙新型利用方式

    概述 近日,阿里云安全团队监测到挖矿团伙利用solr dataimport RCE(CVE-2019-0193)作为新的攻击方式对云上主机进行攻击,攻击成功后下载门罗币挖矿程序进行牟利.该团伙使用的恶 ...

  5. 深喉起底APP线下预装市场,如何一夜间拥有千万用户

    注:预装对于中国的移动互联网创业者有多重要?i黑马知道这样一个内幕,某商务告诉我他们公司的前2000万用户就是靠预装打下来的,总部在北京,直接派驻商务长期扎根在深圳搞定手机厂商.而这家公司初期发展得益 ...

  6. openCV 矩阵(图像)操作函数

    有很多函数有mask,代表掩码,如果某位mask是0,那么对应的src的那一位就不计算,mask要和矩阵/ROI/的大小相等.大多数函数支持ROI,如果图像ROI被设置,那么只处理ROI部分 少部分函 ...

  7. sort方法

    作用:对列表进行排序 >>> spam=[2,5,3,14,1,-7] >>> spam.sort() >>> spam [-7, 1, 2, 3 ...

  8. Jmeter环境搭建及目录介绍

    Jmeter环境搭建及目录介绍 运行环境:jmeter是基于java语言的,所有需要准备Java的JDK环境,并添加到环境变量中. 一.环境搭建及配置 1.JMeter的下载: 官网:http://j ...

  9. tensorflow object detection faster r-cnn 中keep_aspect_ratio_resizer是什么意思

    如果小伙伴的英语能力强可以直接阅读这里:https://stackoverflow.com/questions/45137835/what-the-impact-of-different-dimens ...

  10. Laravel Carbon获取 某个时间后N个月的时间

    $time = "2020-11-20 00:00:00"; $res = (new Carbon)->setTimeFromTimeString($time)->ad ...