Redis事务与数据持久化方式

 更新时间:2025年01月10日 08:49:14   作者:夜夜流光相皎洁_小宁  
该文档主要介绍了Redis事务和持久化机制,事务通过将多个命令打包执行,而持久化则通过快照(RDB)和追加式文件(AOF)两种方式将内存数据保存到磁盘,以防止数据丢失

一、Redis 事务

1.1 事务本质

一组命令的集合

1.2 数据库事务与redis事务

1.2.1 数据库事务

数据库事务通过ACID(原子性、一致性、隔离性、持久性)来保证。

数据库中除查询操作以外,插入(Insert)、删除(Delete)和更新(Update)这三种操作都会对数据造成影响,因为事务处理能够保证一系列操作可以完全地执行或者完全不执行,因此在一个事务被提交以后,该事务中的任何一条SQL语句在被执行的时候,都会生成一条撤销日志(Undo Log)。

1.2.2 Redis事务

redis事务提供了一种“将多个命令打包, 然后一次性、按顺序地执行”的机制, 并且事务在执行的期间不会主动中断 —— 服务器在执行完事务中的所有命令之后, 才会继续处理其他客户端的其他命令。

Redis中一个事务从开始到执行会经历开始事务(muiti)命令入队执行事务(exec)三个阶段,事务中的命令在加入时都没有被执行,直到提交时才会开始执行(Exec)一次性完成。

1.2.2.1 两种错误不同处理方式

1)代码语法错误(编译时异常)

发生代码语法错误时,所有命令都不执行。

2)代码逻辑错误(运行时错误)

发生代码逻辑错误时,其他命令可以正常执行 (该点不保证事务的原子性)

为什么redis不支持回滚来保证原子性

1.2.2.2 这种做法的优点:

  • Redis 命令只会因为错误的语法而失败(并且这些问题不能在入队时发现),或是命令用在了错误类型的键上面:这也就是说,从实用性的角度来说,失败的命令是由编程错误造成的,而这些错误应该在开发的过程中被发现,而不应该出现在生产环境中。
  • 因为不需要对回滚进行支持,所以 Redis 的内部可以保持简单且快速。

鉴于没有任何机制能避免程序员自己造成的错误, 并且这类错误通常不会在生产环境中出现, 所以 Redis 选择了更简单、更快速的无回滚方式来处理事务。

1.3 事务监控

redis使用watch key监控指定数据,相当于加乐观锁

watch保证事务只能在所有被监视键都没有被修改的前提下执行, 如果这个前提不能满足的话,事务就不会被执行。

watch执行流程:

二、数据持久化

Redis是一种内存型数据库,一旦服务器进程退出,数据库的数据就会丢失,为了解决这个问题Redis供了两种持久化的方案,将内存中的数据保存到磁盘中,避免数据的丢失两种持久化方式:快照(RDB文件)追加式文件(AOF文件),下面分别为大家介绍两种方式的原理。

  • RDB持久化方式会在一个特定的间隔保存那个时间点的数据快照。
  • AOF持久化方式则会记录每一个服务器收到的写操作。在服务启动时,这些记录的操作会逐条执行从而重建出原来的数据。写操作命令记录的格式跟Redis协议一致,以追加的方式进行保存。
  • Redis的持久化是可以禁用的,就是说你可以让数据的生命周期只存在于服务器的运行时间里。
  • 两种方式的持久化是可以同时存在的,但是当Redis重启时,AOF文件会被优先用于重建数据。

2.1 RDB持久化

RDB持久化产生的文件是一个经过压缩的二进制文件,这个文件可以被保存到硬盘中,可以通过这个文件还原数据库的状态,它可以手动执行,也可以在redis.conf配置文件中配置,定时执行。

2.1.1 工作原理

在进行RDB时,redis的主进程不会做io操作,会fork一个子进程来完成该操作:

1)Redis 调用forks。同时拥有父进程和子进程。

2)子进程将数据集写入到一个临时 RDB 文件中。

3)当子进程完成对新 RDB 文件的写入时,Redis 用新 RDB 文件替换原来的 RDB 文件,并删除旧的 RDB 文件。

这种工作方式使得 Redis 可以从写时复制(copy-on-write)机制中获益(因为是使用子进程进行写操作,而父进程依然可以接收来自客户端的请求)

2.1.2 触发机制

在Redis中RDB持久化的触发分为两种:自己手动触发与自动触发。

2.1.2.1 手动触发

1)save

save命令是同步的命令,会占用主进程,会造成阻塞,阻塞所有客户端的请求

2)bgsave

bgsave是异步进行,进行持久化的时候,redis还可以将继续响应客户端请求

bgsave和save对比:

命令savebgsave
IO类型同步异步
阻塞是(阻塞发生在fock(),通常非常快)
复杂度O(n)O(n)
优点不会消耗额外的内存不阻塞客户端命令
缺点阻塞客户端命令需要fock子进程,消耗内存

2.1.2.2 自动触发

触发条件:

save自动触发配置,见下面配置,满足m秒内修改n次key,触发rdb

# 时间策略   save m n m秒内修改n次key,触发rdb
save 900 1
save 300 10
save 60 10000

# 文件名称
dbfilename dump.rdb

# 文件保存路径
dir /home/work/app/redis/data/

# 如果持久化出错,主进程是否停止写入
stop-writes-on-bgsave-error yes

# 是否压缩
rdbcompression yes

# 导入时是否检查
rdbchecksum yes

1)从节点全量复制时,主节点发送rdb文件给从节点完成复制操作,主节点会触发bgsave命令;

2)执行flushall命令,会触发rdb

3)退出redis,且没有开启aof时

2.1.3 RDB优缺点

2.1.3.1 优点:

1)RDB 的内容为二进制的数据,占用内存更小,更紧凑,更适合做为备份文件;

2)RDB 对灾难恢复非常有用,它是一个紧凑的文件,可以更快的传输到远程服务器进行 Redis 服务恢复;

3)RDB 可以更大程度的提高 Redis 的运行速度,因为每次持久化时 Redis 主进程都会 fork() 一个子进程,进行数据持久化到磁盘,Redis 主进程并不会执行磁盘 I/O 等操作;

4)与 AOF 格式的文件相比,RDB 文件可以更快的重启。

2.1.3.2 缺点:

1)因为 RDB 只能保存某个时间间隔的数据,如果中途 Redis 服务被意外终止了,则会丢失一段时间内的 Redis 数据。

2)RDB 需要经常 fork() 才能使用子进程将其持久化在磁盘上。如果数据集很大,fork() 可能很耗时,并且如果数据集很大且 CPU 性能不佳,则可能导致 Redis 停止为客户端服务几毫秒甚至一秒钟。

2.2 AOF持久化

以日志的形式来记录每个写的操作,将Redis执行过的所有指令记录下来(读操作不记录),只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,换言之,redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。

2.2.1 AOF配置项

# 默认不开启aof  而是使用rdb的方式
appendonly no

# 默认文件名
appendfilename "appendonly.aof"

# 每次修改都会sync 消耗性能
# appendfsync always
# 每秒执行一次 sync 可能会丢失这一秒的数据
appendfsync everysec
# 不执行 sync ,这时候操作系统自己同步数据,速度最快
# appendfsync no 

AOF的整个流程大体来看可以分为两步,一步是命令的实时写入(如果是appendfsync everysec 配置,会有1s损耗),第二步是对aof文件的重写。

2.2.2 AOF 重写机制

随着Redis的运行,AOF的日志会越来越长,如果实例宕机重启,那么重放整个AOF将会变得十分耗时,而在日志记录中,又有很多无意义的记录,比如我现在将一个数据 incr一千次,那么就不需要去记录这1000次修改,只需要记录最后的值即可。所以就需要进行 AOF 重写。

Redis 提供了bgrewriteaof指令用于对AOF日志进行重写,该指令运行时会开辟一个子进程对内存进行遍历,然后将其转换为一系列的 Redis 的操作指令,再序列化到一个日志文件中。完成后再替换原有的AOF文件,至此完成。

同样的也可以在redis.config中对重写机制的触发进行配置:

通过将no-appendfsync-on-rewrite设置为yes,开启重写机制;auto-aof-rewrite-percentage 100意为比上次从写后文件大小增长了100%再次触发重写;

auto-aof-rewrite-min-size 64mb意为当文件至少要达到64mb才会触发制动重写。

2.2.3 触发方式

在Redis中AOF持久化的触发也分为两种:自己手动触发与自动触发。

2.2.3.1 手动触发

bgrewriteaof

2.2.3.2 自动触发

就是根据配置规则来触发,当然自动触发的整体时间还跟Redis的定时任务频率有关系。

2.2.4 AOF的优缺点

2.2.4.1 优点

1)数据安全

aof 持久化可以配置 appendfsync 属性,有 always,每进行一次 命令操作就记录到 aof 文件中一次。

2)解决数据一致性问题。

通过 append 模式写文件,即使中途服务器宕机,可以通过 redis-check-aof 工具解决数据一致性问题。

3)AOF 机制的 rewrite 模式。

AOF 文件没被 rewrite 之前(文件过大时会对命令 进行合并重写),可以删除其中的某些命令(比如误操作的 flushall))

2.2.4.2 缺点

1)AOF 文件比 RDB 文件大,且恢复速度慢。

2)数据集大的时候,比 rdb 启动效率低。

2.3 rdb与aof对比

比较项RDBAOF
启动优先级
体积
恢复速度
数据安全性性丢数据根据策略决定

总结

RDB基于快照方式在一个特定的间隔保存那个时间点的数据,备份数据相对较小,恢复速度较块,但是可能会发生数据丢失;AOF持久化方式则会记录每一个服务器收到的写操作,备份文件体积较大,恢复速度较慢,但是这种方式制定一定的策略,不会丢失数据,相对来说数据安全性要比RDB高。

在真实的企业生产环境中,Redis数据备份策略,一般是同时开启RDB和AOF两种备份方式,尽可能提高企业安全性的同时,也可以针对某个时间点基于数据快照快速恢复数据。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 超强、超详细Redis数据库入门教程

    超强、超详细Redis数据库入门教程

    这篇文章主要介绍了超强、超详细Redis入门教程,本文详细介绍了Redis数据库各个方面的知识,需要的朋友可以参考下
    2014-10-10
  • Redis中序列化的两种实现

    Redis中序列化的两种实现

    本文主要介绍了Redis中序列化的两种实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-07-07
  • linux 常见的标识与Redis数据库详解

    linux 常见的标识与Redis数据库详解

    这篇文章主要介绍了linux 常见的标识与Redis数据库,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-10-10
  • Redis @type坑的解决

    Redis @type坑的解决

    新建一个对象存入redis中,对象中会出现一个字段@type,本文主要介绍了Redis @type坑的解决,具有一定的参考价值,感兴趣的可以了解一下
    2024-06-06
  • 利用Redis实现访问次数限流的方法详解

    利用Redis实现访问次数限流的方法详解

    这篇文章主要给大家介绍了关于如何利用Redis实现访问次数限流的相关资料,文中通过实例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2022-02-02
  • 通过redis的脚本lua如何实现抢红包功能

    通过redis的脚本lua如何实现抢红包功能

    这篇文章主要给大家介绍了关于通过redis的脚本lua如何实现抢红包功能的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2020-05-05
  • Redis主从实现读写分离

    Redis主从实现读写分离

    这篇文章主要为大家详细介绍了Redis主从实现读写分离的相关资料 ,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-10-10
  • Redis实现延迟任务的常见方案详解

    Redis实现延迟任务的常见方案详解

    延迟任务(Delayed Task)是指在未来的某个时间点,执行相应的任务,本文为大家整理了Redis实现延迟任务的几个常见方案,希望对大家有所帮助
    2024-04-04
  • CentOS系统中Redis数据库的安装配置指南

    CentOS系统中Redis数据库的安装配置指南

    Redis是一个基于主存存储的数据库,性能很强,这里我们就来看一下CentOS系统中Redis数据库的安装配置指南,包括将Redis作为系统服务运行的技巧等,需要的朋友可以参考下
    2016-06-06
  • 在Redis数据库中实现分布式速率限制的方法

    在Redis数据库中实现分布式速率限制的方法

    这篇文章主要介绍了在Redis数据库中实现分布式速率限制的方法,文中展示了一个用Python编写的应用示例,需要的朋友可以参考下
    2015-06-06

最新评论