Redis持久化磁盘IO方式及其带来的问题   有Redis线上运维经验的人会发现Redis在物理内存使用比较多,但还没有超过实际物理内存总容量时就会发生不稳定甚至崩溃的问题,有人认为是基于快照方式持

时间:2021-11-28 23:01:52

转自:http://blog.csdn.net/kaosini/article/details/9176961

一、对Redis持久化的探讨与理解

redis是一个支持持久化的内存数据库,也就是说redis需要经常将内存中的数据同步到磁盘来保证持久化。redis支持两种持久化方式,一种是 Snapshot(RDB)也是默认方式,另一种是Append only file(AOF)的方式。具体的理论说明请见这里

我们应该明确持久化的数据有什么用,答案是用于重启后的数据恢复。Redis是一个内存数据库,无论是RDB还是AOF,都只是其保证数据恢复的措施。所以Redis在利用RDB和AOF进行恢复的时候,都会读取RDB或AOF文件,重新加载到内存中。

RDB就是Snapshot快照存储,是默认的持久化方式。即按照一定的策略周期性的将数据保存到磁盘。对应产生的数据文件为dump.rdb,通过配置文件中的save参数来定义快照的周期。Redis支持将当前数据的快照存成一个数据文件的持久化机制。而一个持续写入的数据库如何生成快照呢。Redis借助了fork命令的copy on write机制。在生成快照时,将当前进程fork出一个子进程,然后在子进程中循环所有的数据,将数据写成为RDB文件。

Redis的RDB文件不会坏掉,因为其写操作是在一个新进程中进行的。当生成一个新的RDB文件时,Redis生成的子进程会先将数据写到一个临时文件中,然后通过原子性rename系统调用将临时文件重命名为RDB文件。这样在任何时候出现故障,Redis的RDB文件都总是可用的。并且Redis的RDB文件也是Redis主从同步内部实现中的一环:
第一次Slave向Master同步的实现是:
Slave向Master发出同步请求,Master先dump出rdb文件,然后将rdb文件全量传输给slave,然后Master把缓存的命令转发给Slave,初次同步完成。
第二次以及以后的同步实现是:
Master将变量的快照直接实时依次发送给各个Slave。但不管什么原因导致Slave和Master断开重连都会重复以上两个步骤的过程。
Redis的主从复制是建立在内存快照的持久化基础上的,只要有Slave就一定会有内存快照发生。

不足:就是一旦数据库出现问题,那么我们的RDB文件中保存的数据并不是全新的,从上次RDB文件生成到Redis停机这段时间的数据全部丢掉了(因为刷写机制还没有出发)。RDB就是Snapshot快照存储,是默认的持久化方式。相关参数:

 1 ################################ SNAPSHOTTING  #################################
2 # Save the DB on disk:
3 # 设置sedis进行数据库镜像的频率。
4 # 900秒(15分钟)内至少1个key值改变(则进行数据库保存--持久化)。
5 # 300秒(5分钟)内至少10个key值改变(则进行数据库保存--持久化)。
6 # 60秒(1分钟)内至少10000个key值改变(则进行数据库保存--持久化)。
7 save 900 1
8 save 300 10
9 save 60 10000
10
11 stop-writes-on-bgsave-error yes
12 # 在进行镜像备份时,是否进行压缩。yes:压缩,但是需要一些cpu的消耗。no:不压缩,需要更多的磁盘空间。
13 rdbcompression yes
14 # 一个CRC64的校验就被放在了文件末尾,当存储或者加载rbd文件的时候会有一个10%左右的性能下降,为了达到性能的最大化,你可以关掉这个配置项。
15 rdbchecksum yes
16 # 快照的文件名
17 dbfilename dump.rdb
18 # 存放快照的目录
19 dir /var/lib/redis

AOF(Append Only File)比RDB方式有更好的持久化性。由于在使用AOF持久化方式时,Redis会将每一个收到的写命令都通过Write函数追加到文件中,类似于MySQL的binlog。当Redis重启是会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。

AOF的完全持久化方式同时也带来了另一个问题,持久化文件会变得越来越大。(比如我们调用INCR test命令100次,文件中就必须保存全部的100条命令,但其实99条都是多余的。因为要恢复数据库的状态其实文件中保存一条SET test 100就够了)。为了压缩AOF的持久化文件,Redis提供了bgrewriteaof命令。收到此命令后Redis将使用与快照类似的方式将内存中的数据以命令的方式保存到临时文件中,最后替换原来的文件,以此来实现控制AOF文件的增长。由于是模拟快照的过程,因此在重写AOF文件时并没有读取旧的AOF文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的AOF文件。相关参数:

 1 ############################## APPEND ONLY MODE ###############################
2 # 是否开启AOF,默认关闭(no)
3 appendonly yes
4 # 指定 AOF 文件名
5 appendfilename appendonly.aof
6 # Redis支持三种不同的刷写模式:
7 # appendfsync always #每次收到写命令就立即强制写入磁盘,是最有保证的完全的持久化,但速度也是最慢的,一般不推荐使用。
8 appendfsync everysec #每秒钟强制写入磁盘一次,在性能和持久化方面做了很好的折中,是受推荐的方式。
9 # appendfsync no #完全依赖OS的写入,一般为30秒左右一次,性能最好但是持久化最没有保证,不被推荐。
10
11 #在日志重写时,不进行命令追加操作,而只是将其放在缓冲区里,避免与命令的追加造成DISK IO上的冲突。
12 #设置为yes表示rewrite期间对新写操作不fsync,暂时存在内存中,等rewrite完成后再写入,默认为no,建议yes
13 no-appendfsync-on-rewrite yes
14 #当前AOF文件大小是上次日志重写得到AOF文件大小的二倍时,自动启动新的日志重写过程。
15 auto-aof-rewrite-percentage 100
16 #当前AOF文件启动新的日志重写过程的最小值,避免刚刚启动Reids时由于文件尺寸较小导致频繁的重写。
17 auto-aof-rewrite-min-size 64mb

到底选择什么呢?下面是来自官方的建议:
通常,如果你要想提供很高的数据保障性,那么建议你同时使用两种持久化方式。如果你可以接受灾难带来的几分钟的数据丢失,那么你可以仅使用RDB。
很多用户仅使用了AOF,但是我们建议,既然RDB可以时不时的给数据做个完整的快照,并且提供更快的重启,所以最好还是也使用RDB。
在数据恢复方面:
RDB的启动时间会更短,原因有两个:
一是RDB文件中每一条数据只有一条记录,不会像AOF日志那样可能有一条数据的多次操作记录。所以每条数据只需要写一次就行了。
另一个原因是RDB文件的存储格式和Redis数据在内存中的编码格式是一致的,不需要再进行数据编码工作,所以在CPU消耗上要远小于AOF日志的加载。

注意:

上面说了RDB快照的持久化,需要注意:在进行快照的时候(save),fork出来进行dump操作的子进程会占用与父进程一样的内存,真正的copy-on-write,对性能的影响和内存的耗用都是比较大的。比如机器8G内存,Redis已经使用了6G内存,这时save的话会再生成6G,变成12G,大于系统的8G。这时候会发生交换;要是虚拟内存不够则会崩溃,导致数据丢失。所以在用redis的时候一定对系统内存做好容量规划。

目前,通常的设计思路是利用Replication机制来弥补aof、snapshot性能上的不足,达到了数据可持久化。即Master上Snapshot和AOF都不做,来保证Master的读写性能,而Slave上则同时开启Snapshot和AOF来进行持久化,保证数据的安全性。

二、对Redis持久化的测试

通过上面的理论对snapshot和aof有了一定的理解,下面开始进行一些测试::
1、redis.conf 基本配置: 开启snapshot,关闭aof

 1 save 900 1
2 save 300 10
3 save 60 10000
4
5 rdbcompression no
6 rdbchecksum no
7 dbfilename zhoujy.rdb
8 dir /var/lib/redis
9
10 appendonly no

操作

 1 redis 127.0.0.1:6379> keys *                     #查看0库下是否有key
2 (empty list or set)
3 redis 127.0.0.1:6379> set name zhoujinyi #set操作
4 OK
5 redis 127.0.0.1:6379> set sex man
6 OK
7 redis 127.0.0.1:6379> set age 27
8 OK
9 redis 127.0.0.1:6379> keys *
10 1) "age"
11 2) "sex"
12 3) "name"
13 redis 127.0.0.1:6379>
14 zhoujy@zhoujy:~$ ls -lh /var/lib/redis/ #rdb文件初始化大小
15 总用量 4.0K
16 -rw-rw---- 1 redis redis 18 2013-05-25 16:19 zhoujy.rdb
17 zhoujy@zhoujy:~$ redis
18 redis 127.0.0.1:6379> save #保存,进行持久化,每执行一次save,会在日至里面记录一条:“ * DB saved on disk ”
19 OK
20 redis 127.0.0.1:6379>
21 zhoujy@zhoujy:~$ ls -lh /var/lib/redis/ #文件大小改变,数据写入文件进行了持久化
22 总用量 4.0K
23 -rw-rw---- 1 redis redis 52 2013-05-25 16:20 zhoujy.rdb
24
25 验证持久化,重启redis:
26
27 redis 127.0.0.1:6379> keys *
28 1) "name"
29 2) "age"
30 3) "sex"
31 redis 127.0.0.1:6379> set address hangzhou #key没有被保存就重启了
32 OK
33 redis 127.0.0.1:6379>
34 zhoujy@zhoujy:~$ sudo /etc/init.d/redis-server restart
35 Stopping redis-server: redis-server.
36 Starting redis-server: redis-server.
37 zhoujy@zhoujy:~$ redis
38 redis 127.0.0.1:6379> keys * #发现刚才没有被保存的key也被持久化了,怎么回事?
39 1) "name"
40 2) "address"
41 3) "sex"
42 4) "age"
43 redis 127.0.0.1:6379>
44
45 查看日志,看看日志里面有什么信息:
46
47 [21154] 25 May 16:28:12.122 # User requested shutdown...
48 [21154] 25 May 16:28:12.122 * Saving the final RDB snapshot before exiting.
49 [21154] 25 May 16:28:12.165 * DB saved on disk
50 [21154] 25 May 16:28:12.165 * Removing the pid file.
51 [21154] 25 May 16:28:12.165 * Removing the unix socket file.
52 [21154] 25 May 16:28:12.165 # Redis is now ready to exit, bye bye...
53
54 从日志里面得到了解释,正常关闭redis,他会自己在关闭前执行save命令。那异常关闭呢? 用kill的效果和上面一样,属于正常关闭。只能用kill -9 才行:
54
55 redis 127.0.0.1:6379> keys *
56 1) "age"
57 2) "name"
58 3) "sex"
59 4) "address"
60 redis 127.0.0.1:6379> set company dxy
61 OK
62 redis 127.0.0.1:6379> keys *
63 1) "name"
64 2) "sex"
65 3) "age"
66 4) "address"
67 5) "company"
68 redis 127.0.0.1:6379> #key没有被保存就重启了
69 zhoujy@zhoujy:~$ sudo kill -9 21250
70 zhoujy@zhoujy:~$ redis
71 Could not connect to Redis at 127.0.0.1:6379: Connection refused
72 not connected>
73 zhoujy@zhoujy:~$ sudo /etc/init.d/redis-server start
74 Starting redis-server: redis-server.
75 zhoujy@zhoujy:~$ redis
76 redis 127.0.0.1:6379> keys * #company没有被持久化,数据丢失,重启日志里没有“* DB saved on disk” 信息
77 1) "sex"
78 2) "age"
79 3) "address"
80 4) "name"
81 redis 127.0.0.1:6379>

从上面的结果看出,开启RDB持久化,在满足save条件、手动save、正常关闭的时候数据都会被持久化,而异常关闭终止的时候数据丢失。

2、redis.conf 基本配置: 关闭snapshot,关闭aof

1 #save 900 1
2 #save 300 10
3 #save 60 10000
4 rdbcompression no
5 rdbchecksum no
6 dbfilename zhoujy.rdb
7 dir /var/lib/redis
8
9 appendonly no

操作

 1 redis 127.0.0.1:6379> keys *                         #查看0库下是否有key
2 (empty list or set)
3 redis 127.0.0.1:6379> set name zhoujinyi #set操作
4 OK
5 redis 127.0.0.1:6379> set sex man
6 OK
7 redis 127.0.0.1:6379> set age 27
8 OK
9 redis 127.0.0.1:6379> save #保存,进行持久化,即使没有开始snapshot,执行save命令一样可以持久化,不手动的触发永远不会持久化。
10 OK #每执行一次save,会在日志里面记录一条:“ * DB saved on disk ”
11 redis 127.0.0.1:6379> set address hangzhou #set操作,但不save,正常重启
12 OK
13 redis 127.0.0.1:6379>
14 zhoujy@zhoujy:~$ sudo /etc/init.d/redis-server restart #正常重启
15 [sudo] password for zhoujy:
16 Stopping redis-server: redis-server.
17 Starting redis-server: redis-server.
18 zhoujy@zhoujy:~$ redis
19 redis 127.0.0.1:6379> keys * #发现刚才没有被保存的key丢失了
20 1) "sex"
21 2) "name"
22 3) "age"
23 redis 127.0.0.1:6379>

从上面的结果看出,关闭持久化,只有在手动save的时候数据都会被持久化,正常关闭的时候数据丢失。要是从一开始到关闭写入的数据没有手动save,则数据全部丢失!既然能手动save间接的说明了快照一直都存在,所以不能说是禁止snapshot,应该是禁止自动snapshot功能。

通过1,2验证了之前说的:一旦数据库出现问题,那么我们的RDB文件中保存的数据并不是全新的。

3、redis.conf 基本配置: 关闭snapshot,开启aof

 1 #save 900 1
2 #save 300 10
3 #save 60 10000
4
5 appendonly yes
6 appendfilename zhoujy.aof
7 # appendfsync always
8 appendfsync everysec
9 # appendfsync no
10
11 no-appendfsync-on-rewrite no
12 auto-aof-rewrite-min-size 64mb

操作

 1 #重启数据库之前有3个key:
2 redis 127.0.0.1:6379> keys *
3 1) "sex"
4 2) "age"
5 3) "name"
6 #修改开启AOF参数,重启数据库:
7 zhoujy@zhoujy:~$ ls -lh /var/lib/redis/
8 总用量 4.0K
9 -rw-r----- 1 redis redis 0 2013-05-25 17:41 appendonly.aof #aof持久化已经开启,0字节大小
10 -rw-rw---- 1 redis redis 52 2013-05-25 17:34 zhoujy.rdb
11
12 redis 127.0.0.1:6379> keys * #数据库里面没有记录?之前还有3个key,Why?
13 (empty list or set)
14 redis 127.0.0.1:6379>
15
16 #查看日志:
17 * DB loaded from append only file: 0.000 seconds
18 发现是从0字节的aof文件里面同步数据,为什么不同步rdb的数据?原来redis代码里面写好了优先级,AOF>RDB
19
20 redis.c里的代码如下:
21
22 void loadDataFromDisk(void) {
23 long long start = ustime();
24 if (server.aof_state == REDIS_AOF_ON) {
25 if (loadAppendOnlyFile(server.aof_filename) == REDIS_OK)
26 redisLog(REDIS_NOTICE,"DB loaded from append only file: %.3f seconds",(float)(ustime()-start)/1000000);
27 } else {
28 if (rdbLoad(server.rdb_filename) == REDIS_OK) {
29 redisLog(REDIS_NOTICE,"DB loaded from disk: %.3f seconds",
30 (float)(ustime()-start)/1000000);
31 } else if (errno != ENOENT) {
32 redisLog(REDIS_WARNING,"Fatal error loading the DB: %s. Exiting.",strerror(errno));
33 exit(1);
34 }
35 }
36 }

这里需要注意的是:当中途开启AOF,重启让他生效的时候,千万不能再让他第2次正常重启了。因为第一次重启让aof生效的时候,启动redis已经读取这个文件了,导致此时的redis数据为空的(优先级)。要是再重启的,则会把这个空的数据save到RDB文件,这样导致RDB原有的数据被替换,导致数据丢失。所以一定要小心,为了避免悲剧的发生,当要重启redis的时候最好都备份下RDB文件。

 1 redis 127.0.0.1:6379> keys *
2 (empty list or set)
3 redis 127.0.0.1:6379> set name zhoujinyi
4 OK
5 redis 127.0.0.1:6379> save
6 OK
7
8 #开启aof参数,重启redis生效(第一次重启)
9 root@m2:/var/lib/redis# /etc/init.d/redis-server restart
10 Stopping redis-server: redis-server stop!.
11 Starting redis-server: redis-server start!
12 root@m2:/var/lib/redis# ls -lh #生成aof文件,已经生效
13 总用量 4.0K
14 -rw-r----- 1 root root 0 5月 26 01:12 appendonly.aof
15 -rw-rw---- 1 root root 36 5月 26 01:12 dump.rdb
16
17 redis 127.0.0.1:6379> keys * #如上面所说的优先级原因:aof > rdb,结果为空
18 (empty list or set)
19
20 #再重启(第2次正常重启),把上面空的结果save到了RDB,数据丢失。此时的db是空的,日志记录 "* DB saved on disk"
21 root@m2:/var/lib/redis# /etc/init.d/redis-server restart
22 Stopping redis-server: redis-server stop!.
23 Starting redis-server: redis-server start!
24
25 root@m2:/var/lib/redis# ls -lh #数据已经被初始化了,数据丢失。
26 总用量 4.0K
27 -rw-r----- 1 root root 0 5月 26 01:12 appendonly.aof
28 -rw-rw---- 1 root root 18 5月 26 01:13 dump.rdb
29 redis 127.0.0.1:6379> keys *
30 (empty list or set)

这里就有一个问题,比如在用redis的时候,刚开始只开启RDB的持久方式,AOF没有开启,在跑一段时间之后想开启AOF,那如何把RDB的数据直接写到AOF文件呢?有2种方法:
①: 在开启AOF之前,先执行bgrewriteaof,再重启。

 1 redis 127.0.0.1:6379> keys *                   #查看是否有数据
2 (empty list or set)
3 redis 127.0.0.1:6379> set name zhoujinyi #生成数据
4 OK
5 redis 127.0.0.1:6379> set sex man
6 OK
7 redis 127.0.0.1:6379> set age 27
8 OK
9 redis 127.0.0.1:6379> keys *
10 1) "name"
11 2) "sex"
12 3) "age"
13 redis 127.0.0.1:6379> bgsave #保存数据
14 Background saving started
15 redis 127.0.0.1:6379> keys *
16 1) "name"
17 2) "sex"
18 3) "age"
19 root@m2:/var/lib/redis# ls -lh #只有一个RDB文件,没有AOF文件
20 总用量 4.0K
21 -rw-rw---- 1 root root 52 5月 25 23:48 dump.rdb
22
23 redis 127.0.0.1:6379> bgrewriteaof #执行合并重写功能,生成AOF文件
24 Background append only file rewriting started
25
26 root@m2:/var/lib/redis# ls -lh #AOF文件生成成功
27 总用量 8.0K
28 -rw-rw---- 1 root root 122 5月 25 23:49 appendonly.aof
29 -rw-rw---- 1 root root 52 5月 25 23:48 dump.rdb
30 #这时候去打开redis.conf 文件中的aof参数(appendonly yes),重启生效。
31 root@m2:/var/lib/redis# /etc/init.d/redis-server restart
32 Stopping redis-server: redis-server stop!
33 Starting redis-server: redis-server start!
34
35 #日志里面出现:* DB loaded from append only file: 0.000 seconds
36
37 redis 127.0.0.1:6379> keys * #数据还在
38 1) "sex"
39 2) "name"
40 3) "age"

②: 利用CONFIG GET/SET 的方法动态修改配置文件,和①比少了重启的操作。

 1 redis 127.0.0.1:6379> set name zhoujinyi
2 OK
3 redis 127.0.0.1:6379> set sex man
4 OK
5 redis 127.0.0.1:6379> set age 27
6 OK
7 redis 127.0.0.1:6379> keys *
8 1) "age"
9 2) "name"
10 3) "sex"
11 redis 127.0.0.1:6379> BGSAVE
12 Background saving started
13 redis 127.0.0.1:6379>
14
15 root@m2:/var/lib/redis# ls -lh #只有rdb文件
16 总用量 4.0K
17 -rw-rw---- 1 root root 52 5月 26 00:09 dump.rdb
18
19 #动态修改参数,把aof功能开启:appendonly yes
20
21 redis 127.0.0.1:6379> CONFIG GET append* #在线查看参数
22 1) "appendonly"
23 2) "no"
24 3) "appendfsync"
25 4) "everysec"
26 redis 127.0.0.1:6379> CONFIG SET appendonly yes #动态修改参数
27 OK
28 redis 127.0.0.1:6379> CONFIG GET append*
29 1) "appendonly"
30 2) "yes"
31 3) "appendfsync"
32 4) "everysec"
33 redis 127.0.0.1:6379>
34
35 root@m2:/var/lib/redis# ls -lh #aof文件已经生成,并且有数据(同步rdb)。
36 总用量 8.0K
37 -rw-rw---- 1 root root 122 5月 26 00:10 appendonly.aof
38 -rw-rw---- 1 root root 52 5月 26 00:09 dump.rdb
39
40 #日志里面的信息:* Background append only file rewriting started by pid 3165
41 #因为参数是动态修改的,在重启之后会失效,所以在维护的时候修改redis.conf文件的参数即可。

从上面的结果看出,redis读取aof的文件要先于rdb文件,所以尽量一开始开启aof选项,不要在中途开启。通过日志可以很清楚的知道redis通过那个文件来取数据的:
RDB:   * DB loaded from disk: 0.000 seconds
AOF: * DB loaded from append only file: 0.000 seconds
保存数据则是:
RDB:* DB saved on disk
AOF:  * Calling fsync() on the AOF file.

4、redis.conf 基本配置: 开启snapshot,开启aof

 1 save 900 1
2 save 300 10
3 save 60 10000
4
5 appendonly yes
6 appendfilename zhoujy.aof
7 # appendfsync always
8 appendfsync everysec
9 # appendfsync no
10
11 no-appendfsync-on-rewrite no
12 auto-aof-rewrite-min-size 64mb

操作

 1 #同时开启这2个参数,在日志里面会记录:
2 * Calling fsync() on the AOF file.
3 * DB saved on disk
4
5 redis 127.0.0.1:6379> keys *
6 (empty list or set)
7 redis 127.0.0.1:6379> set name zhoujinyi
8 OK
9 redis 127.0.0.1:6379> set age 27
10 OK
11 redis 127.0.0.1:6379> set sex man
12 OK
13 redis 127.0.0.1:6379> keys *
14 1) "name"
15 2) "age"
16 3) "sex"
17
18 root@m2:/var/lib/redis# ls -lh #aof,rdb 2个文件已经生成,并且aof文件大小根据操作命令实时增加,而rbd需要手动save或则到了刷写机制的阀值才增加
19 总用量 8.0K
20 -rw-r----- 1 root root 122 5月 26 00:39 appendonly.aof
21 -rw-rw---- 1 root root 18 5月 26 00:37 dump.rdb
22
23 redis 127.0.0.1:6379> save #保存快照
24 OK
25
26 root@m2:/var/lib/redis# ls -lh #rdb文件大小增加
27 总用量 8.0K
28 -rw-r----- 1 root root 136 5月 26 00:41 appendonly.aof
29 -rw-rw---- 1 root root 52 5月 26 00:41 dump.rdb
30
31 redis 127.0.0.1:6379> flushall #清除所有数据
32 OK
33
34 root@m2:/var/lib/redis# ls -lh #数据清除之后,rdb文件大小初始化了,而aof文件却增加了,Why?
35 总用量 8.0K
36 -rw-r----- 1 root root 154 5月 26 00:43 appendonly.aof
37 -rw-rw---- 1 root root 18 5月 26 00:43 dump.rdb
38 #原来aof文件记录的是修改数据的操作,所以文件是追加形式的,flushall命令被追加到最后。
39
40 root@m2:/var/lib/redis# /etc/init.d/redis-server restart #重启,看看通过aof的载入能否被读取到?
41 Stopping redis-server: redis-server stop!.
42 Starting redis-server: redis-server start!
43 root@m2:/var/lib/redis# ls -lh #aof文件大小不变,重启不能初始化aof文件
44 总用量 8.0K
45 -rw-r----- 1 root root 154 5月 26 00:43 appendonly.aof
46 -rw-rw---- 1 root root 18 5月 26 00:45 dump.rdb
47
48 redis 127.0.0.1:6379> keys * #日志里面记录“* DB loaded from append only file: 0.012 seconds”,但没有数据,说明aof确实被初始化了。
49 (empty list or set)
50
51 #因为数据都已经被清除了,想让aof文件大小也初始化掉,该如何操作呢?
52 很简单:
53 redis 127.0.0.1:6379> bgrewriteaof #让aof合并重写,因为aof文件的最后一条记录的flushall操作,前面的记录都无效了,合并所有操作之后就初始化了。
54 Background append only file rewriting started
55 redis 127.0.0.1:6379>
56
57 root@m2:/var/lib/redis# ls -lh #aof文件被初始化
58 总用量 4.0K
59 -rw-rw---- 1 root root 0 5月 26 00:51 appendonly.aof
60 -rw-rw---- 1 root root 18 5月 26 00:45 dump.rdb

通过上面的这些测试,已经说明RDB和AOF他们的操作方式,以及如重启时的载入,重启时将按照以下优先级恢复数据到内存:
 •如果只配置AOF,重启时加载AOF文件恢复数据。
 •如果同时 配置了RBD和AOF,启动是只加载AOF文件恢复数据。
 •如果只配置RBD,启动是讲加载dump文件恢复数据。

为了防止悲剧的发生,我们应该进行备份。

三、对Redis备份

备份很简单,只需要把RDB,AOF的文件复制备份起来就可以了。相同版本的备份文件可以任意使用。不同版本没有试过。

 1 #redisA: A上生成测试数据
2 redis 127.0.0.1:6379> set name zhoujinyi
3 OK
4 redis 127.0.0.1:6379> set sex man
5 OK
6 redis 127.0.0.1:6379> set age 17
7 OK
8 redis 127.0.0.1:6379> keys *
9 1) "age"
10 2) "name"
11 3) "sex"
12 redis 127.0.0.1:6379> bgsave
13 Background saving started
19 #redisB: B上没有数据
20 redis 127.0.0.1:6380> keys *
21 (empty list or set)
22
23 #复制A的文件到B(rdb和aof文件)
24 cp redis/* redis2/
25 #修改权限
26 chown -R redis.redis *
27 #重启B
28 zhoujy@m2:~$ redis -p 6380 shutdown
29 zhoujy@m2:~$ redis -p 6380
30 #还原成功
31 redis 127.0.0.1:6380> keys *
32 1) "sex"
33 2) "name"
34 3) "age"

以上完成。

Redis持久化磁盘IO方式及其带来的问题   有Redis线上运维经验的人会发现Redis在物理内存使用比较多,但还没有超过实际物理内存总容量时就会发生不稳定甚至崩溃的问题,有人认为是基于快照方式持的更多相关文章

  1. Redis持久化磁盘IO方式及其带来的问题

    有Redis线上运维经验的人会发现Redis在物理内存使用比较多,但还没有超过实际物理内存总容量时就会发生不稳定甚至崩溃的问题 一.对Redis持久化的探讨与理解 redis是一个支持持久化的内存数据 ...

  2. 百万级运维心得一:Mongodb和Redis数据不能放在同一个服务器

    百万级运维经验一:Mongodb和Redis数据不能放在同一个服务器 一开始时,为了省服务器,把Mongodb和Redis放在一个服务器上.网站每到高峰期都特别卡,还经常出现502.找了很久的原因,发 ...

  3. 简述C#中IO的应用 RabbitMQ安装笔记 一次线上问题引发的对于C#中相等判断的思考 ef和mysql使用(一) ASP.NET/MVC/Core的HTTP请求流程

    简述C#中IO的应用   在.NET Framework 中. System.IO 命名空间主要包含基于文件(和基于内存)的输入输出(I/O)服务的相关基础类库.和其他命名空间一样. System.I ...

  4. 高级运维(六):源码安装Redis缓存服务、常用Redis数据库操作指令、配置Redis主从服务器

    一.源码安装Redis缓存服务 目标: 本案例要求先快速搭建好一台Redis服务器,并测试该缓存服务器: 1> 设置变量test,值为123 2> 查看变量test的值 3> 设置计 ...

  5. JAVA项目从运维部署到项目开发(三.Redis)

    一.Redis的介绍 Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API.它通常被称为数据结构服务器,因为值(va ...

  6. redis持久化,主从及数据备份

    http://blog.csdn.net/lang_man_xing/article/details/38386113 现在在项目里已经大量使用redis了,为了提高redis的性能和可靠性我们需要知 ...

  7. Redis学习——Redis持久化之AOF备份方式保存数据

    新技术的出现一定是在老技术的基础之上,并且完善了老技术的某一些不足的地方,新技术和老技术就如同JAVA中的继承关系.子类(新技术)比父类(老技术)更加的强大! 在前面介绍了Redis学习--Redis ...

  8. redis持久化的方式RDB 和 AOF

    redis持久化的方式RDB 和 AOF 一.对Redis持久化的探讨与理解 目前Redis持久化的方式有两种: RDB 和 AOF 首先,我们应该明确持久化的数据有什么用,答案是用于重启后的数据恢复 ...

  9. Redis持久化实践及灾难恢复模拟

    参考资料: Redis Persistence http://redis.io/topics/persistence Google Groups https://groups.google.com/f ...

随机推荐

  1. [Machine Learning & Algorithm]CAML机器学习系列1:深入浅出ML之Regression家族

    声明:本博客整理自博友@zhouyong计算广告与机器学习-技术共享平台,尊重原创,欢迎感兴趣的博友查看原文. 符号定义 这里定义<深入浅出ML>系列中涉及到的公式符号,如无特殊说明,符号 ...

  2. 把java对象转化为json格式的对象数组

  3. 转 powerdesigner12&period;5在64位JDK下连接mysql数据库问题

    前因:由于项目在研发的过程中,数据库字段需要不停的增加和修改,导致最初设计的数据库原型无法使用,后来就想到用powerdesinger来反转数据库表结构. 环境:win7 64位系统,本机装有64位j ...

  4. Java EE开发平台随手记6——Mybatis扩展4

    这篇博客中来说一下对Mybatis动态代理接口方式的扩展,对于Mybatis动态代理接口不熟悉的朋友,可以参考前一篇博客,或者研读Mybatis源码. 扩展11:动态代理接口扩展 我们知道,真正在My ...

  5. &lbrack;BZOJ2797&rsqb;&lbrack;Poi2012&rsqb;Squarks

    2797: [Poi2012]Squarks Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 211  Solved: 89[Submit][Status ...

  6. Java之线程———GUI线程(包含打字游戏和计时器俩个GUI实列)

    当java程序包含图形用户界面(GUI)时,Java虚拟机在运行应用程序时会自动启动更多的线程,其中有两个重要的线程:AWT-EventQuecue 和 AWT-Windows. AWT-EventQ ...

  7. MySQL学习笔记一

    MySQL 学习笔记 一 一.数据库简单介绍 1. 按照数据库的发展时间顺序,主要出现了以下类型数据库系统: Ø 网状型数据库 Ø 层次型数据库 Ø 关系型数据库 Ø 面向对象数据库 上面4中数据库系 ...

  8. Linux 高性能服务器编程——socket选项

    socket选项函数 功能:用来读取和设置socket文件描述符属性的方法 函数: #include <sys/scoket.h> int getsockopt ( int sockfd, ...

  9. corel

    corel CorelDRAW X6 Corel CorelCAD 2017 32位/64位破解版

  10. 反射入门-浅谈反射用途&lowbar;根据Ado游标对象创建list集合

    本人大二菜鸟一只,今天在上课期间有个同学看着C#反射的内容说反射没什么用,一时之间也想不到什么更好的例子,就写了个根据泛型类型和游标反射创建List集合的Demo. 首先创建一个用于封装对应数据的en ...