持久化
持久化方式
- 快照方式:将数据库中的所有数据全部拷贝出来,即某时刻的完整备份
- 缺点:耗时耗性能,在拷贝时若又有写入数据时,新写入的数据不会保存
- 优点:备份文件体积小,恢复速度快
- 写日志方式:将数据库中数据的更新记录在日志中,需要将数据恢复时,根据日志文件记录的更新操作进行数据恢复
- 缺点:备份文件体积大,恢复速度慢
- 优点:性能损耗小,不会丢失数据(是否丢失数由备份策略决定)
若两种方式共存时,由于快照方式是一个较重的操作,写日志方式是一个较轻的操作,所以写日志方式优先级会高于快照方式
RDB
是快照方式,将Redis内存中存储的所有数据写入到一个RDB文件(二进制)中,恢复时加载这个RDB文件即可
要注意,若已存在老的RDB文件,会先创建一个临时文件,当备份命令执行完毕后再对老文件进行替换
RDB方式备份的三种方式
- 同步备份:
save
命令,该命令执行时会阻塞其他命令执行,因为Redis是单线程,该命令在主进程中执行 - 异步备份:
bgsave
命令,该命令执行时一般不会阻塞其他的命令,因为该命令会调用Linux系统函数fork()函数创建一个子进程(有可能在调用fork()方法时阻塞,因为创建子进程也需要内存和时间,子进程名为redis-rdb-bgsave),由子进程来完成备份操作,之后子进程再通知主进程 - 自动备份:根据配置文件中配置的备份策略使用
bgsave
命令进行自动备份- 全量复制:主从Redis节点在进行全量复制时(主节点会执行
bgsave
)也会自动生成RDB文件 debug reload
:执行该命令进行热重启,保存数据为RDB文件,清空数据库,在重新加载RDB文件shutdown save
:关闭数据库并保存数据为RDB文件
- 全量复制:主从Redis节点在进行全量复制时(主节点会执行
自动备份配置参数
配置项 | 描述 | 默认值 |
---|---|---|
save |
自动保存策略,第一个参数是时间(单位秒),第二个参数是修改量,比如save 900 1 就代表在900秒内更新过一次数据就触发自动保存,可同时配置多条,若满足任意一条策略就会执行自动备份 |
900 1、300 10和60 10000 |
dbfilename |
自动备份的文件名(仅仅只是名,可使用内置常量命名,比如${port} 代表端口号) |
dump.rdb |
dir |
Redis的工作目录(产生各种的文件的存放目录) | ./ |
stop-writes-on-bgsave-error |
若备份过程中发生错误是否停止写入 | yes |
rdbcompression |
RDB文件是否采用压缩格式 | yes |
rdbchecksum |
是否对RDB文件进行校验和的检验 | yes |
AOF
是写日志方式,实质是将写命令写在硬盘的缓冲区中,再根据相关策略刷新到AOF文件中,恢复时加载这个AOF文件即可
AOF备份的三种策略
-
always
:执行每条写命令都会将写命令写到AOF文件中,一定不会丢失数据,但是IO开销大 -
everysec
:每秒将数据从缓冲区刷到AOF文件中,会适当的保护磁盘,可能会丢失一秒的数据 -
no
:写命令何时刷新的AOF文件中,由操作系统来决定,所以不可控
AOF备份的配置参数
配置项 | 描述 | 默认值 |
---|---|---|
appendonly |
是否开启AOF备份 | no |
appendfilename |
自动备份的文件名(仅仅只是名,可使用内置常量命名,比如${port} 代表端口号) |
appendonly.aof |
appendfsync |
备份策略 | everysec |
dir |
Redis的工作目录(产生各种的文件的存放目录) | ./ |
aof-load-truncated |
在使用AOF恢复时,当AOF文件出现错误是否忽略 | yes |
AOF重写
写日志方式存在一个问题,就是随着时间的推移,日志文件会越来越大,对于同一数据的更新,只有最后那一次才起作用,所以需要将一些无用的命令日志进行化简,化简成一个很小的日志文件,从而能减少日志文件大小,也能加快恢复速度
并非扫描日志文件进行优化,而是对数据库本身进行回溯成AOF文件,为了防止在重新时有新的数据更新请求,会将新的更新请求日志先记录在缓冲区中,当重新完成后,再将缓冲区中的内容添加到重写后的AOF文件中
bgrewriteaof
命令:该命令会创建一个子进程,由子进程来完成AOF重写操作- 自动重写:通过配置文件配置配置的策略进行自动重写(使用
bgrewriteaof
命令进行自动重写)
自动重写配置参数
配置项 | 描述 | 默认值 |
---|---|---|
no-appendfsync-no-rewrite |
在执行重写时是否不进行AOF操作,即是否绕过缓冲区,在重写时可能会丢失数据 | no |
auto-aof-rewrite-min-size |
AOF文件到达多大时重写 | 64mb |
auto-aof-rewrite-percentage |
据上一次重新增加了百分之多少后重写(单位百分比) | 100 |
执行info persistence
查看数据库持久化的具体信息
项 | 描述 |
---|---|
aof_current_size |
AOF文件当前尺寸(单位字节),AOF启用状态才会有此参数 |
aof_base_size |
AOF上次启动和重写的尺寸(单位字节),AOF启用状态才会有此参数 |
持久化中的常见问题
fork操作
在异步备份时Redis主进程都会通过LInux中的fork()系统函数创建一个子进程,创建子进程的过程是同步的,可能会引起阻塞,使用info stats
命令可查看数据库状态,其中latest_fork_usec
项就是之前最近的fork所消耗的时间,单位微秒
导致fork操作慢的原因与机型、内存量有关,一般内存越大,耗时越长,因为内存越大内存页的数据也会也多,fork在寻找可用内存空间也会越耗时
提升fork操作的性能方式有:使用更好支持fork操作的机型、控制Redis实例最大可用内存、合理的配置Linux内存分配策略、甚至降低fork操作的频率
子进程
CPU
开销:RDB和AOF都会生成文件,属于CPU密集型
优化1:不要Redis绑定在一个CPU上,父子进程就会减少CPU竞争
优化2:不和CPU密集型的应用部署在同一台服务器上,减少与其他应用的CPU竞争
优化3:避免在单机多部署的场景大量发生AOF重写
内存
开销:理论上子进程的占用内存应该等于父进程,但是Linux有一个copy-on-write机制,该机制是父子进程共享物理内存页,但是当父进程写请求的时候会创建一个副本,此时会消耗内存,即父进程在大量写入的时候,子进程开销会比较大,因为创建副本
优化1:Linux内核的2.6.38版本中增加了THP的特性,支持大的内存页的分配,对于Redis来说大内存页会降低性能,使用echo never > /sys/kernel/mm/transparent_hugepage/enabled
命令进行关闭该特性
优化2:避免在单机多部署的场景大量发生AOF重写
硬盘
开销:RDB与AOF文件的写入
优化1:不要和高硬盘负载服务部署在一起,例如存储服务、消息队列
优化2:将Redis配置no-appendfsync-on-rewrite
配置项为yes,即在执行重写时不进行AOF操作,减少硬盘写入
优化3:使用固态硬盘
AOF追加阻塞
Redis在进行AOF备份时,主线程将更新命令放入缓冲区,由同步线程将缓冲区刷入AOF文件中,为了保证AOF文件的安全性,主线程会记录同步时间,并比对上一次同步时间,若超过两秒就会阻塞,保证同步完成
- 可以通过Redis日志快速定位该问题:若出现Asynchronous AOF fsync is taking too long (disk is busy?),表示出现了该问题
- 也可以通过
info persistence
命令进行查看:每发生一次追加阻塞,aof_delayed_fsync
项就会加1
优化方式就是上述的硬盘优化
Comments NOTHING