Redis-持久化

Redis持久化

RDB快照(snapshot)

Redis 的内存数据库快照默认保存在 dump.rdb 二进制文件中。

redis.conf配置文件描述如下:

md-end-block 复制代码
# Save the DB to disk.
#
# save <seconds> <changes> [<seconds> <changes> ...]
#
# Redis will save the DB if the given number of seconds elapsed and it
# surpassed the given number of write operations against the DB.
#
# Snapshotting can be completely disabled with a single empty string argument
# as in following example:
#
# save ""
#
# Unless specified otherwise, by default Redis will save the DB:
#   * After 3600 seconds (an hour) if at least 1 change was performed
#   * After 300 seconds (5 minutes) if at least 100 changes were performed
#   * After 60 seconds if at least 10000 changes were performed
#
# You can set these explicitly by uncommenting the following line.
#
# save 3600 1 300 100 60 10000

生成RDB快照命令:savebgsave(redis客户端执行命令,每次执行生成新的rdb文件,覆盖原有的)

bgsave的写时复制(COW)机制

Redis 借助操作系统提供的写时复制技术(Copy-On-Write, COW),在生成快照的同时,依然可以正常处理写命令。bgsave 子进程是由主线程 fork 生成的,可以共享主线程的所有内存数据。bgsave 子进程运行后,开始读取主线程的内存数据,并把它们写入 RDB 文件。

save与bgsave对比:

命令 save bgsave
IO类型 同步 异步
是否阻塞redis其它命令 否(在生成子进程调用fork函数时会有短暂阻塞)
复杂度 O(n) O(n)
优点 不会消耗额外内存 不阻塞客户端命令
缺点 阻塞客户端命令 需要fork子进程,消耗内存

配置自动生成rdb文件后台使用的是bgsave方式

AOF(append-only file)

快照功能并不是非常耐久(durable): 如果 Redis 因为某些原因而造成故障停机, 那么服务器将丢失最近写入、且仍未保存到快照中的那些数据

从 1.1 版本开始, Redis 增加了一种完全耐久的持久化方式: AOF 持久化,将修改的每一条指令记录进文件appendonly.aof中(先写入os cache,每隔一段时间fsync到磁盘)

aof文件示例:

md-end-block 复制代码
执行set a aacv 和 expire a 1000 两条命令:
*3
$3
set
$1
a
$4
aacv
*3
$9
PEXPIREAT
$1
a
$13
1700653658573

执行set b ccc ex 2000 命令
*5
$3
SET
$1
b
$3
ccc
$4
PXAT
$13
1700654874514

这是一种resp协议格式数据,星号后面的数字代表命令有多少个参数,$号后面的数字代表这个参数有几个字符。

注意 :如果执行带过期时间的set命令,aof文件里记录的是并不是执行的原始命令,而是记录key过期的时间戳

redis.conf文件相关配置:(开启AOF 和 配置fsync刷盘频率)

md-end-block 复制代码
# By default Redis asynchronously dumps the dataset on disk. This mode is
# good enough in many applications, but an issue with the Redis process or
# a power outage may result into a few minutes of writes lost (depending on
# the configured save points).
#
# The Append Only File is an alternative persistence mode that provides
# much better durability. For instance using the default data fsync policy
# (see later in the config file) Redis can lose just one second of writes in a
# dramatic event like a server power outage, or a single write if something
# wrong with the Redis process itself happens, but the operating system is
# still running correctly.
#
# AOF and RDB persistence can be enabled at the same time without problems.
# If the AOF is enabled on startup Redis will load the AOF, that is the file
# with the better durability guarantees.
#
# Please check https://redis.io/topics/persistence for more information.

appendonly no	// 修改为yes开启,修改后重启生效

# The fsync() call tells the Operating System to actually write data on disk
# instead of waiting for more data in the output buffer. Some OS will really flush
# data on disk, some other OS will just try to do it ASAP.
#
# Redis supports three different modes:
#
# no: don't fsync, just let the OS flush the data when it wants. Faster.
# always: fsync after every write to the append only log. Slow, Safest.
# everysec: fsync only one time every second. Compromise.
#
# The default is "everysec", as that's usually the right compromise between
# speed and data safety. It's up to you to understand if you can relax this to
# "no" that will let the operating system flush the output buffer when
# it wants, for better performances (but if you can live with the idea of
# some data loss consider the default persistence mode that's snapshotting),
# or on the contrary, use "always" that's very slow but a bit safer than
# everysec.
#
# More details please check the following article:
# http://antirez.com/post/redis-persistence-demystified.html
#
# If unsure, use "everysec".

# appendfsync always 	// 每次有新命令追加到 AOF 文件时就执行一次 fsync ,非常慢,也非常安全
appendfsync everysec 	// 每秒 fsync 一次,足够快,并且在故障时只会丢失 1 秒钟的数据。默认这种
# appendfsync no		// 从不 fsync ,将数据交给操作系统来处理。更快,也更不安全的选择
AOF重写

AOF文件里可能有太多没用指令,所以AOF会定期根据内存的最新数据生成aof文件

配置AOF自动重写频率:

md-end-block 复制代码
# Automatic rewrite of the append only file.
# Redis is able to automatically rewrite the log file implicitly calling
# BGREWRITEAOF when the AOF log size grows by the specified percentage.
#
# This is how it works: Redis remembers the size of the AOF file after the
# latest rewrite (if no rewrite has happened since the restart, the size of
# the AOF at startup is used).
#
# This base size is compared to the current size. If the current size is
# bigger than the specified percentage, the rewrite is triggered. Also
# you need to specify a minimal size for the AOF file to be rewritten, this
# is useful to avoid rewriting the AOF file even if the percentage increase
# is reached but it is still pretty small.
#
# Specify a percentage of zero in order to disable the automatic AOF
# rewrite feature.

auto-aof-rewrite-percentage 100	// aof文件自上一次重写后文件大小增长了100%则再次触发重写
auto-aof-rewrite-min-size 64mb	// aof文件至少要达到64M才会自动重写,文件太小恢复速度本来就很快,重写的意义不大

AOF重写命令:,进入redis客户端执行命令bgrewriteaof重写AOF

注意: AOF重写redis会fork出一个子进程去做(与bgsave命令类似),不会对redis正常命令处理有太多影响

RDB 和 AOF比较:
命令 RDB AOF
启动优先级
体积
恢复速度
数据安全性 容易丢数据 根据策略决定

生产环境可以都启用,redis启动时如果既有rdb文件又有aof文件则优先选择aof文件恢复数据,因为aof一般来说数据更全一点

Redis 4.0 混合持久化

重启 Redis 时,我们很少使用 RDB来恢复内存状态,因为会丢失大量数据。我们通常使用 AOF 日志重放,但是重放 AOF 日志性能相对 RDB来说要慢很多,这样在 Redis 实例很大的情况下,启动需要花费很长的时间。 Redis 4.0 为了解决这个问题,带来了一个新的持久化选项------混合持久化。

md-end-block 复制代码
# Redis can create append-only base files in either RDB or AOF formats. Using
# the RDB format is always faster and more efficient, and disabling it is only
# supported for backward compatibility purposes.
aof-use-rdb-preamble yes	// 开启混合持久化

如果开启了混合持久化,AOF在重写时 ,不再是单纯将内存数据转换为RESP命令写入AOF文件,而是将重写这一刻之前 的内存做RDB快照处理,并且将RDB快照内容和增量的AOF修改内存数据的命令存在一起,都写入新的AOF文件,新的文件一开始不叫appendonly.aof,等到重写完新的AOF文件才会进行改名,覆盖原有的AOF文件,完成新旧两个AOF文件的替换。

于是在 Redis 重启的时候,可以先加载 RDB 的内容,然后再重放增量 AOF 日志就可以完全替代之前的AOF 全量文件重放,因此重启效率大幅得到提升。

Redis数据备份策略:

1、写crontab定时调度脚本,每小时都copy一份rdb或aof的备份到一个目录中去,仅仅保留最近48小时的备份

2、每天都保留一份当日的数据备份到一个目录中去,可以保留最近1个月的备份

3、每次copy备份的时候,都把太旧的备份给删了

4、每天晚上将当前机器上的备份复制一份到其他机器上,以防机器损坏

Redis主从架构

redis主从架构搭建,配置从节点步骤:

md-end-block 复制代码
1、复制一份redis.conf文件
    
2、将相关配置修改为如下值:
port 6380
pidfile /var/run/redis_6380.pid # 把pid进程号写入pidfile配置的文件
logfile "6380.log"
dir ./data/6380 # 指定数据存放目录,目录必须存在 需要提前创建
    
# bind 127.0.0.1 # 这行注释掉

3、配置主从复制
replicaof 192.168.0.60 6379 # 从本机6379的redis实例复制数据,Redis 5.0之前使用slaveof
replica‐read‐only yes # 配置从节点只读

4、启动从节点
redis‐server redis.conf
    
5、连接从节点
redis‐cli ‐p 6380
    
6、测试在6379实例上写数据,6380实例是否能及时同步新修改数据
Redis主从工作原理

如果你为master配置了一个slave,不管这个slave是否是第一次连接上Master,它都会发送一个PSYNC命令给master请求复制数据

master收到PSYNC命令后,会在后台进行数据持久化通过bgsave生成最新的rdb快照文件,持久化期间,master会继续接收客户端的请求,它会把这些可能修改数据集的请求缓存在内存中。当持久化进行完毕以后,master会把这份rdb文件数据集发送给slave,slave会把接收到的数据进行持久化生成rdb,然后再加载到内存中。然后,master再将之前缓存在内存中的命令发送给slave。

当master与slave之间的连接由于某些原因而断开时,slave能够自动重连Master,如果master收到了多个slave并发连接请求,它只会进行一次持久化,而不是一个连接一次,然后再把这一份持久化的数据发送给多个并发连接的slave。

主从复制(全量复制)

数据部分复制

当master和slave断开重连后,一般都会对整份数据进行复制。但从redis2.8版本开始,redis改用可以支持部分数据复制的命令PSYNC去master同步数据,slave与master能够在网络连接断开重连后只进行部分数据复制(断点续传)。

master会在其内存中创建一个复制数据用的缓存队列,缓存最近一段时间的数据,master和它所有的slave都维护了复制的数据下标offset和master的进程id,因此,当网络连接断开后,slave会请求master继续进行未完成的复制,从所记录的数据下标开始。如果master进程id变化了,或者从节点数据下标offset太旧,已经不在master的缓存队列里了,那么将会进行一次全量数据的复制。

主从复制(部分复制,断点续传)

如果有很多从节点,为了缓解主从复制风暴(多个从节点同时复制主节点导致主节点压力过大),可以采用多级主从架构,让部分从节点与从节点(与主节点同步)同步数据

相关推荐
计算机学姐1 分钟前
基于SpringBoot+Vue的在线投票系统
java·vue.js·spring boot·后端·学习·intellij-idea·mybatis
一休哥助手16 分钟前
Redis 五种数据类型及底层数据结构详解
数据结构·数据库·redis
救救孩子把17 分钟前
深入理解 Java 对象的内存布局
java
落落落sss20 分钟前
MybatisPlus
android·java·开发语言·spring·tomcat·rabbitmq·mybatis
万物皆字节25 分钟前
maven指定模块快速打包idea插件Quick Maven Package
java
夜雨翦春韭32 分钟前
【代码随想录Day30】贪心算法Part04
java·数据结构·算法·leetcode·贪心算法
我行我素,向往自由39 分钟前
速成java记录(上)
java·速成
一直学习永不止步44 分钟前
LeetCode题练习与总结:H 指数--274
java·数据结构·算法·leetcode·数组·排序·计数排序
邵泽明1 小时前
面试知识储备-多线程
java·面试·职场和发展
盒马盒马1 小时前
Redis:zset类型
数据库·redis