Redis在持久化时产生的延迟

一个老外的有关Redis的博客文章中提到一个有趣的事情:它们在测试期间获得的延迟图。为了持久化Redis的数据到磁盘(例如:RDB持久化),Redis需要调用fork()系统命令。

通常使用物理服务器和大多数虚拟机管理程序进行fork是很快的,即使很大的进程也是如此。 然而,Xen的fork()速度很慢,因此对于某些EC2实例类型(以及其他虚拟服务器提供程序),每次父进程调用fork()以便进行RDB持久化时,可能会出现严重的延迟峰值。 如下图所示,清晰的展示了延迟峰值:

您可以想象一下,如果您在fork()的时候做一个延迟测试,那么在父进程fork()的时候,所有请求将延迟一秒(以上图为例)。 这将产生大量具有高延迟的样本,并且将影响99%的结果。

要更改实例类型,配置,设置或其他任何内容以改善此行为是一个好主意,并且有些用例即使单个请求具有过高延迟也是不可接受的。然而很明显的是,每30分钟发生1秒的延迟峰值不是很明显,因为这与在请求中均匀分布延迟峰值有很大不同。

如果是均匀分布的峰值,如果访问某个页面需要对Redis服务器执行大量请求,则访问页面很可能会碰到延迟:这会严重影响服务质量。

然而,如上图所示,每运行30分钟后1秒的延迟是完全不同的事情。具有良好延迟表现的百分比随着请求数量的增加而变得更好,因为请求越多,这个延迟就越不可能在样本中过度表示出来,反而会被隐藏。如果您每分钟只有1个请求,并且其中一个请求恰好碰到fork()导致的高延迟,那就会让延迟测试结果非常难看。

另外:大多数页面浏览不受影响。 因为唯一那几个用户碰到1秒延迟的,是刚好他们的请求和fork()在同一时间,其他用户的请求只会有极低的概率碰到这样糟糕的事情。 另外请注意,与fork()撞上的页面访问(即使由100个请求组成)也不会延迟超过一秒,因为fork()完成后请求就会完成,并不需要等到RDB持久化完成。

只有fork()会导致延迟毛刺,fork出来的子进程在生成RDB文件过程中,并不会对系统有很大的影响。除非子进程生成RDB文件的过程中(这个过程使用了操作系统的copy-on-write机制)有大量的写入,而且服务器可用内存不多,这时候可能会发生swapping导致出现延迟。

在当今最流行的运行时环境EC2实例中,fork延迟是Redis用户最糟糕的体验之一,所以redis作者正着手测试Redis和EC2:相信很快就会在Redis官方文档中有对EC2进行特定优化的说明 ,到时候会有比在master-slaves中禁用持久性操作更安全的方案。

如果您现在需要EC2 + Redis主机并且已禁用持久性,则最简单的部署方式是禁用Redis实例的自动重启,并使用Sentinel进行故障转移,以便崩溃的主服务器不会自动返回可用状态。 在检查故障转移成功并且有新的可用的master后,系统管理员可以手动重新启动实例。

需要说明的是,并非所有EC2实例都是相同的,恰恰相反,各种EC2实例fork表现差异还很大。如下图所示,是老外做的一些测试:

总结

  • Redis持久化时调用fork可能引起严重的延迟(RDB持久化以及AOF rewrite都会调用fork命令);
  • 只是fork时引起延迟,fork完成后,子进程生成RDB/AOF文件的过程并不会引起延迟;
  • 即使Redis是单线程处理命令,但是服务器配置最好还是需要双核,如果有多个Redis实例,那么核心数相应的翻倍;
  • 除了fork会引起延迟外,Redis中那些时间复杂度为O(n)的也会引起性能毛刺,例如keys命令等。

原文地址:https://blog.51cto.com/14230003/2433013

时间: 2024-10-26 21:57:24

Redis在持久化时产生的延迟的相关文章

redis 数据持久化

转:redis 数据持久化 1.快照(snapshots) 缺省情况情况下,Redis把数据快照存放在磁盘上的二进制文件中,文件名为dump.rdb.你可以配置Redis的持久化策略,例如数据集中每N秒钟有超过M次更新,就将数据写入磁盘:或者你可以手工调用命令SAVE或BGSAVE. 数据保存的目录: 工作原理 Redis forks. 子进程开始将数据写到临时RDB文件中. 当子进程完成写RDB文件,用新文件替换老文件. 这种方式可以使Redis使用copy-on-write技术. 2.APP

Redis源码剖析和注释(十八)--- Redis AOF持久化机制

Redis AOF持久化机制 1. AOF持久化介绍 Redis中支持RDB和AOF这两种持久化机制,目的都是避免因进程退出,造成的数据丢失问题. RDB持久化:把当前进程数据生成时间点快照(point-in-time snapshot)保存到硬盘的过程,避免数据意外丢失. AOF持久化:以独立日志的方式记录每次写命令,重启时在重新执行AOF文件中的命令达到恢复数据的目的. Redis RDB持久化机制源码剖析和注释 AOF的使用:在redis.conf配置文件中,将appendonly设置为y

Redis数据持久化

总的来说有两种持久化方案:RDB和AOF RDB方式按照一定的时间间隔对数据集创建基于时间点的快照. AOF方式记录Server收到的写操作到日志文件,在Server重启时通过回放这些写操作来重建数据集.该方式类似于MySQL中基于语句格式的binlog.当日志变大时Redis可在后台重写日志. 若仅期望数据在Server运行期间存在则可禁用两种持久化方案.在同一Redis实例中同时开启AOF和RDB方式的数据持久化方案也是可以的.该情况下Redis重启时AOF文件将用于重建原始数据集,因为叫R

关于redis的持久化策略

Redis的持久化 Redis虽然是基于内存的存储系统,但是它本身是支持内存数据的持久化的,而且提供两种主要的持久化策略:RDB快照和AOF日志. Redis的RDB快照 Redis支持将当前数据的快照存成一个数据文件的持久化机制,即RDB快照.这种方法是非常好理解的,但是一个持续写入的数据库如何生成快照呢?Redis借助了fork命令的copy on write机制.在生成快照时,将当前进程fork出一个子进程,然后在子进程中循环所有的数据,将数据写成为RDB文件. 我们可以通过Redis的s

Redis的持久化和主从复制机制

Redis持久化 Redis 提供了多种不同级别的持久化方式: RDB 持久化可以在指定的时间间隔内生成数据集的时间点快照(point-in-time snapshot) AOF 持久化记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集. AOF 文件中的命令全部以 Redis 协议的格式来保存,新命令会被追加到文件的末尾. Redis 还可以在后台对 AOF 文件进行重写(rewrite),使得 AOF 文件的体积不会超出保存数据集状态所需的实际大小. Redi

LINUX系统编程 由REDIS的持久化机制联想到的子进程退出的相关问题

19:22:01 2014-08-27 引言: 以前对wait waitpid 以及exit这几个函数只是大致上了解,但是看REDIS的AOF和RDB 2种持久化时 均要处理子进程运行完成退出和父进程需要做的什么事情,所以特定看了UNIX环境编程和LINUX系统编程这2本书 重新梳理下整个要点. 内容: 一般而言: 如果程序类似于下面的情况: if((pid=fork())==0) { dochildtthing(); exit(0); } else if(pid>0) { dofathertt

Redis数据持久化机制AOF原理分析二

Redis数据持久化机制AOF原理分析二 分类: Redis 2014-01-12 15:36  737人阅读  评论(0)  收藏  举报 redis AOF rewrite 目录(?)[+] 本文所引用的源码全部来自Redis2.8.2版本. Redis AOF数据持久化机制的实现相关代码是redis.c, redis.h, aof.c, bio.c, rio.c, config.c 在阅读本文之前请先阅读Redis数据持久化机制AOF原理分析之配置详解文章,了解AOF相关参数的解析,文章链

Redis学习-持久化

Redis 提供了多种不同级别的持久化方式: RDB 持久化可以在指定的时间间隔内生成数据集的时间点快照(point-in-time snapshot). AOF 持久化记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集. AOF文件中的命令全部以Redis协议的格式来保存,新命令会被追加到文件的末尾. Redis还可以在后台对AOF文件进行重写(rewrite),使得 AOF 文件的体积不会超出保存数据集状态所需的实际大小.   Redis还可以同时使用AOF持

Redis源码解析(五):redis之持久化

redis常常被称为内存数据库是因为它将所有数据保存在内存中,为了能让这些数据在服务器重启后能继续使用,Redis 分别提供了RDB 和AOF 两种持久化模式. 在Redis 运行时,RDB 程序将当前内存中的数据库快照保存到磁盘文件中,在Redis 重启动时,RDB 程序可以通过载入RDB 文件来还原数据库的状态. RDB 功能最核心的是rdbSave 和rdbLoad 两个函数,前者用于生成RDB 文件到磁盘,而后者则用于将RDB 文件中的数据重新载入到内存中: AOF 以协议文本的方式,将