redis学习(九)——数据持久化

1、概述redis

      Redis的强大性能很大程度上都是由于全部数据都是存储在内存中的,然而当Redis重启后,全部存储在内存中的数据将会丢失,在不少状况下是没法容忍这样的事情的。因此,咱们须要将内存中的数据持久化!典型的须要持久化数据的场景以下:数据库

  • 将Redis做为数据库使用;
  • 将Redis做为缓存服务器使用,可是缓存miss后会对性能形成很大影响,全部缓存同时失效时会形成服务雪崩,没法响应。

本文介绍Redis所支持的两种数据持久化方式。windows

2、Redis数据持久化缓存

      Redis支持两种数据持久化方式:RDB方式和AOF方式。前者会根据配置的规则定时将内存中的数据持久化到硬盘上,后者则是在每次执行写命令以后将命令记录下来。两种持久化方式能够单独使用,可是一般会将二者结合使用。安全

一、RDB方式服务器

     RDB方式的持久化是经过快照的方式完成的。当符合某种规则时,会将内存中的数据全量生成一份副本存储到硬盘上,这个过程称做”快照”,Redis会在如下几种状况下对数据进行快照:app

  • 根据配置规则进行自动快照;
  • 用户执行SAVE, BGSAVE命令;
  • 执行FLUSHALL命令;
  • 执行复制(replication)时。

执行快照的场景异步

(1)根据配置自动快照函数

      Redis容许用户自定义快照条件,当知足条件时自动执行快照。缺省状况下,Redis把数据快照存放在磁盘上的二进制文件中,文件名为dump.rdb,此外,咱们也能够经过配置文件来修改Redis服务器dump快照的频率,在打开redis.windows.conf文件以后,咱们搜索save,能够看到下面的配置信息:工具

注意最后三行,分别表示:

在900秒(15分钟)以后,若是至少有1个key发生变化,则dump内存快照;

在300秒(5分钟)以后,若是至少有10个key发生变化,则dump内存快照;

在60秒(1分钟)以后,若是至少有10000个key发生变化,则dump内存快照。

     每一个快照条件独占一行,他们之间是或(||)关系,只要知足任何一个就进行快照。上面配置save后的第一个参数T是时间,单位是秒,第二个参数M是更改的键的个数,含义是:当时间T内被更改的键的个数大于M时,自动进行快照。好比save 900 1的含义是15分钟内(900s)被更改的键的个数大于1时,自动进行快照操做。

(2)执行SAVE或BGSAVE命令

除了让Redis自动进行快照外,当咱们须要重启,迁移,备份Redis时,咱们也能够手动执行SAVE或BGSAVE命令主动进行快照操做。

  • SAVE命令:当执行SAVE命令时,Redis同步进行快照操做,期间会阻塞全部来自客户端的请求,因此放数据库数据较多时,应该避免使用该命令;
  • BGSAVE命令: 从命令名字就能看出来,这个命令与SAVE命令的区别就在于该命令的快照操做是在后台异步进行的,进行快照操做的同时还能处理来自客户端的请求。执行BGSAVE命令后Redis会立刻返回OK表示开始进行快照操做,若是想知道快照操做是否已经完成,可使用LASTSAVE命令返回最近一次成功执行快照的时间,返回结果是一个Unix时间戳。

(3)执行FLUSHALL命令

     当执行FLUSHALL命令时,Redis会清除数据库中的全部数据。须要注意的是:不论清空数据库的过程是否触发了自动快照的条件,只要自动快照条件不为空,Redis就会执行一次快照操做,当没有定义自动快照条件时,执行FLUSHALL命令不会进行快照操做。

(4)执行复制

当设置了主从模式时,Redis会在复制初始化时进行自动快照。

快照原理

      Redis默认会将快照文件存储在Redis当前进程的工做目录的dump.rdb文件中,能够经过配置文件中的dir和dbfilename两个参数分别指定快照文件的存储路径和文件名,默认的存储路径和文件名以下图所示:

快照执行的过程以下:

(1)Redis使用fork函数复制一份当前进程(父进程)的副本(子进程);
(2)父进程继续处理来自客户端的请求,子进程开始将内存中的数据写入硬盘中的临时文件;
(3)当子进程写完全部的数据后,用该临时文件替换旧的RDB文件,至此,一次快照操做完成。

须要注意的是:

在执行fork的时候操做系统(类Unix操做系统)会使用写时复制(copy-on-write)策略,即fork函数发生的一刻,父进程和子进程共享同一块内存数据,当父进程须要修改其中的某片数据(如执行写命令)时,操做系统会将该片数据复制一份以保证子进程不受影响,因此RDB文件存储的是执行fork操做那一刻的内存数据。因此RDB方式理论上是会存在丢数据的状况的(fork以后修改的的那些没有写进RDB文件)。

      经过上述的介绍能够知道,快照进行时是不会修改RDB文件的,只有完成的时候才会用临时文件替换老的RDB文件,因此就保证任什么时候候RDB文件的都是完整的。这使得咱们能够经过定时备份RDB文件来实现Redis数据的备份。RDB文件是通过压缩处理的二进制文件,因此占用的空间会小于内存中数据的大小,更有利于传输。

      Redis启动时会自动读取RDB快照文件,将数据从硬盘载入到内存,根据数量的不一样,这个过程持续的时间也不尽相同,一般来说,一个记录1000万个字符串类型键,大小为1GB的快照文件载入到内存须要20-30秒的时间。

示例

下面演示RDB方式持久化,首先使用配置有以下快照规则:

save 900 1
save 300 10
save 60 10000
dbfilename dump.rdb
dir ./

启动Redis服务:

而后经过客户端设置一个键值:

如今强行kill Redis服务,执行shutdown命令:

如今到D:\Redis_x64_321\目录看,目录下出现了Redis的快照文件dump.rdb:

如今从新启动Redis,而后再用客户端链接,检查以前设置的key是否还存在:

能够发现,以前设置的key在Redis重启以后又经过快照文件dump.rdb恢复了。

二、AOF方式

     在使用Redis存储非临时数据时,通常都须要打开AOF持久化来下降进程终止致使的数据丢失,AOF能够将Redis执行的每一条写命令追加到硬盘文件中,这一过程显然会下降Redis的性能,可是大部分状况下这个影响是能够接受的,另外,使用较快的硬盘能提升AOF的性能。

开启AOF

默认状况下,Redis没有开启AOF(append only file)持久化功能,能够经过在配置文件中做以下配置启用:

开启以后,Redis每执行一条写命令就会将该命令写入硬盘中的AOF文件。AOF文件保存路径和RDB文件路径是一致的,都是经过dir参数配置,默认文件名是:appendonly.aof,能够经过配置appendonlyfilename参数修改,例如:

AOF持久化的实现

AOF以纯文本的形式记录了Redis执行的写命令,例如在开启AOF持久化的状况下执行以下命令:

而后查看D:\Redis_x64_321\appendonly.aof文件:

文件中的内容正是Redis刚才执行的命令的内容,内容的格式就先不展开叙述了。

AOF文件重写

      AOF文件是可识别的纯文本,它的内容就是一个个的Redis标准命令,
      AOF日志也不是彻底按客户端的请求来生成日志的,好比命令 INCRBYFLOAT 在记AOF日志时就被记成一条SET记录,由于浮点数操做可能在不一样的系统上会不一样,因此为了不同一份日志在不一样的系统上生成不一样的数据集,因此这里只将操做后的结果经过SET来记录。

      每一条写命令都生成一条日志,AOF文件会很大。

     AOF重写是从新生成一份AOF文件,新的AOF文件中一条记录的操做只会有一次,而不像一份老文件那样,可能记录了对同一个值的屡次操做。其生成过程和RDB相似,也是fork一个进程,直接遍历数据,写入新的AOF临时文件。在写入新文件的过程当中,全部的写操做日志仍是会写到原来老的AOF文件中,同时还会记录在内存缓冲区中。当重完操做完成后,会将全部缓冲区中的日志一次性写入到临时文件中。而后调用原子性的rename命令用新的 AOF文件取代老的AOF文件。

 命令:BGREWRITEAOF, 咱们应该常常调用这个命令来来重写。

============================================================================= 

假设Redis执行了以下命令:

      若是这全部的命令都写到AOF文件的话,将是一个比较蠢的行为,由于前面两个命令会被第三个命令覆盖,因此AOF文件彻底不须要保存前面两个命令,事实上Redis确实就是这么作的。删除AOF文件中无用的命令的过程称为"AOF重写",AOF重写能够在配置文件中作相应的配置,当知足配置的条件时,自动进行AOF重写操做。配置以下:

auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

第一行的意思是,目前的AOF文件的大小超过上一次重写时的AOF文件的百分之多少时再次进行重写,若是以前没有重写过,则以启动时AOF文件大小为依据。
第二行的意思是,当AOF文件的大小大于64MB时才进行重写,由于若是AOF文件原本就很小时,有几个无效的命令也是无伤大雅的事情。
这两个配置项一般一块儿使用。

咱们还能够手动执行BGREWRITEAOF命令主动让Redis重写AOF文件:

执行重写命令以后查看如今的AOF文件:

能够看到,文件中并无再记录set k v1这样的无效命令。

同步硬盘数据

     虽然每次执行更改数据库的内容时,AOF都会记录执行的命令,可是因为操做系统自己的硬盘缓存的缘故,AOF文件的内容并无真正地写入硬盘,在默认状况下,操做系统会每隔30s将硬盘缓存中的数据同步到硬盘,可是为了防止系统异常退出而致使丢数据的状况发生,咱们还能够在Redis的配置文件中配置这个同步的频率:

1 # appendfsync always
2 appendfsync everysec
3 # appendfsync no

第一行表示每次AOF写入一个命令都会执行同步操做,这是最安全也是最慢的方式;
第二行表示每秒钟进行一次同步操做,通常来讲使用这种方式已经足够;
第三行表示不主动进行同步操做,这是最不安全的方式。

选项:

  一、appendfsync no

  当设置appendfsync为no的时候,Redis不会主动调用fsync去将AOF日志内容同步到磁盘,因此这一切就彻底依赖于操做系统的调试了。对大多数Linux操做系统,是每30秒进行一次fsync,将缓冲区中的数据写到磁盘上。

  二、appendfsync everysec

      当设置appendfsync为everysec的时候,Redis会默认每隔一秒进行一次fsync调用,将缓冲区中的数据写到磁盘。可是当这一次的fsync调用时长超过1秒时。Redis会采起延迟fsync的策略,再等一秒钟。也就是在两秒后再进行fsync,这一次的fsync就无论会执行多长时间都会进行。这时候因为在fsync时文件描述符会被阻塞,因此当前的写操做就会阻塞。因此,结论就是:在绝大多数状况下,Redis会每隔一秒进行一次fsync。在最坏的状况下,两秒钟会进行一次fsync操做。这一操做在大多数数据库系统中被称为group commit,就是组合屡次写操做的数据,一次性将日志写到磁盘。

  三、appednfsync always

      当设置appendfsync为always时,每一次写操做都会调用一次fsync,这时数据是最安全的,固然,因为每次都会执行fsync,因此其性能也会受到影响。

   建议采用 appendfsync everysec(缺省方式)

  快照模式能够和AOF模式同时开启,互补影响。

3、两者的区别

     RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操做过程是fork一个子进程,先将数据集写入临时文件,写入成功后,再替换以前的文件,用二进制压缩存储。

 AOF持久化以日志的形式记录服务器所处理的每个写、删除操做,查询操做不会记录,以文本的方式记录,能够打开文件看到详细的操做记录。

4、两者优缺点

RDB存在哪些优点呢?

    1). 一旦采用该方式,那么你的整个Redis数据库将只包含一个文件,这对于文件备份而言是很是完美的。好比,你可能打算每一个小时归档一次最近24小时的数据,同时还要天天归档一次最近30天的数据。经过这样的备份策略,一旦系统出现灾难性故障,咱们能够很是容易的进行恢复。
    2). 对于灾难恢复而言,RDB是很是不错的选择。由于咱们能够很是轻松的将一个单独的文件压缩后再转移到其它存储介质上。
    3). 性能最大化。对于Redis的服务进程而言,在开始持久化时,它惟一须要作的只是fork出子进程,以后再由子进程完成这些持久化的工做,这样就能够极大的避免服务进程执行IO操做了。
    4). 相比于AOF机制,若是数据集很大,RDB的启动效率会更高。
    
RDB又存在哪些劣势呢?

    1). 若是你想保证数据的高可用性,即最大限度的避免数据丢失,那么RDB将不是一个很好的选择。由于系统一旦在定时持久化以前出现宕机现象,此前没有来得及写入磁盘的数据都将丢失。
    2). 因为RDB是经过fork子进程来协助完成数据持久化工做的,所以,若是当数据集较大时,可能会致使整个服务器中止服务几百毫秒,甚至是1秒钟。

AOF的优点有哪些呢? 

  1). 该机制能够带来更高的数据安全性,即数据持久性。Redis中提供了3中同步策略,即每秒同步、每修改同步和不一样步。事实上,每秒同步也是异步完成的,其效率也是很是高的,所差的是一旦系统出现宕机现象,那么这一秒钟以内修改的数据将会丢失。而每修改同步,咱们能够将其视为同步持久化,即每次发生的数据变化都会被当即记录到磁盘中。能够预见,这种方式在效率上是最低的。至于无同步,无需多言,我想你们都能正确的理解它。
    2). 因为该机制对日志文件的写入操做采用的是append模式,所以在写入过程当中即便出现宕机现象,也不会破坏日志文件中已经存在的内容。然而若是咱们本次操做只是写入了一半数据就出现了系统崩溃问题,不用担忧,在Redis下一次启动以前,咱们能够经过redis-check-aof工具来帮助咱们解决数据一致性的问题。
    3). 若是日志过大,Redis能够自动启用rewrite机制。即Redis以append模式不断的将修改数据写入到老的磁盘文件中,同时Redis还会建立一个新的文件用于记录此期间有哪些修改命令被执行。所以在进行rewrite切换时能够更好的保证数据安全性。
    4). AOF包含一个格式清晰、易于理解的日志文件用于记录全部的修改操做。事实上,咱们也能够经过该文件完成数据的重建。
    
AOF的劣势有哪些呢?
    1). 对于相同数量的数据集而言,AOF文件一般要大于RDB文件。RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
    2). 根据同步策略的不一样,AOF在运行效率上每每会慢于RDB。总之,每秒同步策略的效率是比较高的,同步禁用策略的效率和RDB同样高效。

   两者选择的标准,就是看系统是愿意牺牲一些性能,换取更高的缓存一致性(aof),仍是愿意写操做频繁的时候,不启用备份来换取更高的性能,待手动运行save的时候,再作备份(rdb)。rdb这个就更有些 eventually consistent的意思了。

5、经常使用配置

RDB持久化配置

Redis会将数据集的快照dump到dump.rdb文件中。此外,咱们也能够经过配置文件来修改Redis服务器dump快照的频率,在打开6379.conf文件以后,咱们搜索save,能够看到下面的配置信息:
    save 900 1              #在900秒(15分钟)以后,若是至少有1个key发生变化,则dump内存快照。
    save 300 10            #在300秒(5分钟)以后,若是至少有10个key发生变化,则dump内存快照。
    save 60 10000        #在60秒(1分钟)以后,若是至少有10000个key发生变化,则dump内存快照。

AOF持久化配置 

在Redis的配置文件中存在三种同步方式,它们分别是:    appendfsync always     #每次有数据修改发生时都会写入AOF文件。    appendfsync everysec  #每秒钟同步一次,该策略为AOF的缺省策略。    appendfsync no          #从不一样步。高效可是数据不会被持久化。

相关文章
相关标签/搜索