本文将带你深入了解Redis的持久化方法和原理。Redis的优缺点,本文将介绍Redis的两种持久化方式。希望大家在阅读本文后,对Redis的这两种持久化方式有更全面、更清晰的认识。RDB快照模式持久化从RDB快照模式开始。RDB是Redis默认开启的持久化模式,我们不需要单独开启。我们先看一下RDB相关的配置信息:################################SNAPSHOTTING####################################SavetheDBondisk:##save##WillsavetheDBifboththegivennumberofsecondsandthegiven#numberofwriteoperationsagainsttheDB发生。##Intheexamplebelowthebehaviourwillbetosave:#after900sec(15min)ifatleast1keychanged#after300sec(5min)ifatleast10keyschanged#after60secifatleast10000keyschanged#save""#自动生成快照触发机制的中间部分是时间,单位是秒,后面是60秒后改变数据并更改10000条数据自动生成快照save9001save30010save6010000#生成快照失败时主线程是否停止写入stop-writes-on-bgsave-erroryes#是否使用压缩算法存储rdbcompressionyes#是否校验有效性数据恢复时的RDB文件,我们需要调整的更少,我们只需要修改snapshotgeneration机制和文件存储路径根据我们的业务量。RDB的持久化方式有两种:手动触发和自动触发。手动触发使用以下两个命令:save:会阻塞当前Redis服务器响应其他命令,直到生成RDB快照。对于内存大的实例,会阻塞很长时间,所以不建议在线环境下使用。bgsave:Redis主进程会fork一个子进程,rdb快照生成有子进程负责,完成后子进程会自动结束,bgsave只会在fork子进程时暂时阻塞,这个进程是很短,所以建议使用此命令手动触发。除了通过执行命令手动触发外,Redis内部还有自动触发RDB持久化机制。在以下几种情况下,Redis会自动触发RDB持久化:在配置中配置了save相关的配置信息,如我们上面的配置文件中save6010000也可以归类为“savemn”格式的配置,也就是说:当数据集在m秒内修改n次时,会自动触发bgsave。在master-slave的情况下,如果slave节点进行全量复制操作,master节点自动执行bgsave生成RDB文件发送给slave节点。当执行debugreload命令重新加载Redis时,也会自动触发save操作。默认情况下,执行shutdown命令时,如果没有开启AOF持久化功能,会自动执行bgsave。以上就是RDB持久化的方式。可以看出save命令使用频率较低。大多数情况下都是使用bgsave命令,所以这个bgsave命令还是有些东西的。接下来我们看一下bgsave背后的原理,从流程图开始:bgsave操作流程图bgsave命令有以下步骤:1.执行bgsave命令,Redis主进程会判断是否有RDB/当前正在执行的AOF子进程。如果是这样,bgsave命令会直接返回,不再执行。2、父进程执行fork操作创建子进程。在fork操作过程中,父进程会被阻塞。fork完成后,父进程不会被阻塞,可以接受其他命令。3、子进程新建RDB文件,根据父进程当前内存数据生成临时快照文件,完成后用新的RDB文件替换原来的RDB文件,并发送RDB快照生成完成的通知完成给父进程。以上是bgsave命令背后的一些内容。RDB的内容几乎一样。下面总结一下RDB持久化的优缺点和RDB模式的优点:RDB快照是Redis节点某一时刻的内存数据,非常适合备份上传到远程服务器或者文件系统中,使用用于灾难恢复备份。RDB在数据恢复时比AOF快很多。有优点也有缺点。RDB的缺点是:RDB持久化数据无法做到实时持久化/秒级持久化。我们已经知道bgsave命令每次运行都需要执行fork操作创建子进程,属于重量级操作,频繁执行的代价太高。RDB文件以特定的二进制格式保存。Redis在版本演进过程中,存在多个RDB版本。存在旧版本Redis服务无法兼容新版本RDB格式的问题。如果我们对数据要求比较高,不能丢失每一秒的数据,那么RDB持久化方式肯定不能满足要求。Redis有什么办法可以满足要求吗?答案是肯定的,那就是接下来的AOF持久化方式。AOF文件持久化方式Redis默认是不开启AOF持久化模式的,需要我们自己开启,在redis.conf配置文件中将appendonlyno调整为appendonlyyes,从而开启AOF持久化。与RDB不同的是,AOF是以记录操作命令的形式来持久化数据,我们可以查看如下AOF持久化文件appendonly.aof。*2$6SELECT$10*3$3set$6mykey1$6Hello*3$3set$4key2$5hello*1$8看起来是这样的,具体可以查看你Redis服务器上的appendonly.aof配置文件,也就是那么我们可以修改appendonly.aof文件中的值,Redis重启时会加载修改后的值。看似一些简单的操作命令,其实从command到appendonly.aof的过程是很有学问的。下面是AOF持久化流程图:AOF持久化流程图在AOF持久化过程中有两个非常重要的操作:一个是向AOF_BUF缓冲区追加操作命令,一个是同步AOF_buf缓冲区中的数据到AOF文件。下面详细说一下这两个操作:1.为什么命令要写入aof_buf缓冲区,而不是直接写入aof文件?我们知道Redis是单线程响应的。如果每次写AOF命令都是直接追加到磁盘上的AOF文件中,如此频繁的IO开销,Redis的性能将取决于你的机器硬件,为了提高Redis的响应效率,增加了一层aof_buf缓存层,利用了操作系统的缓存技术,提高了Redis的性能。这样虽然解决了性能问题,但是也引入了一个问题,aof_buf缓存区数据如何同步到AOF文件中?谁来同步它?这就是我们接下来要讲的操作:fsync操作。2、如何将aof_buf缓冲区中的数据同步到aof文件中?aof_buf缓冲区中的数据写入aof文件是由Linux系统完成的。由于Linux系统的调度机制有一个比较长的周期,如果系统出现故障宕机,意味着一个周期文件中的所有数据都会丢失,这不是我们想要的,所以Linux提供了一个fsync命令,fsync是针对单个文件操作(比如这里的AOF文件),做硬盘强制同步,fsync会阻塞直到写入硬盘完成返回,保证数据持久化。因为这个命令,redis提供了配置项让我们决定什么时候进行磁盘同步。Redis在redis.conf中提供了appendfsync配置项,有如下三个选项:#appendfsyncalwaysappendfsynceverysec#appendfsyncnoalways:每次有写命令时,缓存区与磁盘数据同步,保证不会有数据丢失,但是这会导致redis的吞吐量大幅下降,下降到每秒只有几百TPS,违反了redis的设计,所以不建议使用这种方式everysec:这是redis默认的同步机制.虽然数据每秒同步一次,看起来时间很快,但是对redis的吞吐量没有影响,每秒同步一次意味着在最坏的情况下,我们只会丢失1秒的数据。推荐使用这种同步机制,兼顾性能和数据安全。去调度,操作系统同步调度的周期是不固定的,最多会有30秒的间隔,这样一旦出现故障,就会丢失更多的数据。以上就是三种磁盘同步策略,但是大家有没有发现一个问题,AOF文件是追加的,随着服务器的运行,AOF文件会越来越大,过大的AOF文件会影响redis服务器甚至主人。有影响,Redis重启时加载过大的AOF文件耗时太长。这些都是不友好的,那么Redis是怎么解决这个问题的呢?Redis引入了重写机制来解决AOF文件过大的问题。3、Redis是如何进行AOF文件重写的?RedisAOF文件改写是将Redis进程中的数据转换成写入命令,同步到新的AOF文件中的过程。重写后的AOF文件会比旧的AOF文件占用更多的空间。体积小,这是由以下原因造成的:进程中超时的数据不再写入文件。旧AOF文件包含无效命令,如delkey1,hdelkey2,sremkeys,seta111,seta222等,重写直接使用进程内数据生成,这样新AOF文件只保留写命令finaldata多个写命令可以合二为一,比如:lpushlista,lpushlistb,lpushlistc可以转换为:lpushlistabc。为防止单个命令过大导致客户端缓冲区溢出,对于list、set、hash、zset等类型的操作,以64个元素为界划分为多个命令。重写后的AOF文件更小,这不仅节省了磁盘空间,更重要的是,更小的AOF文件在Redis数据恢复时加载时间更短。AOF文件重写分为手动触发和类似RDB持久化的自动触发。手动触发直接调用bgrewriteaof命令。稍后我们将详细讨论此命令。自动触发需要我们在redis.conf中修改如下配置:auto-aof-rewrite-percentage100auto-aof-rewrite-min-size64mbauto-aof-rewrite-percentage:代表当前AOF文件空间的比例(aof_current_size)到上次rewrite后的AOF文件空间(aof_base_size),默认为100%,即大小相同时auto-aof-rewrite-min-size:表示运行AOF时AOF文件的最小大小rewrite,默认是64MB,也就是说AOF文件的最小大小是64MB才能触发rewrite。当满足这两个条件时,Redis会自动触发AOF文件重写。AOF文件重写的细节和RDB持久化快照生成类似。下面是AOF文件重写的流程图:AOF文件重写AOF文件重写也是交给子进程完成,类似于RDB快照的生成。AOF文件改写在改写时会创建一个aof_rewrite_buf缓冲区,用于保存改写时主进程响应的命令。新的AOF文件改写完成后,会将这些文件同步到新的AOF文件中,最后将旧的AOF文件替换为新的AOF文件。需要注意的是,在重写期间,旧的AOF文件还是会同步到磁盘上。这样做的目的是防止重写失败导致数据丢失。Redis持久化数据恢复我们知道Redis是基于内存的,所有的数据都存储在内存中。由于机器宕机或者其他因素重启,我们所有的数据都会丢失,这就是持久化的原因。当服务器重启的时候,Redis会从持久化文件中加载数据,这样我们的数据就会恢复到重启前的数据。Redis是如何实现数据恢复的?我们来看看数据恢复的流程图:Redis数据恢复Redis的数据恢复过程比较简单。AOF文件优先恢复。如果AOF文件不存在,它会尝试加载RDB文件。为什么RDB的恢复速度比AOF文件快,但还是先加载AOF文件?我个人认为AOF文件数据更全面,AOF兼容性比RDB强。需要注意的是,当RDB/AOF存在时,如果数据加载失败,会导致Redis服务启动失败。