`
xiaoZ5919
  • 浏览: 404722 次
  • 性别: Icon_minigender_1
  • 来自: 安平人@北京
博客专栏
Group-logo
Netty学习笔记
浏览量:73198
社区版块
存档分类
最新评论

Redis的Aof被阻塞原因调查

 
阅读更多
背景

   Redis是单进程的,为了发挥多核的优势,我们redis集群采用在单台机器上部署多个redis实例,同时对持久化方式做了改进,采用rdb和增量的aof相结合的方式,appendfsync配置为no。那这样会有一个时段同时进行aof和rdb,当aof和rdb同时进行时,监控系统报警说某些请求Timeout,我们超时设置为2s。另外我们的机器分为两种类型,cpu配置不同,一种是4核,另外一种是12核,timeout发生在4核的机器上。
分析
   解决这个问题还是走了不少弯路的,所以在这儿和大家分享一下。经过一番分析找到一下可能导致慢的原因
  • CPU,rdb过程会有lzf compress以及crc会消耗cpu
  • bgsave的fork,fork需要copy page entry table到子进程中去,这个过程是阻塞的
  • IO问题,bgsave产生大量的IO,但这是在子进程中完成,应该不会影响主进程吧,在此处埋个伏笔


CPU问题?
因为timeout的问题主要出现在4核的机器上,12核的机器没有问题,所以首先怀疑cpu问题。我用info commandstats查看各个命令执行时间都是us级别,但4核的比12核的慢了近50%。如果是cpu撑不了,这个值应该至少在ms级别。同时profiler分析了redis执行bgsave的函数耗时。在MakeFile中添加-pg,注意编译和链接都需要加,我开始只在编译阶段加了,没有效果。
GPROF=-pg
FINAL_CFLAGS=$(STD) $(WARN) $(GPROF) $(OPT) $(DEBUG) $(CFLAGS) $(REDIS_CFLAGS)
# redis-server
$(REDIS_SERVER_NAME): $(REDIS_SERVER_OBJ)
        $(REDIS_LD) $(GPROF)  -o $@ $^ ../deps/hiredis/libhiredis.a ../deps/lua/src/liblua.a $(FINAL_LIBS)


观察都lzf和crc确实很占用cpu时间是最多的。crc采用一种增量的方式,而不是每次全量,性能应该很高。那么关闭compress和crc以后是否能解决呢?关闭以后问题依旧看来不是cpu的问题。

IO问题?
关闭aof以后问题解决,这当中也做了很多尝试,调整bgsave子进程的进程和IO有优先级,将主进程和子进程分别绑定在不同的cpu上,都不管用一度怀疑不是IO的问题。
在这里介绍几个工具
  • renice 调整进程的优先级
  • ionice 调整进程的IO优先级,当然这是针对block层的IO schedule,为啥不生效,后来才发现,ionice对async write的不起作用,cfq是将async write请求在同一请求队列中不属于进程自己的队列,write(2)一般情况是写入page cache就立马返回,而不是等待真正落入磁盘
  • taskset 将指定进程绑定到指定的cpu上

既然write(2)是buffered IO,写先到page cache中,那究竟是什么阻塞了呢?write是不是无限制地使用pagecache,这一点不清楚,这一段时间就狂看各种linux内核相关文档和看源码。
发现阻塞write(2)有几种情况:
  1. fsync(fdatasync) 会阻塞write
  2. pdflush会阻塞write
  3. 还有当dirty page超过可用内存的40%,这时候就会调用schedule_timeout阻塞200ms。write并不是仅仅copy到page cache就返回了,他还会检查dirty page的使用比例,如超过了会尝试阻塞地写入磁盘,如果此时不能完全写入,就会调用schedule_timeout从而产生iotimewait,此时使用top观察确实有90%的CPU使用是iotimewait

弯路
说说其中的弯路,由于我的粗心放过了一个重大的线索,同事告诉我一个linkhttp://www.redis.io/topics/latency,其中有一节就讲到了aof被大量IO阻塞的问题,作者提到fdatasysnc会阻塞write(2),但我们设置appendfsync为no,不会出现fdatasync和write(2)的阻塞
那究竟是什么阻塞了write呢,曾一度怀疑是dirty page超过可用内存的40%导致的拥塞等待。
但后来在一台64G内存redis只占用了7G内存的机器上遇到aof阻塞,排除了拥塞等待,那还有什么原因呢?
我查看redis的pullrequesthttps://github.com/antirez/redis/pull/1862,发现idning也遇到了类似问题,提出aof采用单独异步线程write的方案,不过作者有点不感冒没有merge,但他提出可以把文件系统的日志模式改为writeback模式不写日志,我试了会有所改观但不会解决问题。我依然知道到底是什么阻塞了write,这时候我把write的代码整体读了一篇然后用systemtap检测每一个可疑的高耗时函数
probe kernel.function("__wait_on_bit_lock").return {

  if(isinstr(execname(),"redis-server")){
       time = gettimeofday_us() - @entry(gettimeofday_us())
       if(time > 100000){
           printf("trace:%s,pid:%d,function:%s,cost:%d\n",ctime(gettimeofday_s()),pid(),probefunc(),time);
           print_stack(backtrace());
       }
  }

}

锁定在__wait_on_bit_lock,再根据调用堆栈发现有很多地方调用它,比如是read的时候,等待时候把数据从磁盘加载到page中等等。最终定位到一个可疑之处
page = __grab_cache_page(mapping,index,&cached_page,&lru_pvec);

write的时候都会先定位写那个page并尝试lock,而flush dirty page的时候也会先lock住。如果pdflush时,rdb产生大量的IO,那么他有可能尝试占用lock从而 __grab_cache_page等待很长时间。关于这一点我还不是很确定,欢迎大家帮助我确认。

解决Latency的正确流程
Redis的作者在http://www.redis.io/topics/latency,已经总结了很多种latency的情况,遇到latency一定要先看它,是否有负责自己的场景,比如我提的问题就是Latency due to AOF and disk I/O,我开始使用了pstack和strace但是都没有定位到阻塞的原因,其实strace可以定位到,但是使用方式不对导致没有捕获到真正的原因。redis2.6以后还提供了watchdog功能,通过config set watchdog打开该功能,就能在日志中打印出慢查询的堆栈。
分享到:
评论

相关推荐

    Redis 持久化之RDB和AOF.doc

    Redis 持久化是确保数据安全的重要机制,它提供了两种主要的方法:RDB(Redis Database)和 AOF(Append Only File)。RDB 是一种快照式的持久化方式,而 AOF 则记录每次写操作的日志。 RDB 持久化在特定条件下将...

    redis常见阻塞.docx

    Redis 中常见的阻塞原因有慢查询、bigkey、Swap、fork 子进程、AOF 刷盘阻塞、输入缓冲区阻塞和输出缓冲区阻塞等。为了避免这些阻塞问题,需要对 Redis 进行合理的配置和优化,例如配置最大可用内存、控制 fork 操作...

    redis稳定版6.2.x with cygwin 发布包

    非阻塞,RDB-AOF混合持久化,PSYNC2.0 Redis 5 增加Stream即Redis MQ,主动碎片整理V2,集群管理器移植到C,RESP2 Redis 6 引入多线程IO,客户端缓存,权限控制,支持SSL,提升了RDB加载速度,Redis集群代理模块, ...

    redis开发和运维

    在讨论Redis的噩梦——阻塞问题时,作者分析了阻塞的内在原因(如API使用不当、CPU饱和)和外在原因(如CPU竞争、内存交换、网络问题)。 内存管理是Redis运行中的核心问题,书中第8章专门探讨了Redis的内存消耗、...

    windows版本redis6.0.8

    Redis是一款高性能的键值数据库,常用于数据缓存、消息队列等场景。在Windows操作系统上,虽然Redis原生支持Linux环境,但通过社区的努力,也有适用于Windows的版本。本篇将详细介绍“windows版本redis6.0.8”这一...

    redis 7.0.0 windows版

    5. 在ACL中,pub/sub channel默认是被阻塞的。 6. 在从节点中,TTL的时间标识的是绝对时间,不再是相对时间,从而保证了过期数据被及时删除。 7. 不再支持 gopher协议。 8. 当在配置文件中设置replica-serve-stale-...

    redis-7.0.15-win-amd64

    Redis是世界上最受欢迎的开源内存数据结构存储系统,它作为一个键值数据库被广泛应用于缓存、消息中间件、数据库等多个场景。这个"redis-7.0.15-win-amd64"压缩包提供了Redis在Windows操作系统上的64位版本,为在...

    Redis实战_Redis实战中文完整版_Redis快速入门_Redis数据类型及操作_Redis常用

    4. **Redis持久化**:为了防止数据丢失,Redis提供了两种持久化方式:RDB(快照)和AOF(Append Only File)。这两种方式的原理、优缺点和应用场景会在书中进行深入解析。 5. **Redis复制**:通过主从复制,可以...

    ServiceStack.Redis-5.8无限制.zip

    4. **异步操作**:为适应高并发环境,ServiceStack.Redis提供了大量的异步方法,利用.NET的异步编程模型,确保了在执行多个Redis命令时不会阻塞主线程。 5. **事务处理**:Redis支持单个命令的原子执行,...

    redis-6.2.13.tar.gz

    - **线程I/O多路复用**:Redis使用epoll/kqueue等事件驱动模型,非阻塞I/O,提高了处理速度。 - **LFU(Less Frequently Used)**:在6.2版本中,Redis引入了LFU作为新的淘汰策略,与LRU相比,更适应访问模式变化...

    Redis持久化RDB和AOF区别详解

    为了确保数据在服务器重启或异常情况下的安全,Redis提供了两种主要的持久化机制:RDB(Redis Database Persistence,即快照)和AOF(Append Only File,追加日志)。下面将详细解释这两种持久化方式的区别。 **RDB...

    redis 5.X版本,redis 5.X版本

    Redis 5.0 版本是 Redis 社区推出的一个重大更新,它引入了许多新特性,增强了性能,并修复了大量的bug。作为一个高效的键值存储系统,Redis 在数据库和缓存领域广泛应用。以下是 Redis 5.0 版本中的关键知识点: 1...

    redis稳定版 6.2.x with msys 发布包

    非阻塞,RDB-AOF混合持久化,PSYNC2.0 Redis 5 增加Stream即Redis MQ,主动碎片整理V2,集群管理器移植到C,RESP2 Redis 6 引入多线程IO,客户端缓存,权限控制,支持SSL,提升了RDB加载速度,Redis集群代理模块, ...

    Redis实战.pdf

    它被设计为一个内存数据库,支持多种数据结构,如字符串、哈希、列表、集合和有序集合,同时提供了持久化功能,确保数据在服务器重启后依然可用。Redis的这些特性使得它成为缓存、消息队列、数据存储等多种场景下的...

    AOF持久化策略配置文件

    在 Redis 中,AOF(Append Only File)持久化策略是数据保存的一种方式,它记录了所有对数据库进行修改的命令,确保即使在服务器崩溃后也能恢复数据。本文将深入探讨 AOF 持久化策略及其配置文件。 首先,我们需要...

    redis压缩包.rar

    Redis服务器可以在单进程单线程模式下处理高并发请求,由于其非阻塞I/O模型,因此性能表现非常出色。 对于Linux环境的安装,通常我们会采用以下步骤: 1. 下载Redis源代码,解压至指定目录。 2. 使用`make`命令编译...

    redis实战(带书签,高清扫描)

    在性能优化方面,Redis的内存管理、命令阻塞以及配置调优等策略都对系统的性能有着直接影响。书中会介绍如何监控和分析Redis的运行状态,以及如何调整参数以提高性能。 最后,书中的实例部分是学习Redis的重要环节...

    redis简单使用实例

    Redis,全称Remote Dictionary Server,是一款高性能的键值对存储系统,常被用作数据库、缓存和消息中间件。它的出现主要是为了解决关系型数据库在高并发场景下的性能瓶颈问题,尤其在数据读写速度和内存利用效率上...

    【Redis开发】资源Redis-v6.0.20.zip

    Redis,全称Remote Dictionary Server,是一款高性能的键值存储系统,常被用于数据库、缓存和消息中间件等场景。Redis以其高效的性能、丰富的数据结构和便捷的操作接口赢得了广大开发者们的喜爱。本资源"Redis-v...

Global site tag (gtag.js) - Google Analytics