Redis-事务与持久化

2023-11-15

事务

Redis提供了将多个命令请求打包,然后一次性,按顺序的执行多个命令的机制,这种机制叫事务,并且在事务执行的过程中,服务器不会中断事务去执行其他客户端的请求,而是将事务的所有命令都执行完毕在去执行其他客户端请求

事务命令

  • multi:开启事务
  • exec:执行事务
  • discard:取消事务
  • watch:监视

事务的实现

一个事务会经历以下三个阶段:

  • 事务开始
  • 命令入队
  • 事务执行
事务的开始

Redis中multi命令标志着事务的开始

myRedis:0>multi
"OK"

multi命令将执行的客户端从非事务状态切换到事务的状态,通过客户端的flags属性中打开REDIS_MULTI标识来完成切换

命令入队

客户端在非事务状态下,客户端发送的命令会被立即执行,而在事务状态下,客户端会判断不同的命令执行不同的操作

  • 如果命令是multi,exec,discard,watch服务器会立即执行
  • 如果命令不是multi,exec,discard,watch服务器不会立即执行,是把发送的命令放到一个事务队列里,然后返回queued回复
事务队列

每个Redis客户端都有自己的事务状态,状态保存在mstate属性中,事务状态包含事务的队列和已入命令的计数器(事务队列的长度)

typedef struct multiState {
    //存储命令的FIFO队列
    multiCmd *commands;
    //队列长度
    int count;
} multiState;

事务队列是一个multiCmd类型的数组,数组中每个元素都保存了一个入队命令相关的信息,结构如下

typedef struct multiCmd {
    //参数数组
    robj **argv;
    //参数数量
    int argc;
    //命令的指针
    struct redisCommand *cmd;
} multiCmd;

事务队列multiCmd ,以先进先出的方式(FIFO)保存入队命令

图解分析

myRedis:0>multi
"OK"

myRedis:0>set name guohu
"QUEUED"

myRedis:0>set age 28
"QUEUED"

myRedis:0>get name
"QUEUED"

myRedis:0>get age
"QUEUED"

在这里插入图片描述

执行事务

客户端处于事务状态时,向服务器发送exec命令,此时exec命令会被立即执行,并且服务器会遍历客户端的事务队列,执行队列中所有的命令,并将所有队列命令执行的结果返回给客户端(注意:命令是按顺序执行的,先进先出规则)

myRedis:0>exec
 1)  "OK"
 2)  "OK"
 3)  "guohu"
 4)  "28"

WATCH命令

watch命令是一个乐观锁,它可以在exec命令执行之前,监视任意数量的数据库键,并在exec命令执行时,检查是否至少有一个被修改过,如果监视到有修改,则拒绝执行事务,并想客户端发送事务执行失败的回复

执行时间 客户端A 客户端B
time1 watch “name”
time2 multi
time3 set age 28
time4 set 29
time5 exec
不监视的情况下

客户端A

myRedis:0>multi
"OK"

myRedis:0>set age 28
"QUEUED"

myRedis:0>get age
"QUEUED"

新起一个客户端B

myRedis:0>set age 29
"OK"

myRedis:0>get age
"29"

回到客户端A,执行事务提交

myRedis:0>exec
 1)  "OK"
 2)  "28"

按道理事务里面提交的set时29,但是当执行exec的时候,会发现数据被覆盖了

监视的情况下

客户端A执行命令

myRedis:0>flushdb
"OK"

myRedis:0>watch age
"OK"

myRedis:0>multi
"OK"

myRedis:0>set age 28
"QUEUED"

myRedis:0>set name guohu
"QUEUED"

myRedis:0>set address yinshanhu
"QUEUED"

myRedis:0>get name
"QUEUED"

myRedis:0>get address
"QUEUED"

另起一个客户端B执行

myRedis:0>set age 18
"OK"

myRedis:0>get age 
"18"

再次回到客户端A执行事务提交

myRedis:0>exec
(nil)

myRedis:0>get age
"18"

myRedis:0>get name
null

myRedis:0>get address
null

监视到age发生变化,整个事务拒绝执行name和address都没有保存

事务的ACID特性

A-原子性

事务中的原子性是指多个操作被打包成一个整体执行,要么全部执行,要么都不执行,就Redis性质来说,符合原子性的描述,事务里面的命令会被一起执行
但是Redis不支持事务回滚,如果其中有命令出错了,其他命令还会继续执行直到队列命令执行完毕

myRedis:0>multi
"OK"

myRedis:0>set name guohu
"QUEUED"

myRedis:0>incr name
"QUEUED"

myRedis:0>get name
"QUEUED"

myRedis:0>exec
 1)  "OK"
 2)  "ERR value is not an integer or out of range"
 3)  "guohu"
C-一致性

一致性指是指数据库在执行事务之前数据是一致的,在执行事务之后无论事务是否成功数据也是一致的,这符合数据库本身的定义和要求

I-隔离性

隔离性指的是,即使有多个事务并发的执行,各个事务之间页不会相互影响,并且在并发状态下执行的事务和串行执行的事务产生的结果完全相同,而在Redis中事务的所有命令都会按顺序执行,在执行Redis事务的过程中,另一个客户端发出的请求不会被处理,这保证了命令是作为单独的独立操作执行的

D-持久性

数据库持久性是指当一个事务执行完毕之后,所得到的结果已经被保存到永久性的存储介质中(例如:硬盘),事务执行完毕之后即使数据库宕机,也不会影响事务执行的结果,不过Redis中的持久性依赖其持久化机制和是否被开启持久化,如果没开启持久化就是纯内存运行,重启后数据会丢失,而Redis的持久化有两种模式RDB和AOF,下面会介绍具体的持久化机制

持久化

Redis是数据是存在内存里面的,同时Redis也提供了两种持久化机制RDB和AOF,将内存的数据刷到硬盘上,避免数据的意外丢失

RDB持久化(Redis DataBase)

RDB记录的是数据
RDB持久化既可以手动执行,也可以根据服务器的配置来定期执行,RDB文件时一个压缩的二进制文件(dump.rdb),通过RDB文件可以还原生成RDB时间节点的数据库状态,服务在重启的时候会自动加载RDB文件进行数据恢复,RDB文件时保存再硬盘上的,所以即使redis服务关闭了,仍然可以还原数据库恢复数据
在这里插入图片描述

手动执行命令
  • save
    • 会阻塞redis进程,直到RDB文件生成完毕,再生成期间服务不能处理任何请求
  • bgsave
    • 会派生出一个子进程,然后由子进程创建RDB文件,父进程继续处理请求
  • shutdown
    • 正常关机也会出发生成RDB文件
  • flushall
    • 注意flushdb不会触发RDB的生成
    • 不过flushall本身就是清除数据库的命令,生成的文件也是空的,没什么意义

在Redis服务启动时会自动检测是否存在RDB文件,如果存在则自动载入

自动间隔性保存

刚介绍了手动执行的两个命令,save和bgsave,由于bgsave可以不阻塞进程,Redis允许用户设置每隔一段时间自动执行bgsave的命令:

  • save 900 1 : 900秒内对数据库进行1次修改
  • save 300 10:300秒内对数据库进行10次修改
  • save 60 10000:60秒内对数据库进行了10000次修改
    满足以上三个条件其中一个,bgsave就会被执行,并且针对不同的类型,RDB会使用不同的方式存储(这里不做扩展了,不然这页博客就太细太长了)
RDB的优缺点分析

优点:

  • RDB时一个压缩文件,保存了不同时间点的状态,非常适合做灾备
  • RDB的bgsave可以派生子进程保存文件,不影响父级进程的处理,提高了Redis性能
  • 灾备恢复速度快

缺点:

  • 无法做到试试备份,只能间歇性保存RDB文件,如果非正常关机可能会丢失上次备份到宕机的数据
  • 创建子进程,通常父进程来执行fork操作,频繁的fork操作,严重者会导致父进程短时间不可用

AOF持久化(Append Only File)

与RDB不同的是,AOF持久化机制记录的是写命令
开启AOF之后,AOF是采用日志方式将写命令记录到文件中
在这里插入图片描述
需要注意的是,AOF默认是关闭的,如果同时使用AOF和RDB,Redis会优先使用AOF作为持久化模式

开启AOF配置

appendonly no  //默认是no表示关闭,修改为yes则表示开启
appendfilename "appendonly.aof"  //文件名

还可以通过appendfsync参数来控制是否实时写入磁盘

  • always:写入缓存的同时进行刷盘操作
  • everysec:先写入缓存,然后每秒进行一次刷盘操作(极限状态可能会丢失1s的数据)
  • no:只写入缓存,至于刷盘?随缘吧!看操作系统心情

AOF文件重写

AOF文件里包含了所有Redis的写命令,所以只要服务器读到所有命令并重新执行一遍即可还原数据库状态

虽然可以用命令还原数据库状态,但是此时暴漏了一个缺点,假设写命令很多,那文件岂不是越来越大,又或者针对一个key执行了N次操作,实际上有效操作只有最后一次,为了解决这个问题,Redis提供了AOF文件重写功能

重写条件
  • 自动触发,(配置控制,可修改)
    • auto-aof-rewrite-percentag :文件大小超过上次AOF重写之后的文件的百分比,默认100%(超过,是2倍)
    • auto-aof-rewrite-min-size:重写的最小AOF文件大小,默认64M
  • 手动触发:bgrewriteaof 命令
重写机制
  • 再执行重写文件的过程中,Redis会分析现有的键值对,然后聚合成一条命令记录
  • 如果是集合,列表,hash的话在超过元素数量(64个)也会用多条命令记录

备注:说是重写,但实际上是根据现有的键值对分析出写命令,与原文件没有操作关系

重写缓冲区

写文件一般都是子进程 ,此时父继承是不阻塞的,还可以继续接受处理请求,当AOF重写过程中,父进程又有新的请求,这时就需要保证数据的一致性了,在执行AOF重写的操作时,有个AOF 重写缓冲区的概念,如果在重写期间有新的命令进入,会同时写入AOF缓冲区和AOF重写缓冲区

假设子进程完成了文件重写,会向父进程发送一个信号量,父进程紧接着会进行阻塞,并完成重写的以下剩余工作,之后就可以正常处理请求了

  • 将 AOF重写缓冲区的内容刷新到AOF文件上
  • 将写好的AOF文件替换掉旧的AOF文件

AOF优缺点分析

优点

  • 可以通过修改配置自定义刷盘策略
  • 有重写机制,可以防止AOF文件过大的问题
  • 追加的方式记录操作日志,在非正常关机的情况下也可以实现数据库灾备
    缺点
  • RDB是压缩二进制,AOF是写操作日志,相对而言AOF文件更大
  • RDB是基于数据的,AOF是基于命令的如果遇到写操作的错误情况,AOF有可能出现不能完全还原数据库状态,RDB是快照的方式,还原方式更加严谨
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Redis-事务与持久化 的相关文章

随机推荐

  • hibernate之关于Hibernate的一级、二级缓冲

    Hibernate 一级 二级缓冲 Hibernate缓冲按级别共分为两种 一级缓冲 Session 和二级缓冲 SessionFactory 有的也说是三种 还有一种是查询缓冲 当然 查询缓冲是依托于二级缓冲 ok 什么是缓冲 在内存里开
  • 【全网最细PAT题解】【PAT乙】1044 火星数字(测试点2,测试点4详细解释)

    题目链接 1044 火星数字 题目描述 火星人是以 13 进制计数的 地球人的 0 被火星人称为 tret 地球人数字 1 到 12 的火星文分别为 jan feb mar apr may jun jly aug sep oct nov d
  • Bigdata1234.cn Java 课堂测试

    Java源文件中有一个公共类名称为Test 则该源文件名必须是 Test java Java中的基本数据类型共有8个 byte short int long float double char boolean Eclipse中内容补全的快捷
  • String的基本操作函数

    string类的构造函数 string const char s 用c字符串s初始化 string int n char c 用n个字符c初始化 此外 string类还支持默认构造函数和复制构造函数 如string s1 string s2
  • 错误解决:liquibase.exception.LockException

    今天发现个错误liquibase exception LockException 网上解决方法 url http forum liquibase org topic lock is not released if nocount is on
  • 全网最全C盘清理指南,无需安装清理软件,值得收藏

    最近电脑运行卡顿 打开一看 原来C盘爆红了 找了一个b站的清理教程 此篇来做一个总结 会讲哪些能删哪些不能删 以及原因 无需安装如360 腾讯电脑管家之类的清理软件 原视频链接 up主 小宇Boihttps www bilibili com
  • 决策树模型

    决策树模型是机器学习的各种算法模型中比较好理解的一种模型 它的基本原理是通过对一系列问题进行if else的推导 最终实现相关决策 下图所示为一个典型的决策树模型 员工离职预测模型的简单演示 该决策树首先判断员工满意度是否小于5 若答案为
  • TCL命令

    目录 list命令 concat命令 lindex命令 llength命令 linsert命令 lreplace命令 lrange命令 lappend命令 lsearch命令 lsort命令 split命令 join命令 list命令 li
  • JSP webshell免杀——JSP的基础

    唉 每次开启JSP都要好一会儿 话说我也不知道为啥 我的每次开启条件一次比一次苛刻 一开始必应就可以打开 再后来只能由谷歌打开 现在可好了得开着代理用谷歌才能进去 一个JSP页面可由5种元素组合而成 1 普通的HTML标记和JavaScri
  • 梳理半月有余,精心准备了17张知识思维导图,这次要讲清统计学

    想要学好数据分析 统计学是必学的基础课程 统计学看似简单 实则知识多而繁杂 对于初学小白来说更是不知所措 理不清知识架构体系 为了让大家对统计学有更加清晰地认识 我总结了17 张 统计学知识思维导图 今天分享给大家 图片上传后会自动压缩 如
  • Nuxt3打包部署到Linux(node+pm2详细安装运行步骤)

    小聊 最近写了一个项目 需要打包部署 过程还是比较繁琐的 因为需要先配置运行环境 准备采用 pm2 管理项目运行 需要在服务器安装 pm2 而安装 pm2 的话用 npm 命令最方便 所以还要下载 node 环境 那么 就让我们一步步的完成
  • Nmap扫描原理与用法

    Nmap扫描原理与用法 2012年6月16日 1 Nmap介绍 Nmap扫描原理与用法PDF 下载地址 Nmap是一款开源免费的网络发现 Network Discovery 和安全审计 Security Auditing 工具 软件名字Nm
  • ‘mvn‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件——解决方法(详解,亲测有效)

    错误原因 配置Maven环境变量出现问题 解决方法 以windows 10为例子 步骤一 此电脑 属性 高级系统设置 环境变量 系统变量 新建 变量名 M2 HOME 变量值 D install maven apache maven 3 5
  • jq和vue的区别

    1 从jquery到vue的转变是一个思想想的转变 就是将原有的直接操作dom的思想转变到操作数据上去 2 传统前端开发模式中是以jq为核心的 而vue是现在一个兴起的前端js库 是一个精简的MVVM 3 jQuery是使用选择器 选取DO
  • spring boot定时任务方式

    一 定时任务实现的几种方式 Timer jdk util自带的Timer类 可以调度一个java util TimerTask任务 只能设定任务按照某个频度执行 但不能按设定时间运行 ScheduledExecutorService jdk
  • 使用Python进行测试驱动开发

    作者 Jason Diamond 译者 吴海燕 原文发表日期 12 02 2004 翻译日期 2 17 2005 原文件位置 http www onlamp com pub a python 2004 12 02 tdd pyunit ht
  • 微信小程序使用npm引入三方包详解

    目录 1 前言 2 微信小程序npm环境搭建 2 1 创建package json文件 2 2 修改 project config json 2 3 修改project private config json配置 2 4 构建 npm 包
  • sharepoint 2010 列表数据分页控件介绍 pagination UserControl

    这里主要是介绍下最近开发的一个sharepoint列表或者文档库的分页控件 并且把它包装成一个可以支持自定义列表 Custom list 文档库 Document library 讨论板 Discussion 资源库 Assets libr
  • 创建vue项目-vue2&vue3

    1 安装node 网址 下载 Node js 中文网 可以下载最新版本 也可以点击下方按钮下载其他版本 安装时全部选择默认 点击下一步 完成之后打开cmd命令窗口 检查node js是否安装成功 再查看npm是否安装成功 2 安装vue脚手
  • Redis-事务与持久化

    目录 事务 事务命令 事务的实现 事务的开始 命令入队 事务队列 执行事务 WATCH命令 不监视的情况下 监视的情况下 事务的ACID特性 A 原子性 C 一致性 I 隔离性 D 持久性 持久化 RDB持久化 Redis DataBase