热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

phpredisson,排查redisson中订阅connection无故消失的问题

最近在项目中使用了redis结合springcache一起作了一个缓存,并使用了订阅功能来达到进程间的数据同步。但在测试使用过程中,发现第二天一来&#x

最近在项目中使用了redis结合spring cache一起作了一个缓存,并使用了订阅功能来达到进程间的数据同步。但在测试使用过程中,发现第二天一来,本来应该工作的订阅同步并不能进行。当时没在意,简单重启了事。但后来发现,每天早上相应的同步都不能进行,并且经测试。每个进程的同步都不进行,感觉是redis的订阅出问题了。

1. 验证问题

表现出来就是A程序修改了数据,B程序并没有识别到这次更新。那么就先尝试手动在redis中进行相应的set操作,因为订阅的是redis的空间事件,即key space event. 在控制台单独连接redis,执行相应的set 命令,在B程序中并没有任何表示。

怀疑是不是redis的发布订阅出问题了,就另开终端,手动地进行订阅,一切正常。

初步确定是程序出问题了。

2. 查看程序

把进程的stack打印一份,查看里面的线程信息,发现并没有redisson的线程信息。一般来说,没收到消息也可能是线程内阻塞了,但是直接就没有相应的线程,这就有问题了。

怀疑是不是相应的连接被断开之后就没有再连,也可能是redis server被重启了。

重新连接redis,使用status查看相应的状态,显示server端并没有重启过,其运行时间长达X天,即没有间断过。

回过来再看相应的redisson程序,里面有一个watch dog,是负责连接断开重连的。即如果连接被断掉了,它会尝试重连,但每一次的重连都会迟后一定时间,如 1 2 4 8 秒这样。这也是为什么要看stack的原因。简单看了下watchdog的实现,表示并没有明显的问题(或者就没问题)。

进一步怀疑是不是出现了某个异常,导致相应的watchdog重连直接被中断了。比如Error级错误。将相应的日志拉下来一份,因为一晚上都没人操作,日志信息本身也很少。直接在里面使用grep Exception查找日志信息,但一切也很正常,甚至没有异常发生。

再重新查看了redisson的源码,里面使用netty的channelInActive来进行重连尝试。在本地测试了一下这个机制,redis重启或者断开连接,它都能检测到。开始怀疑是不是日志信息不全,被吞掉了。重新调整日志级别,将redisson和netty的级别调到TRACE级别,结果中午过去一会,再回来看。相应的连接又不见了,订阅又不能正常工作。查看了日志,里面也没有任何信息,因为这期间无任何操作。

3. 回到redis,查找网络问题

从以上的现象,考虑到这期间没有操作,并且在接近1个多小时后,相应的订阅就不能工作。并且在之前的日志中,发现如果redis中一直有相应的命令产生时,订阅反而是在工作的。这就怀疑是不是网络上的问题,因为没有网络操作,导致连接不明原因被中断,但netty没有探测到。

回到redis server,在确定订阅失效后,想到订阅是在相应的连接上调用psubscribe操作,相应的连接信息是有记录的。本来想从redis server日志中找点东西,但看了配置文件,redis server输出默认是关的。但是可以使用 redis client查看所有连接。使用此命令,把所有连接输出到文件,查找 psub=1的行,结果是没有找到任何记录。这就表示,从server这端来看,已经没有订阅的连接连上来。

但从程序这边日志来看,确又表示没有收到连接被断开的消息。这种现象马上就想到keepalive的类似信息,是不是因为没有keepalive导致连接被默认关掉。因为在订阅断开期间,确实没有任何网络交互(trace日志中没有任何输出). 通过google netty channelInactive和keepalive,结果确实有一些信息表明。如果没有开启keepalive,很有可能根本就不会触发netty的这个回调。

之前对netty有一些了解,一般网络程序都有类似ping/pong处理,在redisson中,并没有在netty中使用ping/pong协议。又看了redis,虽然也有提交类似命令。

重新查看redis.conf的整个配置文件,有2个配置项引起了注意,分别是 timeout 和 tcp-keepalive。将这2个参数,再google了一下,发现此篇文章。

http://rossipedia.com/blog/2014/01/redis-i-like-you-but-youre-crazy/

里面提到了这2个参数对redis的影响以及潜在的问题点。

4. 调整配置,网络keepalive

从配置参数上来看,这个keepalive是工作在tcp层的,应用程序不可见,但仍可以任何保持心跳的一种实现手段。将其配置先都配置为 60,即无操作60秒之后关掉空闲连接,并且每60秒发一次心跳交互。

在配置完之后,查看相应的日志,发现redisson在每60秒之后就会显示收到了connection close的通知而重建connection,以保证在minConnection之上。但是订阅连接并没有收到相应的通知。从server端,通过client list也可以看到,每当idle接近60之后相应的连接即会重新换成新的连接,idle再从0开始计时。但是订阅的连接(最后的cmd为psubscribe)相应的age一直在增加,并且idle也一直在增加,并没有被关闭。

在观察了一晚上之后,第二天再看连接列表,相应的订阅连接的age达到10K级别,即生存了一晚上,并且idle时间也很长,但相应的连接也没有被关闭。在终端在通过set测试了一个数据命令,查看程序日志,马上就能打印出相应的订阅消息,表示整个程序工作正常。也没有问题了。

5. keepalive参数重要性

后来又单独google一下keepalive信息,发现了一些关于tcp方面的一些信息,并且在redisson 15年的一次讨论中,也提到server中的keep-alive配置顶。一并链接如下

LVS和Nginx之间的keepAlive 以及在nginx中设置tcp层keepAlive    http://blog.sina.com.cn/s/blog_e59371cc0102ux5w.html

一个老外控诉redis中的这2个网络参数以及默认设置    http://rossipedia.com/blog/2014/01/redis-i-like-you-but-youre-crazy/

redisson中的连接没有响应以及连接超时的问题讨论    https://github.com/redisson/redisson/issues/198

此次问题的处理过程,走了一些弯路,应该直接从client list入手。但通过此次问题处理,也对网络有更深的了解。同时,进程间的通讯也更加了解。

后面,通过日志监控,发现由于订购命令空间事件太多,会在一定程度上影响到订阅的消费处理,取消了一些短时间对象在redis中的缓存(如30秒级的缓存,订阅事件会收到expired通知和delete通知),当然这跟这次的连接关系不大。

相关文章:

作者: flym

I am flym,the master of the site:)查看flym的所有文章



推荐阅读
  • 本文介绍了通过ABAP开发往外网发邮件的需求,并提供了配置和代码整理的资料。其中包括了配置SAP邮件服务器的步骤和ABAP写发送邮件代码的过程。通过RZ10配置参数和icm/server_port_1的设定,可以实现向Sap User和外部邮件发送邮件的功能。希望对需要的开发人员有帮助。摘要长度:184字。 ... [详细]
  • 怎么在PHP项目中实现一个HTTP断点续传功能发布时间:2021-01-1916:26:06来源:亿速云阅读:96作者:Le ... [详细]
  • LVS实现负载均衡的原理LVS负载均衡负载均衡集群是LoadBalance集群。是一种将网络上的访问流量分布于各个节点,以降低服务器压力,更好的向客户端 ... [详细]
  • Spring框架《一》简介
    Spring框架《一》1.Spring概述1.1简介1.2Spring模板二、IOC容器和Bean1.IOC和DI简介2.三种通过类型获取bean3.给bean的属性赋值3.1依赖 ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文介绍了在Oracle数据库中创建序列时如何选择cache或nocache参数。cache参数可以提高序列的存取速度,但可能会导致序列丢失;nocache参数可以避免序列丢失,但在高并发访问时可能导致性能问题。文章详细解释了两者的区别和使用场景。 ... [详细]
  • Java中包装类的设计原因以及操作方法
    本文主要介绍了Java中设计包装类的原因以及操作方法。在Java中,除了对象类型,还有八大基本类型,为了将基本类型转换成对象,Java引入了包装类。文章通过介绍包装类的定义和实现,解答了为什么需要包装类的问题,并提供了简单易用的操作方法。通过本文的学习,读者可以更好地理解和应用Java中的包装类。 ... [详细]
  • 海马s5近光灯能否直接更换为H7?
    本文主要介绍了海马s5车型的近光灯是否可以直接更换为H7灯泡,并提供了完整的教程下载地址。此外,还详细讲解了DSP功能函数中的数据拷贝、数据填充和浮点数转换为定点数的相关内容。 ... [详细]
  • Todayatworksomeonetriedtoconvincemethat:今天在工作中有人试图说服我:{$obj->getTableInfo()}isfine ... [详细]
  • 本文介绍了在Android开发中使用软引用和弱引用的应用。如果一个对象只具有软引用,那么只有在内存不够的情况下才会被回收,可以用来实现内存敏感的高速缓存;而如果一个对象只具有弱引用,不管内存是否足够,都会被垃圾回收器回收。软引用和弱引用还可以与引用队列联合使用,当被引用的对象被回收时,会将引用加入到关联的引用队列中。软引用和弱引用的根本区别在于生命周期的长短,弱引用的对象可能随时被回收,而软引用的对象只有在内存不够时才会被回收。 ... [详细]
  • DSP中cmd文件的命令文件组成及其作用
    本文介绍了DSP中cmd文件的命令文件的组成和作用,包括链接器配置文件的存放链接器配置信息、命令文件的组成、MEMORY和SECTIONS两个伪指令的使用、CMD分配ROM和RAM空间的目的以及MEMORY指定芯片的ROM和RAM大小和划分区间的方法。同时强调了根据不同芯片进行修改的必要性,以适应不同芯片的存储用户程序的需求。 ... [详细]
  • Python中sys模块的功能及用法详解
    本文详细介绍了Python中sys模块的功能及用法,包括对解释器参数和功能的访问、命令行参数列表、字节顺序指示符、编译模块名称等。同时还介绍了sys模块中的新功能和call_tracing函数的用法。推荐学习《Python教程》以深入了解。 ... [详细]
  • 解决Sharepoint 2013运行状况分析出现的“一个或多个服务器未响应”问题的方法
    本文介绍了解决Sharepoint 2013运行状况分析中出现的“一个或多个服务器未响应”问题的方法。对于有高要求的客户来说,系统检测问题的存在是不可接受的。文章详细描述了解决该问题的步骤,包括删除服务器、处理分布式缓存留下的记录以及使用代码等方法。同时还提供了相关关键词和错误提示信息,以帮助读者更好地理解和解决该问题。 ... [详细]
  • 本文介绍了5个基本Linux命令行工具的现代化替代品,包括du、top和ncdu。这些替代品在功能上进行了改进,提高了可用性,并且适用于现代化系统。其中,ncdu是du的替代品,它提供了与du类似的结果,但在一个基于curses的交互式界面中,重点关注占用磁盘空间较多的目录。 ... [详细]
author-avatar
季幸静仪1255_189
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有