Redis服务实例宕机后,其中的数据还能恢复吗?
是的,与其他内存数据库不同(如memcache没有持久化),redis还提供了数据持久化功能,并提供两种持久化方式:
- AOF(append only file):逻辑文件,记录的是一条一条的更改命令。在进行数据恢复时,需要一条一条的重放日志,恢复速度较慢
- RDB(read database):物理文件,把某一时刻内存中的数据写入到磁盘,类似于一个快照。在进行数据恢复时,直接将快照文件加载到内存中,恢复速度快
redis默认使用RDB的方式,异步的将数据写入到磁盘中。
AOF
AOF默认为关闭状态(appendonly no),需要手动开启(appendonly yes)。
# 开启aof
appendonly yes
# aof文件名
appendfilename "appendonly.aof"
# 持久化文件目录,aof+rdb
dir ./
# 进行数据恢复时,在 AOF 文件的开头追加 RDB 文件内容,加快数据恢复速度,减少AOF重放
aof-use-rdb-preamble yes
写入方式
在MySQL中,写日志的方式往往是写前日志(Write Ahead Log, WAL),即先写日志,再更新内存中的数据。Redis中不同的是,采用的写入方式为写后日志,即先更新内存中的数据,再写日志。
这是为什么呢?首先,在速度上,写后日志的速度快于写前日志,但写前日志可支持事务回滚、恢复等事务特性。而redis作为NoSQL更关注于速度,不支持事务回滚、恢复等,所以采用写后日志提供处理速度。
写入策略
我们知道AOF是在命令执行完后再写入日志,那么写入日志是同步写入还是异步写入呢?同步写入可以保证数据一致性,但是影响处理性能,有阻塞主线程的风险;异步写入速度最快,但是有数据不一致的风险(宕机,日志没写入磁盘)。其中的优劣需要根据实际应用去把握,为此,redis提供了三种写入策略:
- always:立即同步写回,每个写命令执行完后,同步地将日志写回磁盘,速度慢、但能保证一致性
- everysec:每秒同步写回,每个写命令执行完后,先把日志写到 AOF 文件的内存缓冲区,主线程每隔一秒把缓冲区中的内容写入磁盘,速度中等、宕机损失一秒内数据更改信息
- no:异步写回,由操作系统控制,每个写命令执行完后,先把日志写到 AOF 文件的内存缓冲区,由操作系统决定何时将缓冲区内容写回磁盘,速度最快、宕机损失的数据也最多
Redis的默认策略是everysec
# appendfsync always
appendfsync everysec
# appendfsync no
AOF日志重写
随着执行的命令数量增加、写入的日志大小也同步增加。为了减小日志的大小,使用一个异步线程对AOF日志进行重写。重写原理是,合并多条更新命令为一条。例如对一个key进行了六次更新,保存了六条日志,重写后只保存最新的一条即可。相关配置如下
# 设置 AOF 重写的触发条件,指定 AOF 文件大小增长的百分比,例如从32mb增加到64mb
auto-aof-rewrite-percentage 100
# 设置 AOF 重写的触发条件,指定最小 AOF 文件大小
auto-aof-rewrite-min-size 64mb
RDB
RDB是将数据库某一时刻的数据当作一个快照文件写入到磁盘中,这就引出了一个问题,什么时候执行RDB?
执行策略
redis中相关的配置格式为save
可以配置多个save,符合任一条配置都可以立即执行RDB,例如,默认的save配置有三个:
- save 3600 1
- save 300 100
- save 60 10000
# 执行策略
save 300 100
# 快照文件名
dbfilename dump.rdb
# 持久化文件目录,aof+rdb
dir ./
# 校验rdb文件,默认yes
rdbchecksum yes
# 压缩rdb文件,默认yes
rdbcompression yes
# 子线程执行RDB失败后,则拒绝接受写请求,用以提醒用户RDB无法正常工作
# 默认为yes,在有监控运维时可设置为no
stop-writes-on-bgsave-error no
写入策略
假设当前redis中有2GB的数据,以什么方式将2GB的数据保存到磁盘上呢?
为了不阻塞主线程,自然只能使用子线程进行异步保存了。具体操作是主线程fork一个子线程,这个子线程共享主线程的内存,可以访问其中的数据。
异步保存?那岂不是可以加快RDB的执行频率了。
这也是不可取的,
- 一是:磁盘的写入速率较慢,会增加磁盘压力
- 二是:虽然保存快照是异步的,但是主线程fork子线程这个操作是同步的,并且内存数据越大,fork时间越长
异步保存快照文件时,内存中的数据还能进行更改吗?变了还能叫做快照吗?
能更改,但是快照还是那个快照,这一切通过写时复制(Copy-On-Write, COW)技术完成。
写时复制
子线程在保存快照文件时,从客户端传来了请求
- 如果是读取请求,没有影响,主线程从内存中读取后返回
- 如果是写请求,主线程在进行更改前,需要将值拷贝一个副本出来,供子线程使用
通过写时复制,可以保证在子线程异步保存快照文件时,不影响主线程处理客户端请求。
如何选择持久化方式?
redis中可以单独使用AOF和RDB,也可以一起使用,具体的配置需要根据实际应用进行选择。
在主从架构中,主库不进行持久化,在从库中进行持久化操作。
不需要持久化
可以在redis.conf中配置save "",表明不使用持久化
需要持久化,但可以忍受几分钟的数据丢失
使用默认的RDB配置即可
不能忍受长时间的数据丢失
使用AOF,并配置appendfsync everysec(要求高可配置为always),配合RDB一起使用,可以在确保数据一致性的基础上加快数据恢复速度。
标签:AOF,异步,持久,可用,Redis,写入,RDB,快照,日志 From: https://www.cnblogs.com/cd-along/p/18168873