文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

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

2024-04-02 19:55

关注

这篇文章主要讲解了“如何解决高并发服务遇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 操作改为批量模式了。但问题来了,很多的 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事故这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-前端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯