不少时候咱们须要持久化数据也就是将内存中的数据写入磁盘里面,大部分缘由是为了以后重用数据(好比重启机器、机器故障以后恢复数据),或者是为了防止系统故障而将数据备份到一个远程位置。redis
Redis不一样于Memcached的很重要一点就是,Redisz支持持久化,并且支持两种不一样的持久化操做,Redis的一种持久化方式叫作快照(Snapshotting,RDB),另外一种方式只追加文件(append-only file,AOF).这两种方法各有千秋,下面将介绍咱们为何须要持久化,这两种持久化的方法是什么,怎么用,如何选择适合本身的持久化方法。数据库
Redis做为一个键值对内存数据库(NoSQL),数据都存储在内存中,在处理客户端请求时,全部操做都在内存当中进行,以下所示: 缓存
这样作有什么问题呢?安全
其实,只要稍微有点计算机基础知识的人都知道,存储在内存当中的数据,只要服务器关机(各类缘由引发),内存中的数据就会消失了,不只服务器关机会形成数据消失,Redis服务器守护进程退出,内存中的数据也同样会消失。bash
对于只把Redis当缓存来用的项目来讲,数据消失或许问题不大,从新从数据源把数据加载进来就能够了,但若是直接把用户提交的业务数据存储在Redis中,把Redis做为数据库来使用,在其存储重要业务数据,那么Redis的内存数据丢失所形成的影响也许是毁灭性的。服务器
为了不内存中数据丢失,Redis提供了持久化的支持,咱们能够选择不一样的方式将数据从内存中保存到硬盘中,将数据持久化保存。app
RDB是一种快照存储持久化方式,具体就是将Redis某一时刻的内存数据保存到硬盘里的文件当中,默认保存的文件名为dump.rdb,而在Redis服务器启动时,会从新加载dump.rdb文件的数据到内存中恢复数据。异步
开启RDB持久方方式很简单,客户端能够经过向Redis服务器发送save或bgsave命令让服务器生成rdb文件,或者经过服务器配置文件指定触发RDB条件。post
save命令是一个同步操做性能
# 同步数据到磁盘上
> save
复制代码
save 900 1 #在900秒(15分钟)以后,若是至少有1个key发生变化,Redis就会自动触发BGSAVE命令建立快照。
save 300 10 #在300秒(5分钟)以后,若是至少有10个key发生变化,Redis就会自动触发BGSAVE命令建立快照。
save 60 10000 #在60秒(1分钟)以后,若是至少有10000个key发生变化,Redis就会自动触发BGSAVE命令建立快照。
复制代码
当客户端向服务器发送save命令请求进行持久化时,服务器会阻塞save命令以后的其余客户端的请求,直到数据同步完成。
若是数据量太大,同步数据会执行好久,而这期间Redis服务器也没法接收其余请求,因此,最好不要在生产环境使用save命令。
与save命令不一样,bgsave命令是一个异步操做。
# 异步保存数据集到磁盘上
> bgsave
复制代码
全部,与save命令相比,Redis服务器在处理bgsave采用子进程进行IO写入,而主进程仍然能够接收其余请求,但forks子进程是同步的,全部forks子进程时,同样不能接收其余请求,这意味着,若是forks一个子进程话费的时间过久(通常很快),bgsave命令任然有阻塞其余客户的请求的状况发生。
除了经过客户端发送命令外,还有一种方式,就是在Redis配置文件中的save指定到达触发RDB持久化的条件,好比多少秒内至少达到多少写操做就开启RDB数据同步。
例如咱们能够在配置文件redis.conf指定以下的选项:
# 900s内至少达到一条写命令
save 900 1
# 300s内至少达至10条写命令
save 300 10
# 60s内至少达到10000条写命令
save 60 10000
复制代码
以后在启动服务器时加载配置文件
# 启动服务器加载配置文件
redis-server redis.conf
复制代码
这种童工服务器配置文件触发RDB的方式,与bgsave命令相似,达到触发条件时,会forks一个子进程进行数据同步,不过最好不要经过这种方式触发RDB持久化,由于设置触发的时间过短,则容易频繁写入rdb文件,影响服务器性能,时间设置太长则会形成数据丢失。
前面介绍了三种让服务器生成rdb文件的方式,不管是由主进程生成仍是子进程来生成,其过程以下:
# 是否压缩rdb文件
rdbcompression yes
# rdb文件的名称
dbfilename redis-6379.rdb
# rdb文件保存目录
dir ~/redis/
复制代码
与RDB存储某个时刻的快照不一样,AOF持久化方式会记录客户端对服务器的每一次写操做命令,并将这些写操做以Redis协议追加保存到之后缀为aof文件末尾,在Redis服务器重启时,会加载并运行aof文件的命令,以达到恢复数据的目的。
Redis默认不开启AOF持久化方式,咱们能够在配置文件中开启并进行更加详细的配置,以下面的redis.conf文件:
# 开启aof机制
appendonly yes
# aof文件名
appendfilename "appendonly.aof"
# 写入策略,always表示每一个写操做都保存到aof文件中,也能够是everysec或no
appendfsync always
# 默认不重写aof文件
no-appendfsync-on-rewrite no
# 保存目录
dir ~/redis/
复制代码
在上面的配置文件中,咱们能够经过appendfsync选项指定写入策略,有三个选项
appendfsync always
# appendfsync everysec
# appendfsync no
复制代码
客户端的每个写操做都保存到aof文档中,这种策略很安全,可是每一个写请求都有IO操做,因此也很慢。
appendfsync的默认策略,每秒写入一次aof文件,所以,不少可能会丢失1s的数据。
Redis服务器不负责写入aof,而是交由操做系统来处理何时写入aof文件。更快,但也最不安全的选择,不推荐使用
AOF将客户端的每个写操做都追加到aof文件末尾,好比对一个key屡次执行incr命令,这时候,aof保存每一次命令道aof文件中,aof文件会变得很是大。
incr num 1
incr num 2
incr num 3
incr num 4
incr num 5
incr num 6
...
incr num 100000
复制代码
aof文件太大,加载aof文件恢复数据时,就会很是慢,为了解决这个问题,Redis支持aof文件重写,经过重写aof,能够生成一个恢复当前数据的最少命令集,好比上面的例子中那么多命令,能够重写为:
set num 100000
复制代码
aof文件是一个二进制文件,并非像上面的例子同样,直接保存每一个命令,而使用Redis本身的格式,上面只是方便演示
经过在redis.conf配置文件中的选项no-appendfsync-on-rewrite能够设置是否开启重写,这种方式会在每次fsync时都重写,影响服务器性能,所以默认值为no,不推荐使用。
#默认不重写aof文件
no-appendfsync-no-rewrite no
复制代码
客户端向服务器发送bgrewriteaof命令,也可让服务器进行AOF重写。
#让服务器异步重写追加aof文件命令
> bgrewriteaof
复制代码
AOF重写方式也是异步操做,即若是要写入aof文件,则Redis主进程会forks一个子进程来处理
在写入aof日志文件时,若是Redis服务器宕机,则aof日志文件会处格式错误,在重启Redis服务器时,Redis服务器会拒绝载入这个aof文件,能够经过如下步骤修复aof并恢复数据。
#修复aof日志文件
$ redis-check-aof -fix file.aof
复制代码
AOF只是追加日志文件,所以对服务器性能影响较小,速度比RDB要快,消耗的内存较少。
经过上面的比较,我么了解了RDB和AOF的各自的优势和缺点,到底如何选择呢? 经过下面的对比,咱们能够从几个方面对比一下AOF和RDB,在应用时要根据本身的实际需求,选择RDB或者AOF,其实,若是想要数据足够安全,能够两种方式都开启,但两种持久化方式同时进行IO操做,会严重影响服务器性能,所以有时候不得不作出选择。
当RDB和AOF两种方式都开启时,Redis会优先选择使用AOF日志恢复数据,所以AOF保存的文件比RDB文件更加完整
Redis 4.0 开始支持 RDB 和 AOF 的混合持久化(默认关闭,能够经过配置项 aof-use-rdb-preamble 开启)。
若是把混合持久化打开,AOF 重写的时候就直接把 RDB 的内容写到 AOF 文件开头。这样作的好处是能够结合 RDB 和 AOF 的优势, 快速加载同时避免丢失过多的数据。固然缺点也是有的, AOF 里面的 RDB 部分就是压缩格式再也不是 AOF 格式,可读性较差。
以上文章主要来自10分钟完全理解Redis的持久化机制:RDB和AOF