为什么会持久化。Redis是一个内存数据库。如果内存数据库状态没有保存到磁盘,那么一旦服务器进程退出,服务器的数据库状态就会消失。(即断电时丢失)。为了保证数据不丢失,我们需要将内存中的数据存储到磁盘中,这样Redis重启的时候就可以从磁盘中恢复出原来的数据,整个过程称为Redis持久化。Redis持久化也是Redis和Memcached的主要区别之一,因为Memcached没有持久化功能。持久化的几种方式Redis持久化有以下三种方式:快照方式(RDB,RedisDataBase)将某一时刻的内存数据以二进制形式写入磁盘;文件追加方式(AOF,AppendOnlyFile),记录所有写操作命令,并以文本形式追加到文件中;混合持久化方式,Redis4.0之后新增的一种方式,混合持久化结合了RDB和AOF的优点。写的时候,先把当前的数据以RDB的形式写入到文件的开头,然后将后续的操作命令以AOF格式存储到文件中,这样既可以保证Redis重启的速度,又可以避免数据丢失的风险。因为每种持久化方案都有特定的使用场景,所以我们先从RDB持久化说起。1、什么是RDB,RDB是如何实现持久化的?1.什么是关系数据库?RDB是Redis数据库的缩写。它的作用是将Redis内存中存储的数据在某个时间点生成一个快照,存储在磁盘等介质上。该磁盘介质上的文件是RDB文件。顾名思义,“快照”就是像拍照一样保存当时的数据。在这里,RDB文件是一个二进制文件,并且是压缩的。由于RDB文件保存在硬盘中,即使Redis服务器进程退出,甚至运行Redis服务器的计算机挂掉,只要RDB文件还存在,Redis服务器就可以利用它来恢复数据库状态。2、触发方式(手动、自动)RDB持久化触发方式有两种:一种是手动触发,一种是自动触发。1)手动触发(执行save或bgsave命令)手动触发持久化操作的命令有两个:save和bgsave。它们的主要区别在于是否阻塞Redis主线程的执行。savecommandredis127.0.0.1:6379>SAVE在客户端执行save命令,会触发Redis的持久化,但同时使Redis处于阻塞状态,不会响应其他客户端,直到RDB持久化完成complete命令,因此在生产环境中必须谨慎使用。bgsave命令redis127.0.0.1:6379>BGSAVEbgsave(后台保存)表示在后台保存。它和save命令最大的区别是bgsave会fork()一个子进程来进行持久化。整个过程中,只有fork()子进程存在短暂的进程阻塞。当子进程被创建后,Redis的主进程就可以响应其他客户端的请求了。与阻塞整个进程的save命令相比,bgsave命令显然更适合我们使用。在快照的过程中,也就是生成文件的过程中,在生成快照之前不会修改原来的RDB文件,直接用旧的替换新的,保证RDB文件在任何时候都是完整的时间。2)自动触发自动触发的意思是我们不需要手动命令触发持久化,而是通过配置在满足一定规则时自动执行bgsave命令。Redis配置文件默认设置了3个保存点:#以下配置表示的条件:#如果一个key在900秒内发生变化,会触发RDB文件的保存save9001#服务器在300秒内被修改10次save30010#服务器在60秒内被修改10000次save6010000#如果要关闭快照保存功能,可以注释掉所有“save”配置,或者在最后一次“save”配置后添加如下配置:save""注意这里执行bgsave命令是为了满足条件。2、什么是AOF,AOF是如何实现持久化的?1.什么是AOF?以日志的形式记录每次写操作,记录Redis执行的所有写命令(读操作不记录),只追加文件不重写文件,redis在启动之初会读取文件重建数据,也就是说,如果redis重启,会根据日志文件的内容从前到后执行write命令,完成数据恢复工作。默认情况下,redis不启用AOF(appendonlyfile)。开启AOF功能需要设置配置:appendonlyyes。2、AOF持久化过程上面说到AOF持久化的过程就是不断追加日志的过程。下面通过图来介绍具体的流程:1.Client作为命令的来源,会有多个来源,源源不断的请求命令。2、这些命令到达RedisServer后,并没有直接写入AOF文件,而是先将这些命令放入AOF缓存中进行存储。这里的AOF缓冲区其实就是内存中的一块区域。存在的目的是在达到一定数量后将这些命令写入磁盘,避免频繁的磁盘IO操作。3、AOF缓冲区会根据相应的策略向磁盘上的AOF文件写入命令。4.随着AOF文件内容的增加,命令会按照规则进行合并。这就叫做AOF重写,从而达到AOF文件压缩的??目的。5、当RedisServer重启时,会从AOF文件中加载数据。有两点需要详细写一下:AOF缓冲区同步文件策略和AOF重写机制。3、AOF缓冲区同步文件策略上面提到Redis会先向AOF缓冲区写入命令,然后再写入AOF文件。下面介绍AOF缓冲区同步文件的三种策略。#aof持久化策略配置appendfsyncalways#always表示每次写入都执行fsync,保证数据同步到磁盘appendfsynceverysec#everysec表示每秒执行一次fsync,可能会造成这1s丢失dataappendfsyncno#no表示不执行fsync,操作系统保证数据同步到磁盘。Always策略最快的同步操作是在主进程的主线程中进行的。由于fsync的阻塞特性,会导致它挂掉,期间无法服务新的。请求,所以吞吐量下降,但确实保证了内存和硬盘数据的一致性。Everysec策略的同步操作是通过后台I/O线程进行的。由于是在子线程中进行,所以主线程不会被阻塞,可以继续服务新的请求,但是内存和硬盘中的数据会有1秒的差异(不一定准确),这是一个妥协解决,寻求平衡。No策略是在不阻塞主线程的情况下,将同步操作的控制权交给操作系统,但数据一致性可能会出现较大偏差。官方推荐使用每秒同步的默认配置,既快速又安全。这种始终策略在实践中非常缓慢,没有办法使fsync比现在更快。4、什么是AOF重写机制(一)?AOF采用文件追加的方式,文件会越来越大。为了避免这种情况,添加了重写机制。当AOF文件的大小超过设定的阈值时,Redis会启动AOF文件的内容压缩。保留可以恢复数据的最小指令集。举个例子:比如有一个key,你一开始设置key1,然后改成设置key2,最后设置key3,如果不改写,那么这3条语句都在文件里,占用空间,启动时必须执行无效命令。如果改写的话,只需要保存setkey3即可。AOF改写不仅可以减少文件占用空间,而且更小的AOF可以更快的被Redis加载。(2)触发机制(手动、自动)手动:客户端向服务端发送bgrewriteaof命令自动:满足配置文件中的选项后,自动执行bgrewriteaof命令。Redis会记录上次重写的AOF大小。默认配置是当AOF文件大小是上次rewrite后的两倍大小,且文件大于64M时触发。(3)重写原理当AOF文件不断增长,过大时,会fork出一个新的进程来重写文件(也是先写临时文件再重命名),遍历新进程内存中的数据,每条记录都有一个TheSet语句。重写aof文件的操作并不是读取旧的aof文件,而是通过命令将整个内存数据库内容重写到一个新的aof文件中,有点类似于快照。三、RDB和AOF的优缺点一、RDB的优点(1)RDB与AOF相比,在数据量比较大的情况下,RDB启动速度更快。(2)RDB文件是一个非常简单的单个文件,保存Redis在某个时间点的数据,非常适合做备份。(3)RDB的性能非常好。当需要持久化时,主进程会fork一个子进程,然后将持久化工作交给子进程,不会有相关的I/O操作。2.RDB的缺点(1)RDB容易造成数据丢失。假设每5分钟保存一次快照,如果Redis由于某种原因无法正常工作,从最后一次快照到Redis故障的数据将会丢失。(2)RDB使用fork()生成子进程的过程会阻塞主进程,所以如果数据比较大,fork()可能会比较耗时,导致Redis停止服务几毫秒。3、AOF的优点(1)这种机制可以带来更高的数据安全性,即数据持久化。Redis提供了3种同步策略,分别是每秒同步、每次修改同步和非同步。其实第二次同步也是异步完成的,效率很高。如果发生灾难,您可能只会丢失1秒的数据。(2)AOF日志文件是一个纯追加文件。即使服务器突然崩溃,也不会有日志定位或损坏的问题。即使因为某种原因(比如磁盘满了)命令只写了一半到日志文件,我们也可以很简单的使用redis-check-aof工具来修复。(3)当AOF文件过大时,Redis会在后台自动重写。重写是安全的,因为重写是在新文件上执行的。4、AOF的缺点(1)在相同的数据集下,AOF文件的大小一般要大于RDB文件。(2)开启AOF后,写入QPS会低于RDB。通常fsync设置为每秒一次以获得比较高的性能,禁用fsync时,速度可以达到RDB的水平。4、关于生产配置持久化的一些看法(1)官方建议:同时开启两种持久化策略。因为有时候需要RDB快照是数据库备份、更快重启、AOF引擎错误的解决方案。(换句话说,通过RDB多备份一份数据总是好的)(2)因为RDB文件只是用来备份的,所以建议只在Slave上持久化RDB文件,它只需要每15分钟备份一次。仅保留save9001规则。(3)如果选择AOF,只要硬盘允许,尽量减少AOF重写的频率。因为一是不断的IO,二是AOFrewrite最终将rewrite过程中产生的新数据写入到新文件中,这几乎是必然的。AOF重写basesize的默认值是64M,太小了,可以设置成2G以上。关注公众号:后端元宇宙。持续输出优质好文
