iis服务器助手广告
返回顶部
首页 > 资讯 > 前端开发 > node.js >如何解决高并发服务遇redis瓶颈引发time-wait事故
  • 849
分享到

如何解决高并发服务遇redis瓶颈引发time-wait事故

2024-04-02 19:04:59 849人浏览 八月长安
摘要

这篇文章主要讲解了“如何解决高并发服务遇Redis瓶颈引发time-wait事故”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何解决高并发服务遇redis

这篇文章主要讲解了“如何解决高并发服务遇Redis瓶颈引发time-wait事故”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何解决高并发服务遇redis瓶颈引发time-wait事故”吧!

摘要

元旦期间 订单业务线 告知 推送系统 无法正常收发消息,作为推送系统维护者的我正外面潇洒,无法第一时间回去,直接让 ops 帮忙重启服务,一切好了起来,重启果然是个大杀器。由于推送系统本身是分布式部署,消息有做各种的可靠性策略,所以重启是不会丢失消息事件的。

事后通过日志分析有大量的 redis 的报错,十分钟内有 16w 次的错误。日志的错误是 connect: cannot assign requested address 。该错误不是推送服务内部及 redis 库返回的 error,而是系统回馈的 errno 错误。

这个错误是由于无法申请可用地址引起的,也就是无法申请到可用的 Socket

话说,元旦当天在线数和订单量确实大了不少,往常推送系统的长连接客户端在 35w,这次峰值飙到 50w 左右, 集群共 6 个节点,其中有 4 个节点每个都抗了 9w+ 的长连接。另外,推送的消息量也随之翻倍。

如何解决高并发服务遇redis瓶颈引发time-wait事故

分析

下面是 kibana 日志的统计,出错的时间区间里有近 16w 次的 redis 报错。

如何解决高并发服务遇redis瓶颈引发time-wait事故

下面是出问题节点的 tcp 连接状况,可以看到 established 在 6w,而 time-wait 连接干到 2w 多个。

如何解决高并发服务遇redis瓶颈引发time-wait事故

为什么会产生这么多 time-wait?谁主动关闭就就有 time-wait,但推送系统除了协议解析失败之外,其余情况都不会主动 close 客户端,哪怕是鉴权失败和弱网络客户端写缓冲爆满,事后通过日志也确定了不是推送系统自身产生的 tw。

另外,linux 主机被 ops 交付时应该有做内核调优初始化的,在开启 tw_reuse 参数后,time-wait 是可以复用的。难道是没开启 reuse?

查看 sysctl.conf 的内核参数得知,果然 tcp_tw_reuse 参数没有打开,不能快速地复用还处在 time-wait 状态的地址,只能等待 time-wait 的超时关闭,rfc 协议里规定等待 2 分钟左右,开启 tw_reuse可在 1s 后复用该地址。另外 ip_local_port_range 端口范围也不大,缩短了可用的连接范围。

sysctl  -a|egrep "tw_reuse|timestamp|local_port"  net.ipv4.ip_local_port_range = 35768    60999 net.ipv4.tcp_timestamps = 1 net.ipv4.tcp_tw_reuse = 0

所以,由于没有可用地址才爆出了 connect: cannot assign requested address 错误。

内在问题

追究问题

上面是表象问题,来查查为什么会有这么多的 time-wait ?再说一遍,通常哪一端主动 close fd,哪一端就会产生 time-wait。事后通过 netstat 得知 time-wait 连接基本是来自 redis 主机。

下面是推送代码中的连接池配置,空闲连接池只有 50,最大可以 new 的连接可以到 500 个。这代表当有大量请求时,企图先从 size 为 50 的连接池里获取连接,如果拿不到连接则 new 一个新连接,连接用完了后需要归还连接池,如果这时候连接池已经满了,那么该连接会主动进行 close 关闭。

MaxIdle   = 50 MaxActive = 500 Wait      = false

除此之外,还发现一个问题。有几处 redis 的处理逻辑是异步的,比如每次收到心跳包都会 Go 一个协程去更新 redis, 这也加剧了连接池的抢夺,改为同步代码。这样在一个连接上下文中同时只对一个 redis 连接操作。

解决方法

调大 golang redis client 的 maxIdle 连接池大小,避免了高下无空闲连接而新建连接和池子爆满又不能归还连接的尴尬场面。当 pool wait 为 true 时,意味着如果空闲池中没有可用的连接,且当前已建立连接的连接数大于 MaxActive 最大空闲数,则一直阻塞等待其他人归还连接。反之直接返回 “connection pool exhausted” 错误。

MaxIdle   = 300 MaxActive = 400 Wait      = true

redis 的 qps 性能瓶颈

redis 的性能一直是大家所称赞的,在不使用 redis 6.0 multi io thread 下,QPS 一般可以在 13w 左右,如果使用多指令和 pipeline 的话,可以干到 40w 的 OPS 命令数,当然 qps 还是在 12w-13w 左右。

Redis QPS 高低跟 redis 版本和 cpu hz、cache 存在正比关系

根据我的经验,在内网环境下且已实例化连接对象,单条 redis 指令请求耗时通常在 0.2ms 左右,200us 已经够快了,但为什么还会有大量因 redis client 连接池无空闲连接而建立新连接的情况?

通过 grafana 监控分析 redis 集群,发现有几个节点 QPS 已经到了 Redis 单实例性能瓶颈,QPS 干到了近 15w 左右。难怪不能快速处理来自业务的 redis 请求。这个瓶颈必然会影响请求的时延。请求的时延都高了,连接池不能及时返回连接池,所以就造成了文章开头说的问题。总之,业务流量的暴增引起了一系列问题。

如何解决高并发服务遇redis瓶颈引发time-wait事故

发现问题,那么就要解决问题,redis 的 qps 优化方案有两步:

  • 扩容 redis 节点,迁移 slot 使其分担流量

  • 尽量把程序中 redis 的请求改成批量模式

增加节点容易,批量也容易。起初在优化推送系统时,已经把同一个逻辑中的 redis 操作改为批量模式了。但问题来了,很多的 redis 操作在不同的逻辑块里面,没法合成一个 pipeline。

然后做了进一步的优化,把不同逻辑中的 redis 请求合并到一个 pipeline 里,优点在于提高了 redis 的吞吐,减少了 socket 系统调用、网络中断开销,缺点是增加了逻辑复杂度,使用 channal 管道做队列及通知增加了 runtime 调度开销,pipeline worker 触发条件是满足 3 个 command 或 5ms 超时,定时器采用分段的时间轮。

对比优化修改前,cpu开销减少了 3% 左右,压测下redis qps平均降了 3w 左右差值,最多可以降到 7w 左右,当然概率上消息的时延会高了几个ms。

如何解决高并发服务遇redis瓶颈引发time-wait事故

实现的逻辑参考下图,调用方把redis command和接收结果的chan推送到任务队列中,然后由一个worker去消费,worker组装多个redis cmd为pipeline,向redis发起请求并拿回结果,拆解结果集后,给每个命令对应的结果chan推送结果。调用方在推送任务到队列后,就一直监听传输结果的chan。

如何解决高并发服务遇redis瓶颈引发time-wait事故

感谢各位的阅读,以上就是“如何解决高并发服务遇redis瓶颈引发time-wait事故”的内容了,经过本文的学习后,相信大家对如何解决高并发服务遇redis瓶颈引发time-wait事故这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

--结束END--

本文标题: 如何解决高并发服务遇redis瓶颈引发time-wait事故

本文链接: https://www.lsjlt.com/news/83981.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 如何解决高并发服务遇redis瓶颈引发time-wait事故
    这篇文章主要讲解了“如何解决高并发服务遇redis瓶颈引发time-wait事故”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何解决高并发服务遇redis...
    99+
    2024-04-02
  • Redis如何解决高并发问题
    这篇文章主要介绍Redis如何解决高并发问题,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!具体如下:redis为什么会有高并发问题redis的出身决定 redis是一种单线...
    99+
    2024-04-02
  • 如何使用Redis解决高并发
    这篇文章主要介绍了如何使用Redis解决高并发的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇如何使用Redis解决高并发文章都会有所收获,下面我们一起来看看吧。NoSQLNot Only SQL的简称。NoSQ...
    99+
    2023-07-05
  • 多个服务连接redis并发问题如何解决
    解决多个服务连接Redis并发问题可以通过以下几种方法:1. 连接池:使用连接池来管理多个连接,每个服务从连接池中获取一个连接,使用...
    99+
    2023-09-04
    redis
  • 如何解决JVMFullGC引发严重线上事故的问题
    今天就跟大家聊聊有关如何解决JVMFullGC引发严重线上事故的问题,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。一、业务场景介绍先简单说说线上生产系统的一个背景,因为仅仅是文章作为...
    99+
    2023-06-03
  • 如何解决Redis高并发防止秒杀超卖的问题
    这篇文章主要介绍了如何解决Redis高并发防止秒杀超卖的问题,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。1:解决思路将活动写入 redis 中,通过 redis 自减指令扣...
    99+
    2023-06-25
  • 如何解决PHP开发中的高并发任务调度问题
    概述:在PHP开发过程中,高并发任务调度是一个常见的挑战。尤其是在大型的网站或应用中,任务调度可能会涉及到同时执行、竞争资源和性能等问题。本文将介绍一些解决高并发任务调度问题的方法,并提供具体的代码示例。使用消息队列:消息队列是一种高效的任...
    99+
    2023-10-21
    高并发 任务调度 PHP开发
  • Go语言中如何解决并发数据库事务问题?
    Go语言是一种支持高并发的编程语言,而数据库事务是在并发环境中经常需要处理的问题之一。在Go语言中,我们可以通过使用事务来确保数据库操作的一致性和完整性。本文将介绍如何在Go语言中解决并发数据库事务问题,并附带具体的代码示例。在Go语言中,...
    99+
    2023-10-22
    Go语言 并发数据库 事务问题
  • 阿里云服务器如何解决并发错误
    在现代网络环境中,并发错误是一个常见的问题,特别是在使用阿里云服务器时。并发错误可能会导致服务器崩溃,数据丢失,甚至影响到用户的使用体验。本文将详细介绍阿里云服务器如何解决并发错误。 并发错误是由于多个用户同时对服务器进行请求而导致的错误。...
    99+
    2023-11-06
    阿里 如何解决 错误
  • 在Go语言中如何解决并发任务的故障恢复问题?
    在Go语言中如何解决并发任务的故障恢复问题?在现代的软件开发中,利用并发处理能够显著提高程序的性能,在Go语言中,我们可以通过使用goroutine和channel来实现高效的并发任务处理。然而,并发任务也带来了一些新的挑战,如处理故障恢复...
    99+
    2023-10-22
    Go语言 (Go language) 并发 (concurrency) 故障恢复 (Fault recovery)
  • 在Go语言中如何解决并发任务的分布式事务管理问题?
    在Go语言中如何解决并发任务的分布式事务管理问题?随着互联网的快速发展,分布式系统的应用越来越广泛。在分布式系统中,由于任务的分布和并发执行,出现了一种重要的问题,那就是分布式事务管理。分布式事务管理的目标是保证在分布式环境中的事务的完整性...
    99+
    2023-10-22
    Go语言 (Go language) 分布式事务 (Distributed Transaction) 并发任务 (Con
  • 使用国外的云服务器发生故障如何解决
    使用国外云服务器发生故障解决的方法:1、网站访问量太大导致使用故障,需要通过升级云服务器配置资源进行解决;2、VPS中毒,需要做好数据备份,通过重装系统来将系统病毒进行清除;3、受到DDOS和CC攻击,通过升级云服务器配置或接入CDN服务来...
    99+
    2024-04-02
  • 在Go语言中如何解决并发网络请求的请求服务降级和异常处理问题?
    在Go语言中如何解决并发网络请求的请求服务降级和异常处理问题?随着互联网的快速发展,越来越多的应用需要进行并发网络请求。然而,在高并发的情况下,网络请求可能会导致超时、阻塞等问题,从而影响到整个系统的稳定性和可靠性。面对这个问题,我们可以使...
    99+
    2023-10-22
    异常处理 (Exception Handling) 并发网络请求 (concurrent network request
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作