【Redis系列笔记】持久化

本文涉及的产品
云原生多模数据库 Lindorm,多引擎 多规格 0-4节点
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
云数据库 MongoDB,通用型 2核4GB
简介: Redis的确是将数据存储在内存的,但是也会有相关的持久化机制将内存持久化备份到磁盘,以便于重启时数据能够重新恢复到内存中,避免数据丢失的风险。有三种持久化方式——RDB,AOF,混合持久化。RDB持久化是形成数据快照,把内存中的所有数据都记录到磁盘中,是全量持久化。AOF持久化是把Redis处理的每一个写命令都会记录在AOF文件,可以看做是命令日志文件,是增量化持久。混合持久化则结合两者。

2.1. 概述

Redis的确是将数据存储在内存的,但是也会有相关的持久化机制将内存持久化备份到磁盘,以便于重启时数据能够重新恢复到内存中,避免数据丢失的风险。

而Redis持久化机制由三种,在4.X版本之前Redis只支持AOF以及RDB两种形式持久化,但是因为AOF与RDB都存在各自的缺陷,所以在4.x版本之后Redis还提供一种新的持久化机制:混合型持久化

2.2. RDB

RDB全称Redis Database Backup file(Redis数据备份文件),也被叫做Redis数据快照。简单来说就是把内存中的所有数据都记录到磁盘中。当Redis实例故障重启后,从磁盘读取快照文件,恢复数据。快照文件称为RDB文件,默认是保存在当前运行目录。

2.2.1. 执行时机

  • save:主线程,用户主动或者关机
  • bgsave:子线程,触发机制

save

save命令会导致主进程执行RDB,这个过程中其它所有命令都会被阻塞。只有在数据迁移时可能用到。在生产环境切记不可使用。

bgsave

bgsave会使主进程fork 出一个子进程来异步进行 RDB 持久化。 需要注意的是不阻塞主进程指的是子进程中的操作不会阻塞主进程,但是 fork 这个动作本身是会阻塞主进程的,因为 fork 子进程的操作就是在主进程中完成的。

触发机制可以在redis.conf文件中找到,格式如下:

//900秒内,如果至少有1个key被修改,则执行bgsave,其他同理
save 900 1 
save 300 10  
save 60 10000 
//表示禁用RDB
save ""
//是否压缩 ,建议不开启,压缩也会消耗cpu,磁盘的话不值钱
rdbcompression yes
//导入时是否检查
rdbchecksum yes
//RDB文件名称
dbfilename dump.rdb  
//文件保存的路径目录
dir ./ 
//当备份进程出错时,主进程就停止接受新的写入操作
stop-writes-on-bgsave-error yes

2.2.2. 特点

  • 优点:使用单独子进程来进行持久化,主进程不会进行任何 IO 操作,保证了 Redis 的高性能;而且RDB文件存储的是压缩的二进制文件,适用于备份、全量复制,可用于灾难备份,同时RDB文件的加载速度远超于AOF文件。
  • 缺点:RDB是间隔一段时间进行持久化,如果持久化之间的时间内发生故障,会出现数据丢失。所以这种方式更适合数据要求不严谨的时候,因为RDB无法做到实时持久化,而且每次都要创建子进程,频繁创建成本过高;备份时占用内存,因为Redis 在备份时会独立创建一个子进程,将数据写入到一个临时文件(需要的内存是原本的两倍);还有一点,RDB文件保存的二进制文件存在新老版本不兼容的问题。

2.2.3. 原理

bgsave开始时会fork主进程得到子进程,子进程共享主进程的内存数据。完成fork后读取内存数据并写入 RDB 文件。

fork采用的是copy-on-write技术:

  • 当主进程执行读操作时,访问共享内存;
  • 当主进程执行写操作时,则会拷贝一份数据,执行写操作。

主进程与子进程共享的是?

主进程和子进程共享页表,共享的是映射关系

为什么主进程和子进程是不同进程,不会出现端口冲突?

主进程和子进程共享端口

为什么要使用copy-on-write?

子进程在执行 RDB 时,若父进程修改了内存数据,则会导致子进程读取的内存数据一起修改了,这样不合理。可是为什么不合理呢?最后保存在 RDB 中的数据有一部分是最新的,应该更不会有问题才对呀?

这跟java的并发问题是一样的,子进程读的值跟期望值不一致,也属于脏读;另外混合持久化会结合RDB和AOF,在最终数据合并会出现数据不一致。所以务必保证子进程的内存数据和 fork 时内存数据一致。


举例分析:

子进程开始进行 RDB,此时没有 "xxx" 这个 key
主进程收到命令 incr("xxx"), 此时 xxx 对应的值是 1(同时AOF命令保存)
子进程保存 RDB 文件时也保存了 xxx ,文件内存在key=xxx, value=1
最终数据合并,最终DB中出现key=xxx, value=2

2.3. AOF

AOF全称为Append Only File(追加文件)。Redis处理的每一个写命令都会记录在AOF文件,可以看做是命令日志文件。

在发生故障后可以做到不丢数据或丢失较少的数据,是一种增量化持久方式,也可以看做对RDB这种全量化持久方式的一种补充。

2.3.1. 执行时机

一般记录日志可能都是在正式操作之前先记录日志,不过 AOF 是在执行命令之后才记录的日志,这样做有优点也有缺点。

  • 优点是记录日志时不用检查命令是否正确,因为如果命令可以正确执行,那命令一定是正确的。
  • 缺点是会出现有可能命令执行成功,但是日志记录失败。AOF 日志虽然没有阻塞当前命令,但是可能阻塞后续命令,因为 AOF 日志也是在主线程写入 AOF缓冲区的 这两个缺点都和 AOF 日志刷盘时机有关

AOF默认是关闭的,需要修改redis.conf配置文件来开启AOF:

# 是否开启AOF功能,默认是no
appendonly yes
# AOF文件的名称
appendfilename "appendonly.aof"
# 表示每执行一次写命令,立即记录到AOF文件
appendfsync always 
# 追加同步策略
# 写命令执行完先放入AOF缓冲区,然后表示每隔1秒将缓冲区数据写到AOF文件,是默认方案
appendfsync everysec 
# 写命令执行完先放入AOF缓冲区,由操作系统决定何时将缓冲区内容写回磁盘
appendfsync no

appendonly.aof如下

root@VM-4-6-debian:/var/lib/docker/volumes/redis-data/_data# cat appendonly.aof 
 *2
 $6
 SELECT
 $1
 0
 *3
 $3
 set
 $4
 num1
 $1
 1
 *3
 $3
 set
 $4
 num2
 $1
 2
 
 
//选择redis数据库,默认存在16个
select 0
//set 值
set num1 1
set num2 2


AOF策略

配置项

刷盘时机

优点

缺点

Always

同步刷盘

可靠性高,几乎不丢数据

性能影响大

everysec

每秒刷盘

性能适中

最多丢失1秒数据

no

操作系统控制

性能最好

可靠性较差,可能丢失大量数据

2.3.2. 特点

  • 优点:根据不同的fsync策略可以保证数据丢失风险降到最低,数据能够保证是最新的,fsync是后台线程在处理,所以对于处理客户端请求的线程并不影响。
  • 缺点:文件体积由于保存的是所有命令会比RDB大上很多,而且数据恢复时也需要重新执行指令,在重启时恢复数据的时间往往会慢很多。虽然fsync并不是共用处理客户端请求线程的资源来处理的,但是这两个线程还是在共享同一台机器的资源,所以在高并发场景下也会一定受到影响。

2.3.3. 重写机制

因为是记录命令,AOF文件会比RDB文件大的多。而且AOF会记录对同一个key的多次写操作,但只有最后一次写操作才有意义。通过执行bgrewriteaof命令,可以让AOF文件执行重写功能,用最少的命令达到相同效果。

Redis也会在触发阈值时自动去重写AOF文件。阈值也可以在redis.conf中配置:

# AOF文件比上次文件 增长超过多少百分比则触发重写
auto-aof-rewrite-percentage 100
# AOF文件体积最小多大以上才触发重写 
auto-aof-rewrite-min-size 64mb

2.3.4. 重写流程

  • 主进程 fork 子进程,此时子进程拥有 Redis 内存快照
  • 子进程扫描内存中的全部键值对,生成 Rewrite 临时文件
  • 在此期间主进程将 AOF 日志同时写入 AOF 缓冲区和 Rewrite 缓冲区,并且 AOF 缓冲区依然会正常刷盘
  • 子进程完成 Rewrite 操作后,主进程会将 Rewrite 缓冲区数据写入临时文件,然后将临时文件重命名,替换原来的 AOF 文件
  • 后续的 AOF 日志写入到这个 Rewrite 之后的 AOF 文件中

2.4. 两者对比

项目

RDB

AOF

数据完整性

不完整,两次备份之间会丢失

相对完整,取决于刷盘策略

文件大小

会有压缩,文件体积小

记录命令,文件体积很大

宕机恢复速度

很快

较慢

数据恢复优先级

低,因为数据完整性不如AOF

高,因为数据完整性更高

系统资源占用

高,大量CPU和内存消耗

低,主要是磁盘I/O资源,但AOF重写时会占用大量CPU和内存资源

使用场景

可以容忍数分钟的数据丢失,追求更快的启动速度

对数据安全性要求较高常见

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
15天前
|
NoSQL Redis 数据库
一文讲透彻Redis 持久化
一文讲透彻Redis 持久化
37 0
|
15天前
|
存储 监控 负载均衡
保证Redis的高可用性是一个涉及多个层面的任务,主要包括数据持久化、复制与故障转移、集群化部署等方面
【5月更文挑战第15天】保证Redis高可用性涉及数据持久化、复制与故障转移、集群化及优化策略。RDB和AOF是数据持久化方法,哨兵模式确保故障自动恢复。Redis Cluster实现分布式部署,提高负载均衡和容错性。其他措施包括身份认证、多线程、数据压缩和监控报警,以增强安全性和稳定性。通过综合配置与监控,可确保Redis服务的高效、可靠运行。
187 2
|
15天前
|
NoSQL 安全 Unix
Redis源码、面试指南(4)单机数据库、持久化、通知与订阅(中)
Redis源码、面试指南(4)单机数据库、持久化、通知与订阅
23 0
|
15天前
|
NoSQL Java 关系型数据库
【Redis系列笔记】分布式锁
分布式锁:满足分布式系统或集群模式下多进程可见并且互斥的锁。 分布式锁的核心思想就是让大家都使用同一把锁,只要大家使用的是同一把锁,那么我们就能锁住线程,不让线程进行,让程序串行执行,这就是分布式锁的核心思路
158 2
|
1天前
|
存储 消息中间件 缓存
Redis - 笔记
Redis是开源的内存数据结构存储系统,兼备数据库、缓存和消息中间件功能。它支持字符串、哈希、列表、集合、有序集合等数据结构,以及地理空间、基数统计和位图等特殊类型。Redis具备复制、LUA脚本、LRU事件、事务、持久化、哨兵和集群等高级特性,以实现高可用性。应用场景包括计数器、存储用户信息、消息队列、共同关注等。字符串最大容量为512M。
|
2天前
|
存储 NoSQL 程序员
Redis(持久化 -- RDB & AOF)
Redis(持久化 -- RDB & AOF)
17 2
|
14天前
|
NoSQL 算法 Java
【redis源码学习】持久化机制,java程序员面试算法宝典pdf
【redis源码学习】持久化机制,java程序员面试算法宝典pdf
|
15天前
|
存储 NoSQL 关系型数据库
【Redis】Redis的特性和应用场景 · 数据类型 · 持久化 · 数据淘汰 · 事务 · 多机部署
【Redis】Redis的特性和应用场景 · 数据类型 · 持久化 · 数据淘汰 · 事务 · 多机部署
29 0
|
15天前
|
存储 NoSQL 调度
Redis源码、面试指南(4)单机数据库、持久化、通知与订阅(下)
Redis源码、面试指南(4)单机数据库、持久化、通知与订阅
18 0
|
15天前
|
存储 NoSQL API
Redis源码、面试指南(4)单机数据库、持久化、通知与订阅(上)
Redis源码、面试指南(4)单机数据库、持久化、通知与订阅
26 1

相关产品

  • 云数据库 Redis 版