Redis 持久化
1. Redis 持久化的取舍和选择
持久化的作用
什么是持久化
- redis所有数据是保存在内存中的,对数据的更新将异步的保存到磁盘上。
持久化的实现方式
- 快照方式
- MySQL Dump
- Redis RDB
- 写日志方式
- MySQL Binlog
- Hbase Hlog
- Redis AOF
2. RDB 持久化 方式
什么是RDB?
触发机制——主要三种方式
1. save(同步)生成RDB文件
2. bgsave(异步)生成RDB文件
3. 自动生成RDB文件
通过修改配置文件,控制自动生成RDB文件
缺点
- RDB 生成频率太高
- 不容易控制写入量
配置
save 900 1
save 300 10
save 60 10000
dbfilename dump.rdb # 生成RDB文件名
dir ./ # 生成RDB文件、日志文件、AOF文件的存储路径
stop-writes-on-bgsave-err yes # bgsave 发生错误,将停止写入
rdbcompression yes # RDB 文件是否压缩 默认yes
rdbchecksum yes # 是否检查 RDB 文件校验和 默认yes
最佳配置
触发机制——不容忽略的方式
- 全量复制(主从复制会触发生成RDB文件)
- debug reload (debug 级别重启 会触发生成RDB文件)
- shutdown (关闭 会触发生成RDB文件)
试验
- 试验 save 是否会阻塞
- 试验 bgsave fork 过程
- 自动配置的 save 是否真的有效
- RDB 文件长什么样子
配置启动试验redis
cd redis
# redis 目录的创建 参照redis 安装部分 https://www.cnblogs.com/guohewei/p/16246771.html#_label0_2mkdir config
# 存放配置文件mkdir data
# 存放RDB 文件cp redis.conf config/
# 复制默认配置文件cat redis.conf | grep -v "#" | grep -v "^$" > redis-6382.conf
# 去掉注释和空格
- 修改配置文件
[root@nezha-api config]# vi redis-6382.conf port 6379 daemonize yes pidfile /var/run/redis_6379.pid logfile 6379.log # save 3600 1 # save 300 100 # save 60 10000 stop-writes-on-bgsave-error yes rdbcompression yes rdbchecksum yes dbfilename dump-6379.rdb dir /root/Redis/redis/data
redis-server redis-6379.conf
# 启动redis
验证用例
首先插入大量数据 (use memory 大于 500MB)
- 试验 save 是否会阻塞
- 打开两个 redis-cli, 其中一个执行 save 后,另一个立即执行 'get hello', 查看执行时间,是否阻塞
- 试验 bgsave fork 过程
- 打开两个 redis-cli, 其中一个执行 bgsave 后,另一个立即执行 'get hello', 查看执行时间,是否阻塞
- 通过命令查看redis 进程
ps aux | grep redis- | grep -v "redis-cli"|grep -v "grep"
查看是否有 fork 进程 - 查执行 bgsave 后,/root/Redis/redis/data 目录中是否有临时文件生成,等一会临时文件消失,dump-6379.rdb 文件被更新
- 自动配置的 save 是否真的有效
- 修改配置文件
[root@nezha-api config]# vi redis-6382.conf port 6379 daemonize yes pidfile /var/run/redis_6379.pid logfile "6379.log" # save 3600 1 # save 300 100 save 60 5 # 60 秒 5条改变记录,自动执行 bgsave stop-writes-on-bgsave-error yes rdbcompression yes rdbchecksum yes dbfilename dump-6379.rdb dir /root/Redis/redis/data
- 重启redis
redis-cli shutdown && redis-server redis-6379.conf
- 执行6次修改命令,查看rbd.文件生成、修改时间 ,查看日志文件是否有记录
14801:M 12 May 2022 16:42:39.099 * 5 changes in 60 seconds. Saving... 14801:M 12 May 2022 16:42:39.100 * Background saving started by pid 15013 15013:C 12 May 2022 16:42:39.103 * DB saved on disk 15013:C 12 May 2022 16:42:39.103 * RDB: 0 MB of memory used by copy-on-write 14801:M 12 May 2022 16:42:39.201 * Background saving terminated with success
- 修改配置文件
总结
- RDB 是 Redis 内存到硬盘的快照,用于持久化
- save 通常会阻塞 Redis
- bgsave 不会阻塞 Redis, 但会fork 新进程
- save 自动配置满足任一就会被执行
- 有些触发 save 机制不容忽视
3. AOF 持久化 方式
RDB 现存问题
-
耗时、耗性能
-
不可控、丢失数据
什么是AOF
-
AOF原理-创建
-
AOF原理-恢复
AOF 三种策略
1. always
2. everysec
3. no
always everysec no 对比
通常使用 everysec 模式
AOF 重写
AOF 重新作用
- 减少硬盘占用量
- 加速恢复速度
AOF 重写实现方式
-
bgrewriteaof
命令 -
AOF 重写配置
auto-aof-rewrite-min-size
: AOF 文件重写需要的尺寸就是当 AOF 文件达到多大的时候进行重写
auto-aof-rewrite-percentage
: AOF 文件增长率就是当执行一次重写后,下一次达到多大进行重写(比如第一次达到100M重写,设置为 100%,则第二次达到200M再次重写)
-
AOF 统计
aof_current_size
: AOF 当前尺寸(单位:字节)aof_base_size
: AOF 上次启动和重写的尺寸(单位:字节)
-
重写自动触发时机
(1) aof_current_size > auto-aof-rewrite-min-size (触发重写)
(2) (aof_current_size - aof_base_size) / aof_base_size > auto-aof-rewrite-percentage (触发重写)
-
AOF 重写流程
AOF 配置
appendonly yes # 打开 AOF 功能
appendfilename apppendonly-6379.aof # AOF 文件名
appendfsync everysec # AOF 策略
dir /bigdiskpath # 存储生成RDB文件、日志文件、AOF文件的路径
no-appendfsync-on-rewrite yes # AOF 重写的时候,是否做正常的 append 操作
auto-aof-rewrite-min-size 64mb # 就是当 AOF 文件达到64mb的时候进行重写
auto-aof-rewrite-percentage 100 # AOF 增长率大于 100% 重写
aof-load-truncated yes # 重启加载 AOF 时,是否忽略由于AOF不完整,格式等错误 (yes 忽略)
试验
- AOF 生成
- AOF 长什么样子
[root@nezha-api data]# cat appendonly-6379.aof REDIS0009� redis-ver6.2.7� �edis-bits�@�ctime���|bused-mem��W aof-preamble���counter�worldbigmy_listabcd�� s�<*2 $6 SELECT $1 0 *3 $3 set $4 hehe $2 go
- AOF 配置
# 基本配置 port 6379 daemonize yes pidfile /var/run/redis_6379.pid logfile "6379.log" dir /root/Redis/redis/data # AOF 配置 appendonly yes # 打开 AOF 功能 appendfilename apppendonly-6379.aof # AOF 文件名 appendfsync everysec # AOF 策略 # AOF 重写配置 no-appendfsync-on-rewrite yes # AOF 重写的时候,是否做正常的 append 操作 auto-aof-rewrite-min-size 64mb # 就是当 AOF 文件达到64mb的时候进行重写 auto-aof-rewrite-percentage 100 # AOF 增长率大于 100% 重写 # AOF 重载配置 aof-load-truncated yes # 重启加载 AOF 时,是否忽略由于AOF不完整,格式等错误 (yes 忽略)
4. RDB 和 AOF 的抉择
(1) RDB 和 AOF 的比较
(2) RDB 最佳策略
- "关" 实际是关不了的(参见上文:"有些触发 save 机制不容忽视")
- 集中管理 (定期 按天、按星期 等等)
- 主从,从节点开 RDB
(3) AOF 最佳策略
- "开": 缓存和存储
- 建议开启
- 如果将redis单纯当做缓存使用,可以考虑关闭
- AOF重新集中管理
- 单机多部署的情况下,如果 AOF 集中发生,可能都在机器内存爆满
- 使用 everysec 策略
(4) 最佳策略
- 小分片 (使用 maxmemory 对redis 进行规划,maxmemory=4GB)
- 存储和缓存特性决定
- 监控(硬盘、内存、负载、网络)
- 保证足够的内存
开发运维常见问题
1. fork 操作
- fork 操作是同步操作,大多数情况下速度是非常快的 (只是做内存页的拷贝,不是完全内存的拷贝)
- 与内存量息息相关:内存越大耗时越长(与机器类型有关系)
info Persistence
查看latest_fork_usec127.0.0.1:6379> info Persistence # 查看持久化信息 # Persistence loading:0 current_cow_size:0 current_cow_size_age:0 current_fork_perc:0.00 current_save_keys_processed:0 current_save_keys_total:0 rdb_changes_since_last_save:0 rdb_bgsave_in_progress:0 rdb_last_save_time:1652358920 rdb_last_bgsave_status:ok rdb_last_bgsave_time_sec:0 rdb_current_bgsave_time_sec:-1 rdb_last_cow_size:286720 aof_enabled:1 aof_rewrite_in_progress:0 aof_rewrite_scheduled:0 aof_last_rewrite_time_sec:0 aof_current_rewrite_time_sec:-1 aof_last_bgrewrite_status:ok aof_last_write_status:ok aof_last_cow_size:323584 module_fork_in_progress:0 module_fork_last_cow_size:0 aof_current_size:207 aof_base_size:153 aof_pending_rewrite:0 aof_buffer_length:0 aof_rewrite_buffer_length:0 aof_pending_bio_fsync:0 aof_delayed_fsync:0
- 改善 fork
- 优先使用物理机或者高效支持fork操作的虚拟化技术
- 控制 Redis 实例最大可用内存:maxmemory
- 合理配置Linux内存分配策略:vm.overcommit_memory=1 (默认是0 当发现没有足够内存分配,就不去分配) 这样会阻塞 fork, 所有设置为 1
- 降低 fork 频率:如放宽 AOF 重写自动触发时机,不必要的全量复制
2. 子进程开销和优化
-
CPU
- 开销: RDB 和 AOF 文件生成,属于CPU密集型
- 优化: 不做 CPU 绑定,不和 CPU 密集型部署
-
内存
- 开销: fork 内存开销,copy-on-write
- 优化: echo never > /sys/kernel/mm/transparent_hugepage/enabled (关闭 可以优化内存,redis 用不着)
-
硬盘
- 开销: AOF 和 RDB 文件写入,可以结合 iostat iotop分析
- 优化:
- 不要和高硬盘负载部署在一起:存储服务,消息队列
- 增加配置
no-appendfsync-on-rewrite yes
: AOF 重写的时候,是否做正常的 append 操作 - 根据写入量决定磁盘类型:例如ssd
- 单机多部署持久化文件目录可以考虑分盘
3. AOF 追加阻塞
AOF 追加阻塞问题定位
-
日志定位
-
info Persistence
查看latest_fork_usec127.0.0.1:6379> info Persistence # 查看持久化信息 # Persistence aof_delayed_fsync:100 # 阻塞会加1,是历史累计值,无法判断那一段事件阻塞
-
通过硬盘观察