Redis学习笔记(二十一) 事务
文章开始啰嗦两句,写到这里共21篇关于redis的琐碎知识,没有过多的写编程过程中redis的应用,着重写的是redis命令、客户端、服务器以及生产环境搭建用到的主从、哨兵、集群实现原理,如果你真的能看的进去,相信对你在以后用到redis时会有一定的帮助。
写到现在,redis相关的内容暂时告一段落了,以后可能更着重的去介绍c#相关的知识,包括用到IL、.net core底层、微服务等知识。
哎呀,写着写着突然又想啰嗦几句,最近几年c#在国内式微java如日中天,好多微软系的小伙伴或者各路大神都不看好c#,网上相关的帖子更是多如牛毛,另外一个现象就是从职位到薪资被java、go等语言甩了n条街。
但我觉得抛开这些外界因素,单从技术或者说是语言上讲c#其实非常优秀,虽然近几年.net core 有些不伦不类、各种借鉴(抄袭)其他语言的语法糖、各个大版本之间不兼容等问题一堆,但是这并不影响他的优秀,毕竟成长确实要走很多弯路,所以希望有兴趣继续搞搞.net 的童鞋可以持续关注c#。
Redis通过MULTI、EXEC、WATCH等命令来实现事务,事务提供了一种将多个命令请求打包,然后一次性、按顺序地执行多个命令的机制,并且在事务执行期间,服务器不会中断事务而改去执行其他客户端命令请求,他会将事务中的所有命令执行完毕,然后采取处理其他客户端的命令请求。
一个事务从开始到结束通常会经历以下三个阶段:事务开始、命令入队、事务执行。
1)事务开始
MULTI命令的执行标志是事务的开始,MULTI命令可以将执行该命令的客户端的从非事务状态切换至事务状态,这一切是通过在客户端状态的flags属性中打开REDIS_MULTI标识来完成的。
2)命令入队
如果客户端发送的命令为EXEC、DISCARD、WATCH、MULTI四个命令的其中一个,那么服务器立即执行这个命令,相反,服务器并不会立即执行这个命令,而是将命令放入到一个事务队列中,而后向客户端返回QUEUED回复。
每个Redis客户端都有自己的事务状态,这个事务状态保存在客户端状态的mstate属性里面:
typedef struct redisClient{
//事务状态
multiState mstate;
} redisClient;
事务状态包含一个事务队列,以及一个已入队命令的计数器:
typedef struct multiState{
//事务队列,FIFO顺序
multiCmd *commands;
///已入队列计数
int count;
} multiState;
typedef struct multiCmd{
//参数
robj **argv;
//参数数量
int argc;
//命令指针
struct redisCommand *cmd;
} multiCmd;
事务队列以先进先出的方式 保存入队的命令。
3)执行事务
当一个处于事务状态的客户端向服务器发送EXEC命令时,这个EXEC命令将立即被服务器执行。服务器会遍历这个客户端的事务队列,执行队列中保存的所有命令,最后将执行命令所得的结果全部返回给客户端。
WATCH命令
watch命令是一个乐观锁,它可以在exec命令执行之前,监视任意数量的数据库键,并在EXEC命令执行时,检查被监视的键是否至少有一个已经被修改过,如果是的话,服务器将拒绝执行事务,并向客户端返回标识事务执行失败的空回复。
每个Redis数据库都保存着一个watched_keys字典,这个键是某个被watch命令监视的数据数据库键,而字典的值是一个链表,链表中记录了所有被监视相应数据库键的客户端。
typedef struct redisDb{
//正在被watch命令监视的键
dict *watched_keys;
} redisDb;
监视机制的触发:所有对数据库进行修改的命令,在执行之后都会调用touchWatchKey函数对watched_keys字典进行检查,查看是否在客户端正在监视刚刚被命令修改过的数据库键,如果有的话,那么touchWatchKey函数会将监视被修改键的客户端的REDIS_DIRTY_CAS标识打开,标识该客户端的事务安全性已经被破坏。
判断事务是否安全
当服务器接收到一个客户端发来的EXEC命令时,服务器会根据客户端是否打开REDIS_DIRTY_CAS标识来决定是否执行事务:如果客户端的REDIS_DIRTY_CAS标识已经被打开,那么说明客户端所监视的键当中,至少有一个键已经被修改过了,在这种情况下,客户端提交的事务已经不再安全,所以服务器会拒绝执行客户端提交的事务;如果客户端REDIS_DIRTY_CAS标识没有被打开,那么说明客户端监视的所有键都没有被修改过,事务仍然是安全的,服务器将执行客户端提交的这个事务。
事务的ACID性质
原子性:Redis的事务和传统的关系型数据库事务最大的区别在于,Redis不支持事务回滚机制,事务队列中的某个命令在执行期间出现错误,整个事务也会继续执行下去,直到将事务队列中的所有命令都执行完毕为止。
一致性:
1、入队错误,如果一个事务在入队命令的过程中,出现了命令不存在,或者命令的格式不正确的情况那么Redis将拒绝执行这个事务
2、执行错误:执行过程中发生的错误都是一些不能再入队时被服务器发现的错误,这些错误只会在命令实际执行时被触发;即使在事务的执行过程中发生了错误,服务器也不会中断事务的执行,他会继续执行事务中余下的其他命令,并且一致性的命令不会被出错的命令影响。
3、服务器停机:如果服务器运行在无持久化的内存模式中,那么重启之后数据库将是一片空白的,因此数据总是一致性的;如果服务器运行了RDB模式下,那么事务中途停机不会导致不一致性,因为服务器可以根据现有的RDB文件来恢复数据,从而将数据库还原到一个一致性的状态。如果服务器运行在APF模式下,那么事务中途停机不会导致不一致性,因为服务器可以根据现有的APF文件来恢复数据,从而将数据库还原至一致的状态。
隔离性:Redis使用单线程的方式执行事务,并且服务器保证,在执行事务期间不会对事务中断,因此,redis的事务总是以串行的方式运行,并且事务也总是具有隔离性的。
耐久性:Redis事务的耐久性由Redis所使用的持久化模式决定的,(不论Redis在什么模式下运行,在一个事务的最后加上SAVE命令总可以保证事务的耐久性。)
每天学一点,总会有收获。
说明:尊重作者知识产权,文中内容参考《Redis设计与实现》,仅在此做学习与大家分享。
Redis学习笔记(二十一) 事务的更多相关文章
- Redis学习笔记二 (BitMap算法分析与BitCount语法)
Redis学习笔记二 一.BitMap是什么 就是通过一个bit位来表示某个元素对应的值或者状态,其中的key就是对应元素本身.我们知道8个bit可以组成一个Byte,所以bitmap本身会极大的节省 ...
- python3.4学习笔记(二十一) python实现指定字符串补全空格、前面填充0的方法
python3.4学习笔记(二十一) python实现指定字符串补全空格.前面填充0的方法 Python zfill()方法返回指定长度的字符串,原字符串右对齐,前面填充0.zfill()方法语法:s ...
- (C/C++学习笔记) 二十一. 异常处理
二十一. 异常处理 ● 异常的概念 程序的错误通常包括:语法错误.逻辑错误.运行异常. 语法错误指书写的程序语句不合乎编译器的语法规则,这种错误在编译.连接时由编译器指出. 逻辑错误是指程序能顺利运行 ...
- redis学习笔记 - Pipeline与事务
原文 Redis提供了5种数据结构,但除此之外,Redis还提供了注入慢查询分析,Redis Shell.Pipeline.事务.与Lua脚本.Bitmaps.HyperLogLog.PubSub.G ...
- Redis学习笔记(十一) 服务器
Redis服务器负责与多个客户端建立网络通信,处理客户端发送的命令请求,在数据库中保存客户端执行命令所产生的数据,并通过资源管理来维持服务器自身的运转. 命令请求过程 以set命令为例 1.客户端向服 ...
- Redis学习笔记二
学习Redis添加Object时,由于Redis只能存取字符串String,对于其它数据类型形容:Int,long,double,Date等不提供支持,因而需要设计到对象的序列化和反序列化.java序 ...
- Redis学习笔记二:单机数据库的实现
1. 数据库 服务器中的数据库 Redis服务器将所有数据库都保存在服务器状态redis.h/redisServer结构的db数组中,db数组的每个项都是一个redis.h/redisDb结构,每个r ...
- redis 学习笔记二 (简单动态字符串)
redis的基本数据结构是动态数组 一.c语言动态数组 先看下一般的动态数组结构 struct MyData { int nLen; char data[0]; }; 这是个广泛使用的常见技巧,常用来 ...
- Java基础学习笔记二十一 多线程
多线程介绍 学习多线程之前,我们先要了解几个关于多线程有关的概念.进程:进程指正在运行的程序.确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于运行过程中的程序,并且具有一定独立功能. 线 ...
- StackExchange.Redis学习笔记(二) Redis查询 五种数据类型的应用
ConnectionMultiplexer ConnectionMultiplexer 是StackExchange.Redis的核心对象,用这个类的实例来进行Redis的一系列操作,对于一个整个应用 ...
随机推荐
- redis学习——day01_redis简介与安装
一.Redis 简介 1.1 Redis是什么 REmote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo写的key-value存储系统.Redi ...
- C# 使用RestClient 调用接口
最近做项目使用RestClient 向第三方接口推送数据.不废话直接贴代码 /// <summary> /// 获取Token /// </summary> /// <r ...
- 一篇文教你使用python Turtle库画出“精美碎花小清新风格树”快来拿代码!
Turtle库手册可以查询查询 python图形绘制库turtle中文开发文档及示例大全,手册中现有示例,不需要自己动手就可以查看演示. 使用Turtle画树,看了一下网上的代码,基本上核心的方法是使 ...
- [PHP学习教程 - 网络]001.下载/采集远程文件到本地(Download File)
引言:如何把http://mzitu.com里的图片全部下载下来呢? 一身浩然正气的AC陷入的深思.... 当然这里涉及到的功能有线程,网页请求,页面提取,下载图片等等.今天,我们先讲一下如何下载文件 ...
- 画出决策边界线--plot_2d_separator.py源代码【来自python机器学习基础教程】
import numpy as np import matplotlib.pyplot as plt from .plot_helpers import cm2, cm3, discrete_scat ...
- CAD文件打印为PDF文档
标题: CAD文件打印为PDF文档 作者: 梦幻之心星 347369787@QQ.com 标签: [CAD, 打印, 转换] 目录: 软件 日期: 2019-5-28 目录 CAD文件打印为PDF文档 ...
- debug PHP程序(xdebug、IntelliJ IDEA)
之前写PHP程序的都是echo调试,今天感觉太麻烦了就想起研究一下IntelliJ IDEA如何调试PHP程序. 从网上查找了很多资料,大部分都提到在IDE里开启服务,一下就懵了,怎么启这么多服务呢. ...
- ES6-面向对象即类
简单介绍 在ES6面向对象基本上与java的类实现类似 1 class关键字,构造器和类分开了 1.1 ES5代码如下 <!DOCTYPE html> <html lang=&quo ...
- Java Word中的文本、图片替换功能
Word中的替换功能以查找指定文本然后替换为新的文本,可单个替换或全部替换.以下将要介绍的内容,除常见的以文本替换文本外,还将介绍使用不同对象进行替换的方法,具体可包括: 1. 指定字符串内容替换文本 ...
- xss(跨站脚本攻击)
xss(跨站脚本攻击) 原理:攻击者可以通过在页面中注入恶意链接或者脚本代码,当受害者访问时,脚本代码会在其浏览器中执行,这个时候,我们可以获取当前用户的cookie或者进行重定向等操作. xss造成 ...