Redis持久化的原理及优化

做者:全菜工程师小辉html

连接:https://www.cnblogs.com/mseddl/p/11465417.html?utm_source=tuicool&utm_medium=referrallinux

Redis提供了将数据按期自动持久化至硬盘的能力,包括RDB和AOF两种方案,两种方案分别有其长处和短板,能够配合起来同时运行,确保数据的稳定性。ios

RDB

保存数据快照至一个RDB文件中,用于持久化。RDB操做和Mysql Dump类似。面试

执行方式

  • save。同步操做,会阻塞Redis。
  • bgsave。调用linux的fork(),而后使用新的线程执行复制。可是fork期间也会阻塞Redis,可是阻塞时间一般很短。
  • 自动保存。Redis配置文件中设置了自动保存的触发机制,能够自定义修改,运行原理同bgsave。

save和bgsave的对比

注意:sql

  • 若是机器上运行多个Redis,须要配置RDB文件名称,不然多个Redis的RDB文件会相互覆盖。

除了上述三种执行方式,如下状况也会生成RDB文件:数据库

  • 主从的全量复制时,主机会生成RDB文件。
  • Redis中的debug reload提供debug级别的重启,不清空内存的一种重启,这种方式也会触发RDB文件的生成。
  • 执行shutdown时,会触发RDB文件的生成。

RDB的缺点

  • 全量数据存储,耗时。
  • 虽然fork()采用copy-on-write策略,但仍消耗内存
  • 写RDB文件消耗大量IO性能。

AOF

采用AOF持久方式时,Redis会把每个写请求都记录在一个日志文件里,AOF操做和Mysql Binlog类似。经过AOF重写机制减小AOF文件的体积,从而减小恢复时间。bash

执行方式

  • always。Redis的每条写命令都写入到系统缓冲区,而后每条写命令都使用fsync“写入”硬盘。
  • everysec。过程与always相同,只是fsync的频率为1秒钟一次。这个是Redis默认配置,若是系统宕机,会丢失一秒左右的数据
  • no。由操做系统决定何时从系统缓冲区刷新到硬盘。

AOF重写

为了解决AOF文件体积膨胀的问题,Redis提供了AOF重写功能:Redis服务器能够建立一个新的AOF文件来替代现有的AOF文件,新旧两个文件所保存的数据库状态是相同的,可是新的AOF文件不会包含任何浪费空间的冗余命令,一般体积会较旧AOF文件小不少。服务器

AOF重写方式

  • bgrewriteaof(流程与bgsave类似)
  • AOF重写配置(与RDB自动保存类似)

AOF重写并不须要对原有AOF文件进行任何的读取,写入,分析等操做,这个功能是经过读取服务器当前的数据库状态来实现的。微信

RDB vs AOF

Redis启动时的数据加载

Redis启动数据加载流程:架构

  1. AOF持久化开启且存在AOF文件时,优先加载AOF文件。
  2. AOF关闭或者AOF文件不存在时,加载RDB文件。
  3. 加载AOF/RDB文件成功后,Redis启动成功。
  4. AOF/RDB文件存在错误时,Redis启动失败并打印错误信息。

开发运维中常见的问题

fork操做

fork()的实际开销就是复制父进程的页表以及给子进程建立一个进程描述符,因此速度通常比较快

内存量越大,耗时越长;物理机相对较快,虚拟机相对较慢。

优化方法

  1. 优先使用物理机或者高效支持fork操做的虚拟化技术
  2. 控制Redis实例最大可用内存maxmemory
  3. 合理配置Linux内存分配策略:vm.overcommit_memory=1。默认值为0,会使Linux在内存分配时,发现不够内存不足时,不会进行分配,进而形成fork阻塞,加微信号 weixin99ting 免费领取(BATJ面试资料、高可用、高并发、高性能及分布式、Jvm性能调优、Spring源码,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)和Java进阶学习路线图)
  4. 下降fork频率。例如放宽AOF重写自动触发时机或者减小没必要要的主从全量复制

进程外开销

  • CPU。RDB和AOF文件生成,属于CPU密集型。不要将Redis进程绑定在某个CPU上,防止单核过载;同时Redis不和CPU密集型应用一块儿部署。
  • 内存。fork内存开销,copy-on-write。
  • 硬盘。AOF和RDB文件的写入。能够结合iostat和iotop进行分析。

优化方法

  1. 不要和高硬盘负载服务部署在一块儿:存储服务、消息队列等
  2. 配置no-appendfsync-on-rewrite=yes。这样在AOF重写的期间,不要进行AOF追加操做(主线程只将数据写入缓冲区),能够减小内存的开销。

但若是AOF重写期间,Redis宕机的话,在Linux的系统默认配置下,最多会丢失30s的数据。若是没法忍受数据丢失,no-appendfsync-on-rewrite配置no;若是应用系统没法忍受延迟,而能够容忍少许的数据丢失,则设置为yes。

  1. 根据写入量决定磁盘类型:例如ssd
  2. 单机多实例持久化文件目录能够考虑分盘,或者使用相似cgroups机制进行硬盘资源的合理分配

AOF追加阻塞

例如在AOF的everysec策略中,主线程会对比上次fsync的时间,若是距离上次fsync时间超过两秒,就会形成主线程阻塞(等待同步线程同步完成)。

平常开发可使用 info persistence 命令,查看历史发生AOF阻塞的次数;然而须要了解AOF追加阻塞的发生时间则须要查看Redis日志。

发送AOF追加阻塞的时候,日志以下:

Asynchronous AOF fsync is taking too long (disk is busy?). Writing the AOF buffer without waiting for fsync to complete, this may slow down Redis.复制代码

优化方法(参考其余方面的优化点)

相关文章
相关标签/搜索