首先,要知道我们为什么要对redis做持久化?
因为,redis本身运行时数据保存在内存中,如果不进行持久化,那么在redis出现非正常原因宕机或者关闭redis的进程或者关闭计算机后数据肯定被会操作系统从内存中清掉。
很多人又会问,“明明我们在本地自己搭redis环境的时候没有多余的配置操作呀,但是就算自己重启redis或者重启计算机后,甚至过了几个月后,redis中的数据仍然存在哦!?”。
当然,redis本身默认采用了一种持久化方式,即RDB (Redis DataBase)——可以在redis的目录中找到dump.rdb文件,这就是使用RDB方式做持久化后生成的数据文件。所以,redis如果没有做持久化,在重启redis后,数据会丢失,而redis默认就采用了一种持久化方式,即RDB。
redis持久化的方式有两种:RDB(Redis DataBase)和AOF(Append Only File)
RDB方式采用的思想是定时将内存中的数据进行快照,并写入dump.rdb文件当中,这个文件当中所存储的就是当前redis环境中的配置以及数据。每次当redis重启之后,redis会先读dump.rdb文件,将数据从硬盘写入到内存中。
Redis 调用fork函数复制一份子进程. 同时拥有(当前进程)父进程和子进程。
父进程继续接收处理客户端发送过来的请求操作,子进程则从内存中将数据集写入到一个临时 RDB 文件中。
当子进程完成对新 RDB 文件的写入时,Redis 用新 RDB 文件替换原来的 RDB 文件,并删除旧的 RDB 文件。
在redis的配置文件redis.conf中搜索save,这一个save可以设置在指定时间内,更新操作达到了固定次数,就将数据同步到数据文件,这里可以写多个save多条件配合使用。比如以下代码所示
# 表示900秒内有一次更改,或者900秒内有10次更改,或者60秒内有10000此更改执行同步操作 save 900 1 save 300 10 save 60 10000
另外,如果想不使用RDB做持久化了,可以不配置任何的save,或者将save配成空字符串,如下图所示。
save ""
在redis的配置文件中如果使用RDB的方式做持久化,除了要注意save的配置外,还有两个配置需注意。其中一个是dbfilename,这一个配置表示存储的快照文件(数据文件)的文件名,redis默认为dump.rdb,所以我们看到redis目录中会有这样一个文件,这个文件中存放了二进制的内容。另外一个是dir,dir的配置表示了dbfilename所配置的这一个文件的路径,这里最好配一个绝对路径,因为如果使用了相对路径,那么通过不同的方式其启动redis可能会出现文件找不到导致数据前后不一致的情况发生。
AOP模式做持久化,把所有的写操作命令记录到磁盘文件中保存,也就是说使用AOF会将客户端对于redis的操作(查询除外)以一个字符串的形式记录到磁盘的文件中去,而在启动redis的时候会去读取这一个文件,将命令执行。
AOF 文件与RDB 文件相比不同的是AOF 文件并不是一个snapshot (快照)的概念, 他是一个 append 的概念,文件的信息会直接添加到文件的末尾,当然这的方式比上面的RDB文件的好处就是,通过调整数据的刷新(同步)方式,是可以做到数据不丢失的,但不利的地方,即使随着保证数据不丢失的等级升高,对REDIS 本身的性能影响就会越突出。并且AOF 文件是在系统重启动,或者CRASH 后,在启动REDIS后对系统数据进行恢复的一种方式。
redis默认是关闭AOF模式持久化的,需要打开,并且默认是每秒来进行与磁盘的交互,如果要使用需要修改一下配置:
# 默认为no,需修改为yes appendonly yes # AOF默认的持久化文件的文件名称 appendfilename "appendonly.aof"
而指定更新日志条件的同步策略有三个可选条件,默认每秒进行同步:
# 当操作系统进行数据缓存同步到磁盘文件 # appendfsync no
# 每秒同步一次(默认值,也是最佳的选择,速度快,可能会丢失一秒以内的数据(最多不过2秒)) appendfsync everysec
# 同步持久化,当数据发生变更时,立即同步到磁盘文件(效率慢些,能保证数据的完整性) # appendfsync always
另外,可以配置当持久化的文件到达一定程度后,进行重写,为什么要进行重写?由于AOF模式持久化记录的是操作命令,文件会越来越大,其实可以优化aof文件,去掉多余的中间操作命令,比如说当有这两个命令set key "value1", set key "value2"依次执行后,实际上要恢复数据只需要执行set key "value2"即可。经过类似的压缩,可以为原本已经很大的文件“瘦身”,以下的内容,即为执行此“瘦身”操作的配置。触发重写机制为:
# 当AOF的持久化文件大小的增长率大于此配置时,自动开启重写,redis会自动执行“BGREWRITEAOF”命令; auto-aof-rewrite-percentage 100 # 当AOF的持久化文件大小大于此配置时,自动开启重写,redis会自动执行“BGREWRITEAOF”命令; auto-aof-rewrite-min-size 3000mb
注:通过fork一个子进程,重新写一个新的aof文件,该次重写不是读取旧的aof文件进行复制,而是将读取内存中的redis数据库,重写一份aof文件,有点类似于rdb的快照方式;
AOF的优点:
(1)AOF模式可以更好的保护数据不丢失,在redis因为非正常原因挂掉时,其保存数据的完整度理论上高于RDB模式,因为采用appendfsync everysec去写入持久化文件,最多丢失一秒到两秒的数据;而RDB模式丢失的数据根据其配置的写入频率决定;
(2)AOF写入性能高,这归功于其是以append-only的方式写入;
AOF的缺点:
(1)对于同样的数据,通常AOF文件的大小回比RDB的要大;
(2)因为AOF存的是命令而不是数据,所以恢复数据时可能较慢。
如果你的REDIS 是从事写缓冲的工作,例如经常更新数据,所以在REDIS中进行了数据的更新,在多次的运算和更新后,将最后的结果刷入到传统的数据库中,这的确是一个解决高并发,更新值,降低传统数据库负担的方式。例如你一分钟更新上百次或上千次的值的情况下,在这样的情况下,你就需要将 RDB 文件和 AOF 文件都开启的,并且随着你的应用逻辑和你容忍数据可能丢失度的降低,你的RDB 文件和 AOF 文件的保存方式等级都会提高;
例如 RDB 文件,你是否需要提高下面的RDB 文件的刷新率 ,根据刷新的频率,调整:
例如,如果写入的在5秒就有10000次,则不需要调整,如果60秒内写入9999次,则需要调整一下 save 60 10000 变为 save 60 5000,这样RDB 的刷新文件(同步)的频率就会提高,满足你的需求。另外在你CTRL + C 终止REDIS 的情况下(Redis 并未在有),会强制先将数据刷入到 RDB 文件,否则除非你 KILL 否则是无法关闭 REDIS的。
像我上面所说,AOF 持久化模式默认是关闭的,需要打开,并且默认是每秒来进行与磁盘的交互:
所以在双重的RDB 和AOF 文件的加持下,在这样的业务场景下,数据安全是有保证的,如果还想严格的不丢失数据,则需要将上图的设置调整为 appendfsync always 打开,则任何的操作都会记录在 appendonly.aof 文件中,这种同步模式虽然是最安全,但也是性能最差的。
所以REDIS 的持久化可以根据Redis在系统中所承担的作用来设置,如果是只读作为读缓冲,则可以不需要进行持久化的操作,可以将RDB AOF 文件关闭,已达到最好的效果,当然你的程序也需要考虑在 REDIS CRASH (崩了)后的数据重新刷入,否则会引起缓存雪崩,导致你的实体数据库 MYSQL ORACLE ,POSTGRESQL SQL SERVER 等数据库无法承受短期的高频的数据读取,而不再有响应。
要不就需要设置 RDB, AOF 文件,在某些应用场景下,防止丢失数据,或者引起缓冲击穿后的雪崩问题。
建议如果没有特殊的要求,需要打开 RDB AOF 持久化,这样REDIS 好, 传统数据库好,你好我好,大家好。
参考文章:
https://blog.csdn.net/y506798278/article/details/103541097
https://blog.csdn.net/liuhuayang/article/details/105743430