美文网首页
Redis持久化

Redis持久化

作者: 努力耕耘少问收获 | 来源:发表于2020-01-19 15:41 被阅读0次

    Redis的强大性能很大程度上都是因为所有数据都是存储在内存中的,

    然而当Redis重启后,所有存储在内存中的数据将会丢失,在很多情况

    下是无法容忍这样的事情的。所以,我们需要将内存中的数据持久化!

    典型的需要持久化数据的场景如下:

    将Redis作为数据库使用;

    将Redis作为缓存服务器使用,但是缓存miss后会对性能造成

    很大影响,所有缓存同时失效时会造成服务雪崩,无法响应。

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

    Redis数据持久化

    Redis支持两种数据持久化方式:RDB方式和AOF方式。前者会根据配置

    的规则定时将内存中的数据持久化到硬盘上,后者则是在每次执行写命

    令之后将命令记录下来。两种持久化方式可以单独使用,但是通常会将

    两者结合使用。

    RDB方式

    RDB方式的持久化是通过快照的方式完成的。当符合某种规则时,会将

    内存中的数据全量生成一份副本存储到硬盘上,这个过程称作”快

    照”,Redis会在以下几种情况下对数据进行快照:

    根据配置规则进行自动快照;

    用户执行SAVE, BGSAVE命令;

    执行FLUSHALL命令;

    执行复制(replication)时。

    执行快照的场景

    根据配置自动快照Redis允许用户自定义快照条件,当满足条件时自动执行快照,快照规

    则的配置方式如下:

    1 save 900 1

    2 save 300 10

    3 save 60 10000

    每个快照条件独占一行,他们之间是或(||)关系,只要满足任何一个

    就进行快照。上面配置save后的第一个参数T是时间,单位是秒,第二

    个参数M是更改的键的个数,含义是:当时间T内被更改的键的个数大于

    M时,自动进行快照。比如save 900 1的含义是15分钟内(900s)被更改

    的键的个数大于1时,自动进行快照操作。

    执行SAVE或BGSAVE命令

    除了让Redis自动进行快照外,当我们需要重启,迁移,备份Redis时,

    我们也可以手动执行SAVE或BGSAVE命令主动进行快照操作。

    SAVE命令:当执行SAVE命令时,Redis同步进行快照操

    作,期间会阻塞所有来自客户端的请求,所以放数据库数据较多

    时,应该避免使用该命令;

    BGSAVE命令: 从命令名字就能看出来,这个命令与SAVE

    命令的区别就在于该命令的快照操作是在后台异步进行的,进行

    快照操作的同时还能处理来自客户端的请求。执行BGSAVE命令

    后Redis会马上返回OK表示开始进行快照操作,如果想知道快照

    操作是否已经完成,可以使用LASTSAVE命令返回最近一次成功

    执行快照的时间,返回结果是一个Unix时间戳。

    执行FLUSHALL命令

    当执行FLUSHALL命令时,Redis会清除数据库中的所有数据。需要注意

    的是:不论清空数据库的过程是否触发 了自动快照的条件,只要自动快照条件不为空,Redis就会执行一次快照操作,当没有定义自动快照

    条件时,执行FLUSHALL命令不会进行快照操作。

    执行复制

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

    快照原理

    Redis默认会将快照文件存储在Redis当前进程的工作目录的dump.rdb文

    件中,可以通过配置文件中的dir和dbfilename两个参数分别指定快照

    文件的存储路径和文件名,例如:

    1 dbfilename dump.rdb

    2 dir /opt/soft/redis-3.0.4/cache

    快照执行的过程如下:

    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方式持久化,首先使用配置有如下快照规则:

    1 save 900 1

    2 save 300 10

    3 save 60 10000

    4 dbfilename dump.rdb

    5 dir /opt/soft/redis-3.0.4/cache

    的配置文件/opt/soft/redis-3.0.4/conf/redis.conf启动Redis服务:

    然后通过客户端设置一个键值:

    1 [qifuguang@Mac~]$ /opt/soft/redis-3.0.4/src/redis-cli -p 6379

    2 127.0.0.1:6379> set test-rdb HelloWorld

    3 OK

    4 127.0.0.1:6379> get test-rdb

    5 "HelloWorld"6 127.0.0.1:6379>

    现在强行kill Redis服务:

    现在到/opt/soft/redis-3.0.4/cache目录看,目录下出现了Redis的快

    照文件dump.rdb:

    1 [qifuguang@Mac/opt/soft/redis-3.0.4/cache]$ ls

    2 dump.rdb

    现在重新启动Redis:

    然后再用客户端连接,检查之前设置的key是否还存在:

    4

    3

    2

    1 3.0.4/src/redis-cli -p 6379

    127.0.0.1:6379> get test-r

    "HelloWorld"

    127.0.0.1:6379>

    [qifuguang@Mac~]$ /opt

    可以发现,之前设置的key在Redis重启之后又通过快照文件dump.rdb恢

    复了。

    AOF方式在使用Redis存储非临时数据时,一般都需要打开AOF持久化来降低进程

    终止导致的数据丢失,AOF可以将Redis执行的每一条写命令追加到硬盘

    文件中,这已过程显然会降低Redis的性能,但是大部分情况下这个影

    响是可以接受的,另外,使用较快的硬盘能提高AOF的性能。

    开启AOF

    默认情况下,Redis没有开启AOF(append only file)持久化功能,可

    以通过在配置文件中作如下配置启用:

    1 appendonly yes

    开启之后,Redis每执行一条写命令就会将该命令写入硬盘中的AOF文

    件。AOF文件保存路径和RDB文件路径是一致的,都是通过dir参数配

    置 , 默 认 文 件 名 是 : appendonly.aof , 可 以 通 过 配 置

    appendonlyfilename参数修改,例如:

    1 appendonlyfilename appendonly.aof

    AOF持久化的实现

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

    情况下执行如下命令:

    1 [qifuguang@Mac/opt/soft/redis-3.0.4]$ ./src/redis-cli

    2 127.0.0.1:6379>

    3 127.0.0.1:6379>

    4 127.0.0.1:6379>

    5 127.0.0.1:6379> set aof1 value1

    6 OK

    7 127.0.0.1:6379> set aof2 value2

    8 OK

    9 127.0.0.1:6379>

    然后查看/opt/soft/redis-3.0.4/cache/appendonly.aof文件:

    1 [qifuguang@Mac/opt/soft/redis-3.0.4/cache]$ cat appendonly.aof

    2 *23 $6

    4 SELECT

    5 $1

    6 0

    7 *3

    8 $3

    9 set

    10 $4

    11 aof1

    12 $6

    13 value1

    14 *3

    15 $3

    16 set

    17 $4

    18 aof2

    19 $6

    20 value2

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

    开叙述了。

    AOF文件重写

    假设Redis执行了如下命令:

    1 [qifuguang@Mac/opt/soft/redis-3.0.4]$ ./src/redis-cli

    2 127.0.0.1:6379>

    3 127.0.0.1:6379>

    4 127.0.0.1:6379>

    5 127.0.0.1:6379> set k v1

    6 OK

    7 127.0.0.1:6379> set k v2

    8 OK

    9 127.0.0.1:6379> set k v3

    10 OK

    11 127.0.0.1:6379>

    如果这所有的命令都写到AOF文件的话,将是一个比较蠢行为,因为前

    面两个命令会被第三个命令覆盖,所以AOF文件完全不需要保存前面两个文件,事实上Redis确实就是这么做的。删除AOF文件中无用的命令的

    过程成为”AOF重写”,AOF重写可以在配置文件中做相应的配置,当满

    足配置的条件时,自动进行AOF重写操作。配置如下:

    1 auto-aof-rewrite-percentage 100

    2 auto-aof-rewrite-min-size 64mb

    第一行的意思是,目前的AOF文件的大小超过上一次重写时的AOF文件的

    百分之多少时再次进行重写,如果之前没有重写过,则以启动时AOF文

    件大小为依据。

    第二行的意思是,当AOF文件的大小大于64MB时才进行重写,因为如果

    AOF文件本来就很小时,有几个无效的命令也是无伤大雅的事情。

    这两个配置项通常一起使用。

    我们还可以手动执行BDREWRITEAOF命令主动让Redis重写AOF文件,执行

    重写命令之后查看现在的AOF文件:

    1 [qifuguang@Mac/opt/soft/redis-3.0.4]$ cat cache/appendonly.aof

    2 *2

    3 $6

    4 SELECT

    5 $1

    6 0

    7 *3

    8 $3

    9 SET

    10 $4

    11 aof2

    12 $6

    13 value2

    14 *3

    15 $3

    16 SET

    17 $1

    18 k

    19 $2

    20 v3

    21 *322 $3

    23 SET

    24 $4

    25 aof1

    26 $6

    27 value1

    可以看到,文件中并没有再记录set k v1这样的无效命令。

    同步硬盘数据

    虽然每次执行更改数据库的内容时,AOF都会记录执行的命令,但是由

    于操作系统本身的硬盘缓存的缘故,AOF文件的内容并没有真正地写入

    硬盘,在默认情况下,操作系统会每隔30s将硬盘缓存中的数据同步到

    硬盘,但是为了防止系统异常退出而导致丢数据的情况发生,我们还可

    以在Redis的配置文件中配置这个同步的频率:

    1 # appendfsync always

    2 appendfsync everysec

    3 # appendfsync no

    第一行表示每次AOF写入一个命令都会执行同步操作,这是最安全也是

    最慢的方式;

    第二行表示每秒钟进行一次同步操作,一般来说使用这种方式已经足

    够;

    第三行表示不主动进行同步操作,这是最不安全的方式。

    总结:redis的持久化

    Snapshotting(快照)RDB

    修改配置文件,在指定时间内修改的键个数大于设定的值执行save,

    参数:秒数,修改的键个数

    例如:

    save 20 1

    save 900 1save 300 10

    save 60 10000

    配置文件不起作用是因为重启的时候没有加配置文件的参数,例如:

    redis­server /tsh/redis­3.0.0/redis.conf

    append only file(AOF模式)

    修改配置文件redis.conf,appendonly yes

    重启服务,一定有加上配置文件的参数

    此时在 src目录下生成文件appendonly.aof,这个文件记录了每一步

    的操作,效率稍慢但是更安全

    相关文章

      网友评论

          本文标题:Redis持久化

          本文链接:https://www.haomeiwen.com/subject/sebrzctx.html