一、对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文件。
Client 也可以使用save或者bgsave命令通知redis做一次快照持久化。save操作是在主线程中保存快照的,由于redis是用一个主线程来处理所有 client的请求,这种方式会阻塞所有client请求。所以不推荐使用。另一点需要注意的是,每次快照持久化都是将内存数据完整写入到磁盘一次,并不 是增量的只同步脏数据。如果数据量大的话,而且写操作比较多,必然会引起大量的磁盘io操作,可能会严重影响性能。
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就一定会有内存快照发生。
快照持久化过程:
1.redis调用fork,现在有了子进程和父进程。 2.父进程继续处理client请求,子进程负责将内存内容写入到临时文件。由于os的写时复制机制(copy on write)父子进程会共享相同的物理页面,当父进程处理写请求时os会为父
进程要修改的页面创建副本,而不是写共享的页面。所以子进程的地址空间内的数 据是fork时刻整个数据库的一个快照。 3.当子进程将快照写入临时文件完毕后,用临时文件替换原来的快照文件,然后子进程退出。
不足:就是一旦数据库出现问题,那么我们的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
上面提出了RDB持久化的不足,要是不允许数据丢失,则需要用AOF来持久化。
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文件。
AOF持久化过程:
1. redis调用fork ,现在有父子两个进程 2. 子进程根据内存中的数据库快照,往临时文件中写入重建数据库状态的命令 3.父进程继续处理client请求,除了把写命令写入到原来的aof文件中。同时把收到的写命令缓存起来。这样就能保证如果子进程重写失败的话并不会出问题。 4.当子进程把快照内容写入已命令方式写到临时文件中后,子进程发信号通知父进程。然后父进程把缓存的写命令也写入到临时文件。 5.现在父进程可以使用临时文件替换老的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操作都是顺序IO操作,性能都很高。而同时在通过RDB文件或者AOF日志进行数据库恢复的时候,也是顺序的读取数据加载到内存中。所以也不会造成磁盘的随机读。
到底选择什么呢?下面是来自官方的建议:
通常,如果你要想提供很高的数据保障性,那么建议你同时使用两种持久化方式。如果你可以接受灾难带来的几分钟的数据丢失,那么你可以仅使用RDB。
很多用户仅使用了AOF,但是我们建议,既然RDB可以时不时的给数据做个完整的快照,并且提供更快的重启,所以最好还是也使用RDB。
在数据恢复方面:
RDB的启动时间会更短,原因有两个:
一是RDB文件中每一条数据只有一条记录,不会像AOF日志那样可能有一条数据的多次操作记录。所以每条数据只需要写一次就行了。
另一个原因是RDB文件的存储格式和Redis数据在内存中的编码格式是一致的,不需要再进行数据编码工作,所以在CPU消耗上要远小于AOF日志的加载。
注意:
上面说了RDB快照的持久化,需要注意:在进行快照的时候(save),fork出来进行dump操作的子进程会共享父进程的内存(真正的copy-on-write)。比如机器8G内存,Redis已经使用了6G内存,这时新操作100M的内存,save的话会再多生成100M(放到缓冲区里),总共进行RDB的时候会多出100M,既6.1G的内存。
目前,通常的设计思路是利用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>
总结1:从上面的结果看出,开启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>
总结2: 从上面的结果看出,关闭持久化,只有在手动save的时候数据都会被持久化,正常关闭的时候数据丢失。要是从一开始到关闭写入数据的期间没有手动save,则数据全部丢失!既然能手动save间接的说明了快照一直都存在,所以不能说是禁止snapshot,应该是禁止自动snapshot功能。
通过1,2验证了之前说的:一旦数据库出现问题,那么我们的RDB文件中保存的数据并不是全新的,下面看看AOF。
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文件的参数即可。
总结3: 从上面的结果看出,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"
以上完成。