Redis持久化

持久化机制⭐⭐⭐

Client redis ---> 内存数据 数据持久化--->硬盘

Redis官方提供了两种不同的持久化方法来将数据存储到硬盘中分别是:

  • 快照(snapshot)
  • AOF(Append Only Flie) 只追加日志文件

快照

# 1 特点
-	这种方式可以将`某一时刻的所有数据`都写入硬盘中,当然这也是redis的默认kaiq持久化方式,保存的文件是以`.rdb形式结尾的文件`,因此这种方式也称之为`RDB持久化方式`.

# 2 生成方式
- 客户端方式 : BGSAVE 和 SAVE指令
- 服务器配置自动触发

# 2.1 客户端方式值BGSAVE
- 客户端可以使用BGSAVE命令来创建一个快照,当接收到客户端的BGSAVE命令时,redis会`调用fork`来创建一个子进程,然后子进程负责将快照写入磁盘,而父进程则继续处理命令请求.
		fork : 当一个进程创建子进程的时候,底层的操作系统会创建该进程的一个副本,在类unix系统中创建子进程的操作会进行优化: 	在刚开始的时候,父子进程共享相同内存,直到父进程或子进程对内存进行了写之后,对被写入的内存的共享才会结束服务	
- 为什么这么做?
	  	创建快照的过程可能会有几秒钟到几分钟,如果放到主线程来做会阻塞主进程继续处理客户端请求

# 2.2 客户端方式之SAVE
- 客户端还可以使用SAVE命令来创建一个快照,接收到SAVE命令的redis服务器在快照创建完毕之前将不再响应任何其他的命令
 
 		与BGSAVE不同,使用SAVE命令在快照创建完毕之前,redis处于阻塞状态,无法对外服务

# 3 服务器配置方式之满足配置自动触发
- 如果用户在redis.conf中设置了save配置选项,redis会在save选项条件满足之后自动触发一次BGSAVE命令,如果设置多个save配置选项,当任意一个save配置选项条件满足,redis也会触发一次BGSAVE命令

# 4 服务器接收客户端shutdown指令
- 当redis通过shutdown指令接收到关闭服务器的请求时,会执行一个`save命令`,阻塞所有的客户端,不再执行客户端执行发送的任何命令,并且在save命令执行完毕之后关闭服务器

# 5 设置生成快照名称和位置
- 修改生成快照名称
		vim redis.conf
		找到并修改 dbfilename dump.rgb
		
- 修改生成位置
		dir ./

弊端

可能会丢失某一时刻的数据

例如:

刚做完快照,还没到达下一次快照的条件就断电了


AOF只追加日志文件

特点

​ 这种方式可以将所有客户端执行的写命令记录到日志文件中,AOF持久化会将被执行的写命令写到AOF的文件末尾,以此来记录数据发生的变化,因此只要redis从头到尾执行一次AOF文件所包含的所有写命令,就可以恢复AOF文件的记录的数据集

开启AOF持久化

​ 在redis的默认配置中AOF持久化机制是没有开启的,需要在redis.conf修改配置启动

# 1 开启AOF持久化
- 修改 appendonly yes 开启持久化

- 修改 appendfilename "appendonly.aof" 指定生成文件名称

日志追加频率

# 1 always  [谨慎使用]
- 说明 : 每个redis写命令都要同步写入硬盘,严重降低redis速度

- 解释 : 如果用户使用了always选项,那么`每个redis写命令都会被写入硬盘`,从而将发生系统崩溃时出现的`数据丢失减到最少`;遗憾的是,因为这种同步策略需要`对硬盘进行大量的写入操作`,所以redis处理命令的速度会受到`硬盘性能的限制`

- 注意 : 转盘式硬盘(机械硬盘)在这种频率下200左右个命令/s ; 固态硬盘(SSD)几百万个命令/s 

- 警告 : 使用SSD用户请谨慎使用always选项,这种模式`不断写入少量数据`的做法有可能会引发严重的`写入放大问题(不断写入小文件)`,导致将固态硬盘的`寿命从原来的几年降低为几个月`.

# 2 everysec  [推荐]
- 说明 : 每秒执行一次同步显式的将多个写命令同步到磁盘

- 解释 : 为了`兼顾数据安全的写入性能`,用户可以考虑使用everysec选项,让redis`每秒一次的频率对AOF文件进行同步`;redis每秒同步一次AOF文件时性能和不使用任何持久化特性时的`性能相差无几`,而通过每秒同步一次AOF文件,redis可以保证,即使系统崩溃,`用户最多丢失一秒之内产生的数据`

# 3 no  [不推荐]
- 说明 : 由操作系统决定何时同步

- 解释 : 最后使用no选项,将完全`由操作系统决定什么时候同步AOF日志文件`,这个选项`不会对redis性能带来影响`但是`系统崩溃时,会丢失不定数量的数据`,另外如果用户硬盘处理写入操作不够快的话,当缓冲区被等待写入硬盘数据填满时,redis会处于阻塞状态,并导致redis的处理命令请求的速度变慢.

修改同步频率

# 1 修改日志同步频率
- 修改appendfsync everysce|always|no

弊端

​ AOF的方式也同时带来了拎一个问题.持久化文件会变得越来越大(极端情况会占满磁盘).例如我们调用了 incr test 命令 100次,文件中必须保存全部的100条命令,其实有99条都是多余的.因为要恢复数据库的状态其实文件中保存一条 set test 100 就够了.

为了压缩aof的持久化文件Redis提供了AOF重写机制


AOF文件的重写

用来在一定程度上减小AOF文件的体积

触发重写方式

# 1 客户端方式触发重写
- 执行BGREWRITEAOF命令   不会阻塞redis的服务

# 2 服务器配置方式自动触发
- 配置redis.conf中的auto-aof-rewrite-percentage选项,如下图:
- 如果设置`auto-aof-rewrite-percentage为100`和`auto-aof-rewrite-min-size 64mb`,并且启用的AOF持久化时,那么当AOF文件体积大于64M,并且AOF文件的体积比上一次重写之后体积大了至少一倍(100%)时,会自动触发,`如果重写过于频繁,用户可以考虑将auto-aof-rewrite-percentage设置为更大`

重写原理

重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件替换原有的文件,这点和快照有点类似

# 重写流程
- 1 redis调用fork,现在有父子两个进程 子进程根据内存中的数据库快照,往临时文件中写入重建数据库状态的命令

- 2 父进程继续处理client请求,除了把写命令写入到原来的aof文件中,同时把收到的写命令缓存起来.这样就能保证如果子进程重写失败的话并不会出问题

- 3 当子进程把快照内容写入已命令方式写到临时文件中后,子进程发信号通知父进程.然后父进程把缓存的写命令也写入到临时文件.

- 4 现在父进程可以使用临时文件替换老的aof文件,并重命名,后面收到写命令也开始往新的aof文件中追加.

持久化总结

​ 两种持久化方案即可以同时使用(aof),又可以单独使用,在某种情况下也可以都不使用,具体使用哪种持久化方案取决于用户的数据和应用决定

​ 无论使用AOF还是快照机制持久化,将数据持久化到硬盘都是有必要的,除了持久化外,用户还应该对持久化的文件进行备份(最好备份在多个不同地方)

posted @ 2020-09-10 17:33  longda666  阅读(79)  评论(0)    收藏  举报