记录一次高并发引起的生产事故的溯源记录

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: 记录一次高并发引起的生产事故的溯源记录

一次高并发抢购活动引起的生产事故的过程分析记录

1.在日志中观察到的很多dubbo超时报错

Caused by: com.alibaba.dubbo.remoting.TimeoutException: Waiting server-side response timeout. 

排查过程:数据库sql负载偏高,有接口直接查sql没有加缓存的,数据库瓶颈没办法,一个sql延迟几十毫秒,并发上来之后,就会把整体往后拖了

原因分析:

1.执行sql没有超时时间,慢就慢了,但是rpc接口和对外接口是有timeout的,单个dubbo服务是的线程池数量是有上限的,

2.每个rpc接口调用1个sql,一个sql延迟100ms,就算一个rpc调用100ms,比如这个进程给的线程数是100,那么一秒钟1000ms/200ms * 100 = 500次,也就是这个rpc接口的性能是500次/秒,恰好能够没有线程阻塞等待处理完毕,当501并发时第501个就会阻塞100ms才能进到rpc中执行代码处理,最后因为sql的超时导致了调用dubbo provider进程阻塞,继而导致rpc外层调用的consumer超时,接口返回异常。

将sql全部优化之后,发现在高并发的时候日志中还是有超时的报错,看问题还是一样的,最后排查发现是因为A服务对外提供了一个按id查唯一信息的rpc接口,B服务中有逻辑为了获取多个id的信息,循环进行多次rpc调用。所以如果B服务获取的id信息越多对应的rpc循环调用的次数也就越多,从而B的这个业务操作会更加耗时,最后导致超时问题的出现。

最后把这里优化掉,改成一次rpc调用从A服务中批量拿到全部的数据后再在B服务这里分组依次获取。

2.修复上面的问题后发现又出现了dubbo线程池满了的报错

[DUBBO] Thread pool is EXHAUSTED! Thread Name: DubboServerHandler-ip:70882, Pool Size: 400 (active: 400, core: 400, max: 400, largest: 400), Task: 8640430 (completed: 8640030), Executor status:(isShutdown:false, isTerminated:false, isTerminating:false), in dubbo://ip:70882!, dubbo version: 2.6.2, current host: ip

dubbo线程池满了,我们通过重新设置线程池大小dubbo.provider.threads = 1000

3.调大线程池后又出现了另外一个问题,Redis连接数跑满了

org.springframework.data.redis.RedisConnectionFailureException: No reachable node in cluster; nested exception is redis.clients.jedis.exceptions.JedisNoReachableClusterNodeException: No reachable node in cluster

redis连接数跑满了,这个问题寻找了好久,最终发现是Jedis的版本问题版本问题,导致链接没有释放,连接泄露,我们通过升级jedis版本到2.10.2就解决了这个问题。

详情见这里https://blog.csdn.net/RL_LEEE/article/details/99831991

4.修复了上面的问题后,又出现了redis连接池跑满了问题

org.springframework.dao.InvalidDataAccessApiUsageException: Could not get a resource since the pool is exhausted; nested exception is redis.clients.jedis.exceptions.JedisExhaustedPoolException: Could not get a resource since the pool is exhausted

redis连接池数量太小了,我们通过增大spring.redis.jedis.pool.max-idle = 100,spring.redis.jedis.pool.max-active = 100,这两个配置重新进行了调整。

5.连接池跑满了的问题解决了,紧接着又出现了热点Key的分布不均匀的问题

redis.clients.jedis.exceptions.JedisClusterMaxRedirectionsException: Too many Cluster redirections?

这个是一个热点大Key的问题,把一个在高峰期会频繁访问的对象全部缓存成一个大对象放到redis里面,最终导致这个对象的大小超过了5MB,因为redis是单线程,每次读取5MB然后再进行传输,会导致网络io上升,并发数上来后,很容易把热点Key所在的节点给压挂。

解决方法就是将整存整取的大对象,分拆为多个小对象。可以尝试将对象分拆成几个key-value, 使用multiGet获取值,这样分拆的意义在于分拆单次操作的压力,将操作压力平摊到多个redis实例中,降低对单个redis的IO影响。这里可以参见我另外一篇文章https://www.cnblogs.com/lingyejun/p/12539694.html

6.最终,将上面的问题都解决了之后事故得以最终解决,特此记录,备忘。

如果对您有帮助,请不要忘了给翎野君点赞。


目录
相关文章
|
7月前
|
人工智能 开发工具
Gartner®榜单发布 | 阿里云获评全部GenAI 4大细分技术领域新兴领导者
Gartner®榜单发布 | 阿里云获评全部GenAI 4大细分技术领域新兴领导者
|
SQL Java 数据库
Springboot整合JPA 多表关联操作 @Query
Springboot整合JPA 多表关联操作 @Query
1169 0
Springboot整合JPA 多表关联操作 @Query
|
4月前
|
缓存 NoSQL 算法
高并发秒杀系统实战(Redis+Lua分布式锁防超卖与库存扣减优化)
秒杀系统面临瞬时高并发、资源竞争和数据一致性挑战。传统方案如数据库锁或应用层锁存在性能瓶颈或分布式问题,而基于Redis的分布式锁与Lua脚本原子操作成为高效解决方案。通过Redis的`SETNX`实现分布式锁,结合Lua脚本完成库存扣减,确保操作原子性并大幅提升性能(QPS从120提升至8,200)。此外,分段库存策略、多级限流及服务降级机制进一步优化系统稳定性。最佳实践包括分层防控、黄金扣减法则与容灾设计,强调根据业务特性灵活组合技术手段以应对高并发场景。
1100 7
|
12月前
|
安全 关系型数据库 MySQL
mysql8.0 正值表达式Regular expressions (sample database classicmodels _No.5)
本文介绍了MySQL8.0中的正值表达式及其相关函数,通过实例展示了如何使用正则表达式进行字符串匹配,并提出了关于执行效率的问题。
288 1
|
存储 安全 Java
javax.security.auth.login.LoginException: Unable to obtain password from user
假设我们公司有自己的门户网站,现在我们收购了一家公司,他们数据库采用ldap存储用户数据,那么为了他们账户能登陆我们公司项目所以需要集成,而不是再把他们的账户重新在mysql再创建一遍,万一人家有1W个账户呢,不累死了且也不现实啊。我之所以选这么旧的版本,是因为我最后要在自己项目集成,我们项目就是上面版本附近的,所以不能选太高版本,这点请注意各版本之间的兼容性问题。:如果里面的某些配置不知道在哪或者不知道干啥的,可以看我的前面的博客,详细介绍了安装配置等,可以大致了解参数。
293 9
|
监控 NoSQL Redis
Asynchronous AOF fsync is taking too long (disk is busy?). Writing the AOF buffer without waiting for fsync to complete, this may slow down Redis.
Asynchronous AOF fsync is taking too long (disk is busy?). Writing the AOF buffer without waiting for fsync to complete, this may slow down Redis.
|
Linux Shell
28. 【Linux教程】删除环境变量
28. 【Linux教程】删除环境变量
449 0
|
SQL 存储 安全
开发实战(6)--对fofa收集的漏洞资产使用poc进行批量验证
主要还是围绕渗透测试的流程进行开发,一般在信息收集后,在渗透测试后,在发现通用型漏洞时,我们为了节省时间,可以通过写批量脚本来信息收集,然后使用poc来进行批量验证,本篇是一个编写批量验证python的示例.
|
JavaScript 前端开发 API
使用Python和Vue构建多用户协作平台的终极指南
【4月更文挑战第11天】本指南介绍了如何使用Python和Vue.js构建多用户协作平台。首先确保安装Node.js、Python 3.x、pip和git。使用Flask搭建后端,设计RESTful API实现用户注册、登录等功能。前端利用Vue.js创建组件,结合Vuex和Vue Router处理状态管理和页面路由。通过Axios与后端通信,实现用户交互和数据同步。完成后进行测试,用Docker容器化应用并选择云服务部署。随着需求和技术发展,持续迭代和完善平台。
388 0