大数据
在Redis存储的数据量只有几个GB的时候,使用快照来保存数据是没有问题的。Redis会创建子进程并将数据保存到硬盘里面,生成快照需要的时间比你读这句话的时间还要短。三随着Redis占用的内存越来越多,bgsave在创建子进程时耗费的时间越来越多。如果Redis的内存占用量达到数十个GB,并且剩余的空闲内存并不多,或者Redis运行在虚拟机上面,那么执行bgsave可能会导致系统长时间地停顿,也可能引发系统大量地使用虚拟内存,从而导致Redis的性能降低至无法使用的程度。
执行bgsave而导致的挺短时间有多长取决于Redis所在的系统:对于真实的硬件,vmware虚拟机或者KVM虚拟机来说,Redis进行每占用一个GB的内存,创建该进程的子进程所需的时间就要增加10~20毫秒,而对于Xen虚拟机来说,根究配置的不同,Redis进程每占用一个GB的内存,创建该进程的子进程所需的时间就要增加200~300毫秒。因此,如果我们的Redis进程占用了20GB的内存,那么在标准硬件上运行bgsave所创建的子进程将导致Reeis停顿200~400毫秒,如果我们使用的是Xen虚拟机(亚马逊EC2和其他几个云计算供应商都使用这种虚拟机),那么相同的创建子进程操作将导致Redis停顿4~6秒。用户必须考虑自己的应用程序能否接受这种停顿。
为了防止Redeis因为创建子进程而出现停顿,我们可以考虑关闭自动保存呢,转而通过手动发送bgsave或者save来进行持久化。手动发送bgsave一样会引起停顿,唯一不同的是用户可以控制停顿出现的时间。另一方面,虽然save会一直阻塞Redis知道快照生产完毕,但是因为它不需要创建子进程,所以就不会想bgsave一样因为创建子进程而导致Redis停顿;并且因为没有子进程在争抢资源,所以save创建快照的速度比bgsave创建快照的速度要快一些。
根据个人经验,在一台拥有68GB内存的Xen虚拟机上面,对一个占用50GB内存的Redis服务器执行bgsave命令的话,光是创建子进程就需要花费15秒以上,而生成快照则需要花费15~20分钟;但使用save值需要3~5分钟就可以完成快照的生成工作。因为的应用程序只需要每天生成一次快照,所以我写了一个脚本,让它在每天凌晨3点停止所有客户端对Redis的访问,调用save命令并等待该命令执行完毕,之后备份刚刚生成的快照文件,并通知客户端继续执行操作。
如果用户能够妥善地处理快照持久化可能会带来的大量数据丢失,那么快照持久化对用户来说将使一个不错的选择,但对于很多用于程序来说,丢失15分钟、1小时甚至更长时间的数据都是不可接受的,在这种情况情况下,我们可以使用AOF持久化来将存储在内存里面的数据尽快的保存到硬盘里面。