在redis中,我们可以在特定时间点进行内存拷贝来创建快照,在创建完毕之后,这个快着能够回退,还可以拷贝到其他机器甚至是机器的重启。
快照会被写入在配置文件中配置的文件中,并存储在dir目录中,在执行下一个快照前,如果redis或者硬件或者系统导致崩溃,那么数据会从最新的redis快照中进行恢复。
这里举个例子就是说我们有一台redis机器,下午2:35内存中有10G的缓存,然后现在已经完成了快照操作,新的快照在3:06启动,在下午3:08完成之前,我们需要更新35个数据。但是在这期间如果系统奔溃,那么下午2:35之后的所有数据都讲丢失。而如果当前快照完成了话,那么仅仅会丢失这35个数据。
这块有五个方法进行快照执行
1.任何redis客户端都可以通过bgsave命令来初始化一个快照(window平台除外),这个命令会创建一个子线程去将快照写入磁盘,并且对主线程没有任何影响。
2.reids客户端同样可以蚕蛹save命令初始化一个快照,这个命令能够让redis停止执行接受到的命令,直到快照完成之后。这个命令不常用,除非我们需要我们的数据在磁盘上,或者我们可以等待redis在一定时间内不执行命令,或者我们没有足够的内存去执行bgsave命令。
3.如果在redis中配置了保存行,比如save 60 10000,那么如果在上次成功保存之后60秒内发生10000次写入,那么 redis就会自动触发bgsave。但存在多个保存行,只要一个规则匹配,就会触发bgsave。
4.当redis接受shutdown命令或者收到term命令,redis将执行save命令,然后阻止客户端的命令执行。save执行完毕之后就关闭。
5.当redis服务连接到其他redis服务进行sync同步命令,进行复制。如果其中的命令还没有执行或者完成,那么redis将开始进行bgsave命令。
当我们使用快照的方式进行持久化,那么我们不可避免的会存在最新快照到故障时刻的数据丢失的问题,对于某些应用来说,数据丢失是不能容忍的,这时候我们可以采用aof去持久化。但是如果应用可以允许数据丢失,那么快照也行的。
redis快照采用的fork的方式将内存进行拷贝,然后进行快照存储,因此如果缓存的数据很大,比如数十G,那么内存的压力就会很大,就会导致进程采用虚拟内存,这样会降低redis的性能,降低redis的响应时间。一般情况下,硬件或者虚拟机每G的fork大概需要10-20ms,所以说如果是20G的redis数据进行快照bgsave,那么将会产生20*(10-20)ms=200ms-400ms的暂停。
因为采用bgsave会导致内存复制的时间延迟,因此我们可以采用save指令,但是save指令因为是客户端阻塞的,因此不能执行其他的命令。所以快照完成的速度会更快。
本书的作者也提到了他们在68G的虚拟机上运行近50G数据的redis去检测bgsave和save的差别,bgsave的内存拷贝需要15秒甚至更多。15-20分钟才能完成整个快照的保存。但是使用save去完成快照只需要3-5分钟。