将数据生成快照保存在磁盘
bgsave:fork操作创建子进程,阻塞时间短
触发方式:
save 900 1 表示每900秒有一次修改就自动bgsave
3. 从节点执行全量复制时,主节点自动bgsave生成RDB文件发送给从节点
4. 执行debug reload时也会触发save操作
5. 默认情况下,执行shutdown时,如果没有开启AOF持久化就会自动执行bgsave进RDB持久化
bgsave流程说明:
紧凑压缩的二进制文件,加载快,适用于灾备。但是使用子进程是一个重量级操作不适合实时持久化,而且老版本无法兼容。故有了AOF(append only file)持久化方式
以独立日志的方式记录下每一个写命令,重启时在重新执行。解决了redis数据持久化的实时性问题。
开启:config set appendonly yes
文件名:config get dir ;config get appendfilename; 默认为appendonly.aof
流程:
文本协议格式
例如:set hello world
写入AOF文件内:*3\r\n$3\r\nset\r\n$5\r\n\hello\r\n$5\r\nworld\r\n
优点:可读,便于修改;避免二次处理;兼容性好
由参数appendfsync控制
fsync操作:强制同步到硬盘,写入硬盘后线程返回,保证了持久化。
write操作:写入文件缓冲区页后即返回,缓冲区写满或者达到特定条件后进行持久化。如果中间发生宕机,缓冲区页内的数据可能会丢失。
将进程内的数据转化为写命令重新写入AOF文件,压缩AOF文件大小,能够更快的加载。
触发方式:
手动触发:bgrewriteaof
自动触发:根据参数:auto-aof-rewrite-min-size(运行AOF重写时的aof文件最小体积)和auto-aof-rewrite-percentage(当前aof文件体积aof_current_size和上一次文件重写后的体积aof_base_size的比值)参数确定触发时机
当aof-current-size>auto-aof-rewrite-min-size
且(aof_current_size - aof_base_size)/aof_base_size>=auto-aof-rewrite-percentage
ps: aof_current_size 和 aof_base_size通过info persistence查看
重写流程:
优先加载AOF文件,没有的话再看RDB文件
文件校验:
对于错误的文件无法加载时可以备份后进行修复:redis-check-aof --fix
掉电等故障可能会导致aof文件尾部写入不全。参数aof-load-truncated用来兼容此情况,默认开启,如果遇到此问题忽略并继续加载,打印警告日志。
fork操作会复制父进程的空间内存页表。例如10G的redis进程需要复制约20M的内存页表。故fork操作耗时跟进程的总内存量息息相关。
正常情况下fork操作每GB耗时20ms左右。
查看上一次fork操作耗时:info stats 中latest_fork_usec(单位:微秒)
如何改善fork操作耗时:
子进程通过fork操作产生,占用内存大小等同于父进程,理论上需要2倍内存来完成持久化操作。但是linux有写时复制机制(copy-on-write),
父子进程共享相同的物理内存页,父进程处理写请求时会把修改的内存页创建副本,子进程在fork过程中共享父进程整内存快照。
重写内存消耗情况:
监控redis日志
RDB重写:copy-on-write父进程创建的副本内存
AOF重写:copy-on-write父进程创建的副本内存+AOF缓冲区所占内存
内存消耗优化:
持久化到硬盘,硬盘写入压力,命令:sar/iostat/iotop 分析当前的硬盘负载情况。
优化方式:
AOF持久化常用的硬盘同步策略是everysec,如果系统硬盘资源繁忙,会造成redis主线程的阻塞。
主线程每隔1秒进行一次对比,如果距离上次同步成功时间>2s,堵塞主线程
所以
问题定位:
参考:《redis开发与运维》付磊、张益军著