Redis的读写都是在内存中进行的,所以它的性能很高。而当我们的服务器断开或者重启的时候,数据就会消失,那我们怎么解决这个问题呢?其实Redis已经为我们提供了一种持久化机制,就是RDB和AOF。快下来跟我一起看看这两个小技巧是如何保证数据持久化的吧。持久化由于Redis是一个基于内存的数据库,当服务器出现故障时,我们的数据将不安全。这时候就需要将内存中的数据存储到磁盘中。当我们的服务器重启的时候,可以通过磁盘恢复数据。这个过程称为Redis持久化。RedisPersistentRDB介绍RDB的全称是RedisDatabaseBackupfile(Redis数据备份文件),也可以称为Redis数据快照。RDB文件是一个压缩的二进制文件(默认:dump.rdb);RDB文件保存在硬盘中;通过在数据库中保存键值对来记录数据库状态。在创建Redis持久化时,程序会将当前内存中的数据库状态保存到磁盘中。有两个主要的Redis命令用于创建RDB文件:SAVE和BGSAVE。SAVE是一个同步操作。命令执行时,Redis服务器进程会被阻塞,客户端发送的命令请求会被拒绝。代码示例:defSAVE():#CreateRDBfilerdbSave()图:保存命令BGSAVE异步操作。命令执行时,子进程执行保存工作,服务端可以继续让主线程处理客户端发送的命令请求。代码示例:defBGSAVE():#创建子进程pid=fork()ifpid==0:#子进程负责创建RDB文件rdbSave()#完成后向父进程发送信号signal_parent()elifpid>0:#父进程继续通过循环处理命令请求并等待子进程的信号在加载RDB文件的过程中,加载服务器会被阻塞,直到加载工作完成。主要设置Redis通过设置服务器配置的保存选项,允许用户每隔一段时间自动执行BGSAVE命令。设置保存条件提供配置如下:save9001save30010在这种情况下,只要满足以下条件之一,就会执行BGSAVE命令:服务器在900秒内至少对数据库进行了一次修改;服务器在300秒内修改了数据库,期间至少对数据库进行了10次修改。saveparams服务器程序会根据save选项设置的保存条件设置服务器状态redisServer结构体的saveparams属性。saveparams属性是一个数组;数组中的每个元素都是一个saveparam结构;每个saveparam结构都包含由保存选项设置的保存条件。structsaveparam{//秒数time_tseconds;//修改次数intchanges;}dirtydirty计数器记录自上次成功执行SAVE命令以来服务器修改数据库状态的次数(包括写入、删除、更新等)或BGSAVE命令。lastsave是一个UNINX时间戳,记录服务器最后一次成功执行SAVE命令或BGSAVE命令的时间。检查是否满足保存条件。服务器周期性运行函数serverCron(该函数维护正在运行的服务器)默认每100毫秒执行一次。其中一项任务是检查是否满足保存选项设置的保存条件。如果是,请执行BGSAVE命令。代码示例:defserverCron():#....#遍历所有保存条件forsaveparaminserver.saveparams:#计算自上次保存操作以来经过了多少秒save_interval=unixtime_now()-server.lastsave#如果更改次数为databasestateexceedstheconditionthetimesset#如果距离上次保存的时间超过条件设置的时间ifserver.dirty>=saveparam.changesandsave_interval>saveparam.seconds:BGSAVE()默认配置RDB文件的默认配置如下:################################SNAPSHOTTING####################################SavetheDBondisk:#在给定的秒数和给定的数据库写操作次数下,自动持久化操作。#save#save9001save30010save6010000#bgsave出错时是否停止写入,一般是stop-writes-on-bgsave-erroryes#持久化时是否使用LZF压缩字符串对象?rdbcompressionyes#是否对rdb文件进行Checksum校验,一般为yesrdbchecksumyes#RDB持久化文件名dbfilenamedump.rdb#持久化文件存放目录dir./AOF简介AOF的全称是AppendOnlyFile(追加日志文件)。日志是后写日志,Redis先执行命令,将数据写入内存,然后记录日志。写后日志通过保存Redis服务器执行的写命令来记录数据库的状态;所有写入AOF文件的命令都以Redis的命令请求协议格式保存。AOF持久化过程的实现主要是通过以下过程实现的:AOF过程commandappend如果开启了AOF持久化功能,服务器执行一个命令后,会将执行的写命令以协议格式追加到服务器状态中aof_buf缓冲区的末尾。在文件同步服务器结束事件循环之前,它会调用flushAppendOnlyFile函数。该函数会考虑是否需要将aof_buf缓冲区的内容写入并保存到AOF文件中。flushAppendOnlyFile函数执行如下过程:WRITE:根据条件,将aof_buf中的buffer写入AOF文件;SAVE:根据条件,调用fsync或fdatasync函数将AOF文件保存到磁盘。该函数受服务端配置的appendfsync三个值的影响:always、everysec、no,又称为三种策略。Always的每条命令都会fsync到硬盘,这样redis写入的数据就不会丢失。Alwayseverysec每秒将缓冲区刷新到硬盘(默认值)。everysecno根据当前操作系统的规则决定什么时候刷入硬盘,不需要我们考虑。没有数据加载创建一个没有网络连接的伪客户端;分析并从AOF文件中读取写入命令;使用伪客户端执行读写命令;执行第2步和第3步,直到AOF文件处理完所有写命令为止。为什么需要文件重写:为了解决AOF文件体积膨胀的问题;通过重写创建一个新的AOF文件来替换现有的AOF文件,并且新的AOF文件不会包含任何浪费空间的冗余命令。文件改写的实现原理:不需要对已有的AOF文件进行任何操作;直接从数据库中读取key的当前值;用一条命令记录键值对,从而代替之前记录键值对的顺序。后台rewrite是为了不阻塞父进程,Redis将AOFrewrite程序放在子进程中执行。在子进程执行的AOF改写过程中,服务器进程需要执行三个过程:执行客户端发送的命令;将执行的写命令追加到AOF缓冲区;将执行的写命令附加到AOF重写缓冲区。服务器进程默认配置AOF文件默认配置如下:###############################APPENDONLYMODE################################开启AOF持久化方法appendonlyno#AOF持久化文件名appendfilename"appendonly.aof"#追加数据在buffereverysecondfsynctodiskappendfsynceverysec#appendfsyncno#rewrite时不同步数据到AOF文件no-appendfsync-on-rewriteno#触发AOF文件的增长率来执行rewriteauto-aof-rewrite-percentage100#触发AOF文件执行rewrite最小大小auto-aof-rewrite-min-size64mb#Redis在恢复aof-load-truncatedyes时会忽略最后一个可能有问题的命令#是否开启混合开关aof-use-rdb-preambleyes大家有一个大致了解了Redis的持久化,那么这两种方式我们应该如何选择呢?对于大中型应用,我们要保证数据的完整性和高效性,所以应该结合使用RDB和AOF两种方式;如果只是需要保证数据的完整性,保护数据不丢失,那么优先使用AOF方式;如果是处理大规模数据恢复,追求更高更快的效率,优先使用RDB方式。也可以参考下图选择:主要对比转载本文请联系浅羽IT之家公众号。