持久化

概述:

持久化的目的:
1)将内存中的数据存储到硬盘的一个主要原因是为了在之后重用数据
2)防止系统故障而将数据备份到一个远程位置
3)存储在Redis 里面的数据有可能是经过长时间计算得出的,所以用户会希望自己可以将这些数据存储起来以便之后使用,这样就不必再重新计算了

持久化的方式:
概述:
Redis提供了AOF和RDB两种方式,两者可单独使用也可以结合使用,同时使用时重新启动Redis后Redis会使用AOF文件来恢复数据,因为AOF方式的持久化可能丢失的数据更少

RDB(快照方式):

当满足一定条件时Redis会自动将内存中的所有数据进行快照并存储在硬盘上。进行快照的条件可以由用户在配置文件中自定义,由两个参数构成:时间和改动的键的个数。当在指定的时间内被更改的键的个数大于指定的数值时就会进行快照。RDB是Redis默认采用的持久化方式,在配置文件中已经预置了3个条件:

 save 900 1

save 300 10

save 60 10000

save参数指定了快照条件,可以存在多个条件,条件之间是“或”的关系。如上所说,save 900 1的意思是在15分钟(900秒钟)内有至少一个键被更改则进行快照。如果想要禁用自动快照,只需要将所有的save参数删除即可。
Redis默认会将快照文件存储在当前目录的dump.rdb文件中,可以通过配置dir和dbfilename两个参数分别指定快照文件的存储路径和文件名。

快照的实现过程:
(1)Redis使用fork函数复制一份当前进程(父进程)的副本(子进程);
(2)父进程继续接收并处理客户端发来的命令,而子进程开始将内存中的数据写入硬盘中的临时文件;
(3)当子进程写入完所有数据后会用该临时文件替换旧的RDB文件,至此一次快照操作完成。
在执行fork的时候操作系统(Unix操作系统)会使用写时复制(copy-on-write)策略,即fork函数发生的一刻父子进程共享同一内存数据,当父进程要更改其中某片数据时(如执行一个写命令),操作系统会将该片数据复制一份以保证子进程的数据不受影响,所以新的RDB文件存储的是执行fork一刻的内存数据。
通过上述过程可以发现Redis在进行快照的过程中不会修改RDB文件,只有快照结束后才会将旧的文件替换成新的,也就是说任何时候RDB文件都是完整的。这使得我们可以通过定时备份RDB文件来实现Redis数据库备份。RDB文件是经过压缩(可以配置rdbcompression参数以禁用压缩节省CPU占用)的二进制格式,所以占用的空间会小于内存中的数据大小,更加利于传输。

触发方式:
除了自动快照,还可以手动发送SAVEBGSAVE命令让Redis执行快照,两个命令的区别在于,前者是由主进程进行快照操作,会阻塞住其他请求,后者会通过fork子进程进行快照操作。
Redis启动后会读取RDB快照文件,将数据从硬盘载入到内存。根据数据量大小与结构和服务器性能不同,这个时间也不同。通常将一个记录一千万个字符串类型键、大小为1GB的快照文件载入到内存中需要花费20~30秒钟。

错误处理:
默认情况下,如果Redis在后台生成快照的时候失败,那么就会停止接收数据,目的是让用户能知道数据没有持久化成功。但是如果你有其他的方式可以监控到Redis及其持久化的状态,那么可以把这个功能禁止掉。

stop-writes-on-bgsave-error yes

优点:
1)RDB的性能很好,需要进行持久化时,主进程会fork一个子进程出来,然后把持久化的工作交给子进程,自己不会有相关的I/O操作。
2)比起AOF,在数据量比较大的情况下,RDB的启动速度更快。
3)你可以设定一个时间点对RDB文件进行归档,这样就能在需要的时候很轻易的把数据恢复到不同的版本。
缺点:
1)RDB容易造成数据的丢失。会丢失从上次产生快照到Redis出现问题这段时间的数据。
2)RDB使用fork()产生子进程进行数据的持久化,如果数据比较大的话可能就会花费点时间,造成Redis停止服务几毫秒。如果数据量很大且CPU性能不是很好的时候,停止服务的时间甚至会到1秒。

AOF(append only file):

AOF 持久化会将被执行的写命令写到AOF 文件的末尾,以此来记录数据发生的变化。因此, Redis 只要从头到尾重新执行一次AOF 文件包含的所有写命令,就可以恢复AOF 文件所记录的数据。

默认情况下Redis没有开启AOF方式的持久化,可以通过appendonly参数开启: appendonly yes 开启AOF持久化后每执行一条会更改Redis中的数据的命令,Redis就会将该命令写入硬盘中的AOF文件。AOF文件的保存位置和RDB文件的位置相同,都是通过dir参数设置的,默认的文件名是appendonly.aof,可以通过appendfilename参数修改:appendfilename appendonly.aof

AOF实现过程:
假设在开启AOF持久化的情况下执行了如下4个命令:SET foo 1
 SET foo 2
 SET foo 3
 GET foo
Redis会将前3条命令写入AOF文件中,然而这时有一个问题是前2条命令其实都是冗余的,因为这两条的执行结果会被第三条命令覆盖。随着执行的命令越来越多,AOF文件的大小也会越来越大,即使内存中实际的数据可能并没有多少。很自然地,我们希望Redis可以自动优化AOF文件,就上例而言,就是将前两条无用的记录删除,只保留第三条。实际上Redis也正是这样做的,每当达到一定条件时Redis就会自动重写AOF文件,这个条件可以在配置文件中设置: auto-aof-rewrite-percentage 100
 auto-aof-rewrite-min-size 64mb
auto-aof-rewrite-percentage
参数的意义是当目前的AOF文件大小超过上一次重写时的AOF文件大小的百分之多少时会再次进行重写,如果之前没有重写过,则以启动时的AOF文件大小为依据。
auto-aof-rewrite-min-size
参数限制了允许重写的最小AOF文件大小,通常在AOF文件很小的情况下即使其中有很多冗余的命令我们也并不太关心。除了让Redis自动执行重写外,我们还可以主动使用BGREWRITEAOF命令手动执行AOF重写。

BGREWRITEAOF的工作原理和BGSAVE创建快照的工作原理非常相似:Redis会创建一个子进程,然后由子进程负责对AOF文件进行重写。因为AOF文件重写也需要用到子进程,所以快照持久化因为创建子进程而导致的性能问题和内存占用问题,在AOF持久化中也同样存在。更糟糕的是,如果不加以控制的话,AOF文件的体积可能会比快照文件的体积大好几倍,在进行AOF重写并删除旧AOF文件的时候,删除一个体积达到数十GB大的旧AOF文件可能会导致操作系统挂起(hang)数秒。所以需要上述两个条件很重要

文件同步 在向硬盘写入文件时,至少会发生3件事。当调用file.write()方法对文件进行写入时,写入的内容首先会被存储到缓冲区,然后操作系统会在将来的某个时候将缓冲区存储的内容写入硬盘,而数据只有在被写入硬盘之后,才算是真正地保存到了硬盘里面。用户可以通过调用file.flush()方法来请求操作系统尽快地将缓冲区存储的数据写入硬盘里,但具体何时执行写入操作仍然由操作系统决定。除此之外,用户还可以命令操作系统将文件同步(sync)到硬盘,同步操作会一直阻塞直到指定的文件被写入硬盘为止。当同步操作执行完毕之后,即使系统出现故障也不会对被同步的文件造成任何影响。

appendfsync选项及同步频率:

always 每个Redis 写命令都要同步写入硬盘。这样做会严重降低Redis 的速度
every sec 每秒执行一次同步,显式地将多个写命令同步到硬盘
no 让操作系统来决定应该何时进行同步


为了兼顾数据安全和写入性能,用户可以考虑使用appendfsync everysec选项,让Redis以每秒一次的频率对AOF文件进行同步。Redis每秒同步一次AOF文件时的性能和不使用任何持久化特性时的性能相差无几,而通过每秒同步一次AOF文件,Redis可以保证,即使出现系统崩溃,用户也最多只会丢失一秒之内产生的数据。当硬盘忙于执行写入操作的时候,Redis还会优雅地放慢自己的速度以便适应硬盘的最大写入速度。

数据损坏修复:

如果因为某些原因(例如服务器崩溃)AOF文件损坏了,导致Redis加载不了,可以通过以下方式进行修复:
备份AOF文件。
使用redis-check-aof命令修复原始的AOF文件:

$ redis-check-aof --fix

可以使用diff -u命令看下两个文件的差异,使用修复过的文件重启Redis服务。

数据备份:
无论是使用AOF持久化还是快照持久化,将数据持久化到硬盘上都是非常有必要的,但除了进行持久化之外,用户还必须对持久化所得的文件进行备份(最好是备份到多个不同的地方),这样才能尽量避免数据丢失事故发生。如果条件允许的话,最好能将快照文件和最新重写的AOF文件备份到不同的服务器上面。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值