Redis持久化

  前言:持久化是什么?简单的说就是将数据放在断电后不会丢失的设备中,比如磁盘,数据库在进行写操作时做了哪些事呢?

  主要有五个过程
  1、客户端向服务端发送写操作(数据在客户端的内存中)。
  2、数据库服务端接收到写请求的数据(数据在服务端的内存中)。
  3、服务端调用write这个系统调用,将数据往磁盘上写(数据在系统内存的缓冲区中)。
  4、操作系统将缓冲区中的数据转移到磁盘控制器上(数据在磁盘缓存中)。
  5、磁盘控制器将数据写到磁盘的物理介质中(数据真正落到磁盘上)。

  从上面可以看出,当数据库发生故障时,如果系统内核是完好的。那么执行完了第三步,那么数据就是安全的,如果断电,上面五项中所有的缓存都会失效,数据库和操作系统都会停止工作。所以只有全部走完才能保证数据不丢失。
  通过上面的分析,我们可能有一些疑惑。
  1、数据库多长时间调用一次write,将数据写到内核缓冲区?
  2、内核多长时间会将系统缓冲区中的数据写到磁盘控制器?
  3、磁盘控制器又在什么时候把缓存中的数据写到物理介质上?
  其中第一个问题通常都是由数据库层面控制。第二个问题呢操作系统都有默认的策略,但是可以通过通过POSIX API提供的fsync系列命令强制操作系统将数据从内核区写到磁盘控制器上
  对于第三个问题数据库已经无法触及,但实际上,大多数情况下磁盘缓存是被设置关闭的,或者是只开启为读缓存,也就是说写操作不会进行缓存,直接写到磁盘。建议的做法是仅仅当你的磁盘设备有备用电池时才开启写缓存。
  数据备份一般有三种方式:
  A:数据同步备份的方式
  B:记录每一步的操作行为
  C:以追加的方式记录数据,数据本身不修改,数据本身就是一份日志。

  Redis有两种持久化策略:RDB和AOF

  一、RDB快照

  RDB 持久化可以在指定的时间间隔内生成数据集的时间点快照。如何生成快照呢?Redis借助了fork命令的copy on write机制。在生成快照时,将当前进程fork出一个子进程,然后在子进程中循环所有的数据,将数据写成为RDB文件。
  子进程基本上是复制父进程,这等于两个相同的redis进程在系统上运行,会造成内存使用率的大幅增加。redis.conf中配置参数如下:含义为X秒改变了N次

      

Background saving started by pid 19064
19064:C 19 Sep 23:55:45.087 # Failed opening the RDB file dump.rdb (in server root dir /home/matao/redis-3.2.9/src) for saving: Permission denied
#   Will save the DB if both the given number of seconds and the given
--More--(15%)2470:M 19 Sep 23:55:45.186 # Background saving error
#   number of write operations against the DB occurred.
#
#   In the example below the behaviour will be to save:
#   after 900 sec (15 min) if at least 1 key changed
#   after 300 sec (5 min) if at least 10 keys changed
#   after 60 sec if at least 10000 keys changed
#
#   Note: you can disable saving completely by commenting out all "save" lines.
#
#   It is also possible to remove all the previously configured save
#   points by adding a save directive with a single empty string argument
#   like in the following example:
#
#   save ""

//保存的策略
save
900 1 save 300 10 save 60 10000
# The filename where to dump the DB
dbfilename dump.rdb  //保存的文件名       
# The working directory.
#
# The DB will be written inside this directory, with the filename specified
# above using the 'dbfilename' configuration directive.
#
# The Append Only File will also be created inside this directory.
#
# Note that you must specify a directory here, not a file name.
dir ./   //保存的文件路径

  手动保存有两种方式:

  1、save 同步进行 阻塞客户端请求
  2、bgsave异步进行 不妨碍目前的写入。

  二、AOF

  AOF是通过保存对redis服务端的写命令来记录数据库状态的,即保存你对redis数据库的写操作。AOF的运作方式是不断的将写命令追加到文件的末尾,所以随着写入命令的不断增减,AOF的文件体积也会变大越来越大。
  例如:一个计数器调用了100次INCR,那么AOF文件就记录了100条记录。实际上只使用一条set命令足以保存计数器当前的值了,为了控制AOF文件的大小,redis支持执行 BGREWRITEAOF 命令, Redis 将生成一个新的 AOF 文件, 这个文件包含重建当前数据集   所需的最少命令。
  Redis调用write写入后,何时调用fsync将其写到磁盘上,通过appendfsync来控制
  1、appendfsync no
  当设置appendfsync为no的时候,Redis不会主动调用fsync去将AOF日志内容同步到磁盘,所以这一切就完全依赖于操作系统的调试了。对大多数Linux操作系统,是每30秒进行一次fsync,将缓冲区中的数据写到磁盘上。
  2、appendfsync everysec
  当设置appendfsync为everysec的时候,Redis会默认每隔一秒进行一次fsync调用,将缓冲区中的数据写到磁盘。但是当这一 次的fsync调用时长超过1秒时。Redis会采取延迟fsync的策略,再等一秒钟。也就是在两秒后再进行fsync,这一次的fsync就不管会执行多长时间都会进行。这时候由于在fsync时文件描述符会被阻塞,所以当前的写操作就会阻塞。 所以,结论就是:在绝大多数情况下,Redis会每隔一秒进行一次fsync。在最坏的情况下,两秒钟会进行一次fsync操作。 这一操作在大多数数据库系统中被称为group commit,就是组合多次写操作的数据,一次性将日志写到磁盘。
  3、appednfsync always
  当设置appendfsync为always时,每一次写操作都会调用一次fsync,这时数据是最安全的,当然,由于每次都会执行fsync,所以其性能也会受到影响。
  优点:RDB非常适合用于备份,恢复速度很快。AOF会使redis变得非常耐久,使数据安全性进一步提高。
  缺点:RDB在服务器故障时会丢失一段时间的数据。AOF文件的体积大于RDB,AOF的速度可能会慢于RDB。

posted @ 2017-09-20 15:02  猿祖  阅读(926)  评论(3编辑  收藏  举报