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结合springboot进行分页查询和按条件进行查询

    界面: 主要代码: 搜索框: <el-form ref="searchForm" :inline="true" :model="searchMa ...

  2. 如何做系列(4)-微博URL短网址生成算法原理(java版、php版实现实例)

    短网址(Short URL),顾名思义就是在形式上比较短的网址.通常用的是asp或者php转向,在Web 2.0的今天,不得不说,这是一个潮流.目前已经有许多类似服务,借助短网址您可以用简短的网址替代 ...

  3. UOJ#449 喂鸽子

    题意:有n个鸽子,你每秒随机喂一只鸽子,每只鸽子吃k次就饱了.求期望多少秒之后全饱了.n <= 50, k <= 1000. 解:有两种做法.一种直接DP的n2k做法在这.我用的是Min- ...

  4. SQLServer-SQLServer2017:SQLServer2017

    ylbtech-SQLServer-SQLServer2017:SQLServer2017 微软推出了首个公共预览版本,并持续带来更新和改进.而今天,微软同时向 Windows.Linux.macOS ...

  5. mysql利用MySQLWorkbench生成数据表之间的关系图

    先看结果,默认是展开的,我手动把表折叠了 那么如何实现呢 先点击这里 然后通过向导来创建即可,一直到finish就行了

  6. 谷歌浏览器flash被禁用解决方法

    谷歌浏览器访问设置:chrome://settings/content/flash 把要启动flash插件的网址添加进去

  7. Mac下,spacy配置

    pip3 install -U spacy -i http://pypi.douban.com/simple --trusted-host pypi.douban.com python3 -m spa ...

  8. TCP/TP:DNS区域(Zone)

    之前阅读资料不是特别明白,看到一个博主的解释,豁然开朗,特此记录. https://blog.csdn.net/huangzx3/article/details/79347556 DNS区域(ZONE ...

  9. [Array] 561. Array Partition I

    Given an array of 2n integers, your task is to group these integers into n pairs of integer, say (a1 ...

  10. Django项目:CRM(客户关系管理系统)--32--24PerfectCRM实现King_admin自定义操作数据

    #admin.py # ————————01PerfectCRM基本配置ADMIN———————— from django.contrib import admin # Register your m ...