首页 > 数据库 >Redis持久化RDB和AOF原理解析、使用和优缺点对比

Redis持久化RDB和AOF原理解析、使用和优缺点对比

时间:2023-04-05 19:44:57浏览次数:50  
标签:AOF 文件 Redis RDB 进程 数据

前言

本文讲述 Redis 两种持久化方式 RDB 和 AOF 优缺点以及原理。

为何需要持久化?

Redis 是基于内存操作的,进程终止、服务器宕机后内存数据会丢失,但是在很多使用场景中我们希望数据不丢失,服务重启之后数据还能恢复到停机前的状态,特别是使用 Redis 做数据库的情况。

Redis 持久化就是在服务运行期间将数据写到磁盘上,进程重新启动的时候将磁盘上的数据加载到内存中,恢复到停机前的状态。Redis 有 RDB 和 AOF两种实现方式。

RDB、AOF 两种方式优劣

RDB 是意图在某一时刻保存一份完整的内存快照数据集到后缀为 .rdb的二进制文件中,文件中的内容是到那一刻为止内存中完整的数据状态,那一刻之后的操作跟它无关。

  • 优点:因为是数据快照,所以生成的文件内容紧凑占用磁盘空间小,重启恢复到内存速度也较快,持久化的频率一般也会配置得比较低,并且执行过程交给子进程,对服务性能影响小。
  • 缺点:因为是保存整个内存的数据,所以执行的整个过程会相对较长;因为间隔较长,会丢失较多的数据,在间隔期内服务进程终止的话上一次创建快照到终止那一刻对 Redis 数据的改动都会丢失。

AOF 则是在 .aof 文件中以追加写指令的方式实现的。

  • 优点:因为追加写指令执行的频率高、间隔短,所以间隔期内进程停止丢失的数据较少,数据比较完整。
  • 缺点:也是因为执行频率高,影响服务性能;写指令跟数据本身比占用空间较大,导致落到磁盘上的文件也很大,重启恢复的时间长。

RDB(Redis Database)

同/异步创建方式

RDB 有两种方式:通过 SAVE 指令同步执行,在明确创建过程中不对外提供服务或者明确会停机的时候使用;另一种是通执行 BGSAVE 指令,它会调用 fork() 函数创建子进程异步执行,默认、一般都是这种 。

fork() 和 copy-on-write

在触发保存 RDB的时候 Redis 会调用系统 fork() 函数创建出一个子进程将数据写到临时文件里,全部写完后再替换原来的 RDB 文件,文件最终都只有一份。子进程创建速度快,占用空间小,原因是用到了 Linux 系统写时拷贝技术(copy-on-write)。

写时拷贝技术(copy-on-write)如下图示:

【1】父进程调用系统 fork() 函数创建子进程,并复制一份父进程虚拟地址空间数据,其数据体积小,所以子进程创建速度快;

【2】虚拟地址保存的是物理空间的逻辑指针,物理空间则是真正保存数据的地方。父子进程指针一致,指向同一个物理内存实现了数据共享,子进程执行保存任务;

【3】主进程修改数据时,开辟新的物理内存写入数据,再修改指针变量的指向,父子进程互不干扰。
整个过程没有完整复制存储的数据,保存上 G 的数据也不必担心空间不足,虽然修改数据时占用了新的物理空间,但是占比很小。

在这里插入图片描述

配置

# 不保存 RDB
# save ""

# 下列是保存 RDB 的条件,可配置多个
# 经过 3600 秒,并且有 1 个以上 key 改变
save 3600 1
# 经过 300 秒 并且有 100 个以上 key 改变
save 300 100
# 经过 60 秒 并且有 10000 个以上 key 改变
save 60 10000

# 保存的文件名
dbfilename dump.rdb
# 保存的目录
dir /var/lib/redis/6379

AOF(Append Only File)

将所有写指令追加到一个缓冲区中,再按配置的策略由其他后台线程定期写到 AOF 文件中,宕机时缓冲区的数据会丢失。Redis 还会按配置定期对文件进行重写以减小文件的体积。

重写

重写同样运用了写时拷贝技术(copy-on-write)

在 4.0 版本之前重写就是对文件可以互相抵消的写指令进行简化,比如重复更新一个数据只需要保存最后一条指令,新增+删除则直接抵消。

Redis 执行 fork() ,子进程将 AOF 文件内容重写到临时文件。

对于新的写命令,父进程一边将它们累积到一个内存缓存中,一边将这些改动追加到现有 AOF 文件的末尾,这样即使在重写的中途发生停机,现有的 AOF 文件也还是安全的。

当子进程完成重写工作时,它给父进程发送一个信号,父进程在接收到信号之后,将内存缓存中的所有数据追加到新 AOF 文件的末尾。

最后 Redis 原子地用新文件替换旧文件,之后所有命令都会直接追加到新 AOF 文件的末尾。

在 4.0 之后版本 AOF 可以使用混合体,先生成 RDB 快照到 .aof 文件中,再追加写命令。

配置

# 开启 AOF
appendonly yes
# 文件名
appendfilename "appendonly.aof"

# 触发从缓存写到磁盘的策略
# 每条写指令触发
# appendfsync always
# 每秒触发
appendfsync everysec
# 让系统决定
# appendfsync no
# 用 RDB 混合方式,内容 "REDIS" 开头
aof-use-rdb-preamble yes


# Redis 记录每次重写时原文件大小,下次文件体积增长 100% 后触发重写
auto-aof-rewrite-percentage 100
# 文件大小达到 64 兆触发第一次重写
auto-aof-rewrite-min-size 64mb

管道与父子进程

  • 你可以通过 $$ 和 $BASHPID 都代表当前 bash 进程 ID,你可以通过 echo 将它输出。

在这里插入图片描述

  • 符号 | 可以用来创建管道,管道符左边命令的输出作为右边的命令的输入。如下图左边输出 123 管道右边 more 代表把接收的数据显示出来:

在这里插入图片描述

  • 并且管道两边的指令会创建两个新的进程来执行。如下图:

【1】我们先用两种方式输出了当前解释进程ID;

【2】尝试将管道左边创建的进程 ID 作为右边进程参数输出出来,执行了两次可以发现 ID 都不一样,并且不等于外层进程 ID 9441,验证确实创建了新进程;

【3】用这种方式却发现输出的进程 ID 和外层进程一样的。是因为 $$ 优先级比管道符号 | 高,先将外层进程 ID 替换到了 echo 语句中,管道再创建了新进程执行这条已经完整的语句 echo 9441,所以不是用的新进程 ID。

在这里插入图片描述

  • 常规情况下进程是数据隔离的。如下图:

【1】我们先创建了环境变量 num 赋值赋值为 1,并打印验证;

【2】/bin/bash 创建子进程,并打印进程 ID 对比进行验证;然后输出 num 显示空行代表没内容,验证进程间数据隔离。最后 exit 结束子进程。

在这里插入图片描述

  • 父进程可以让子进程看到数据,父子进程修改数据互不影响,如下图:

【1】使用 export 指令,然后在子进程成功打印出了父进程的 num;

【2】在子进程修改数据并打印,验证子进程数据修改成功;

【3】exit 结束子进程,在父进程打印 num,验证父子进程修改数据互不影响。

在这里插入图片描述

参考链接

Redis 中文网 持久化

标签:AOF,文件,Redis,RDB,进程,数据
From: https://www.cnblogs.com/shuiyao3/p/17290687.html

相关文章

  • Redis 在身份认证中的应用
    1.Redis在Session共享问题中的应用传统Session-Cookeis身份认证方法中,一个Session只保存在一台服务器上,适合域单体应用。随着项目规模的增加,项目的架构也不断向微服务分布式集群演进,传统的Session-Cookie方式在集群环境下就不能很好的工作了,这时就产生了Session共......
  • Redis 缓存机制
    1.Redis缓存缓存(cache),原始意义是指访问速度比一般随机存取存储器(RAM)快的一种高速存储器,通常它不像系统主存那样使用DRAM技术,而使用昂贵但较快速的SRAM技术。缓存的设置是所有现代计算机系统发挥高性能的重要因素之一。Redis因读写性能较高,它非常适合作为存贮数据......
  • 在Linux部署Redis主从和哨兵集群实现高可用
    前言本文主要讲述在Linux系统中配置和部署Redis主从集群和哨兵,实现高可用和自动故障迁移。准备工作参考Redis单机部署安装3个Redis服务作一主二从,本文准备了6380(主)、6381(从)和6382(从)。参考Redis单机部署安装3个Redis服务作哨兵集群,本文准备了26380......
  • 在Linux部署Redis Cluster集群
    前言本文讲述在Linux系统部署RedisCluster实现数据分片的具体步骤。请参考Redis单机部署下载编译。RedisCluster是什么?RedisCluster是官方提供的一种用数据分片来实现横向扩容的解决方案,由一个或多个Redis服务组成一个无主集群。对Key使用哈希算法将数据分散......
  • 在Linux部署Redis代理Predixy实现数据分片
    前言本文以predixy-1.0.5为例,讲述Redis代理Predixy安装过程。Predixy是一款高性能全特征Redis代理,支持Redis-sentinel和Redis-cluster。作者拿其它常用代理做了性能测评,Predixy在各个维度性能都是最优的,与其他代理的功能对比。我们可以通过取模、随机、一致性哈希......
  • 在Linux部署Redis代理Twemproxy实现数据分片
    前言本文主要讲述Redis代理Twemproxy安装过程。Twemproxy是推特开源用于Memcached和Redis的轻量级代理。这里以0.5.0版本为例。我们可以通过取模、随机、一致性哈希等算法将数据分散在多个Redis服务来实现水平扩展。但是客户端直连就需要跟每个Redis服务产生连接,......
  • Redis——(主从复制、哨兵模式、集群)的部署及搭建
    重点:主从复制:主从复制是高可用redis的基础,主从复制主要实现了数据的多机备份,以及对于读操作的负载均衡和简单的故障恢复。哨兵和集群都是在主从复制基础上实现高可用的。缺点:故障恢复无法自动化,写操作无法负载均衡,存储能力受到单机的限制。哨兵:在主从复制的基础上,哨兵......
  • 在Linux部署单机Redis完整过程
    前言本文以redis-6.2.5为例,讲述在Linux系统下单机Redis下载、编译、打包、安装为服务、启动和访问的整个过程。安装环境为LinuxCentOS64,本文用的7.5版本.下载编译目录在当前目录soft/redis下,最终服务可执行程序在/opt/soft/redis6中。准备工作#查看是否有文件下载......
  • Redis系列12:Redis 的事务机制
    Redis系列1:深刻理解高性能Redis的本质Redis系列2:数据持久化提高可用性Redis系列3:高可用之主从架构Redis系列4:高可用之Sentinel(哨兵模式)Redis系列5:深入分析Cluster集群模式追求性能极致:Redis6.0的多线程模型追求性能极致:客户端缓存带来的革命Redis系列8:Bitmap实现亿万级......
  • Redis 的 Java 客户端
    实际项目中,需要通过编程语言去访问并操作Redis。Redis官方提供了多种语言的客户端,具体可访问以下地址:https://redis.io/clientsJava语言访问Redis,常用的API包括:(1)Jedis:一个很小但很健全的redis的java客户端,通过Jedis可以像使用Redis命令行一样使用Redis;Jedis......