redis + dubbo 高并发出现的问题及其解决思路

博客内容描述了在高并发场景下,由于Redis连接池的并发问题导致线程池耗尽,服务器挂机的现象。经过排查,发现在Redis获取和释放连接的过程中存在并发死锁,通过增加`synchronized`关键字解决并发问题,并通过压力测试验证了解决方案的有效性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

            dubbo报错问题解决,最终发现是redis process执行并发问题,引起服务器挂机
开始出现报错是
Thread pool is EXHAUSTED!Thread Name: %s, Pool Size: 200 (active: 200, core: 200, max: 200, largest: 200
从报错信息看是dubbo的线程池爆满了。
但是原因是什么呢,然后设置各种并发参数等优化,但是问题还是未得到解决。
然后再次判断为线程池的线程一直阻塞未能释放出来执行其他任务,那为什么线程一直处于阻塞状态,
按照正常线程池的线程执行完一个任务后就会变为空闲等待(底层代码实现是while循环一直判断是否有要执行的任务和缓存队列中是否有要执行的任务)
然后就利用jstack pid > file文件名 输出来看看dataServer服务的线程使用情况,发现一大堆redis报错。
"laizhan-fixed-thread-pool-thread-183" #405 daemon prio=5 os_prio=0 tid=0x0000000021448800 nid=0x3f64 waiting on condition [0x000000003ea2c000]
   java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for  <0x0000000082f9df40> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at org.apache.commons.pool2.impl.LinkedBlockingDeque.takeFirst(LinkedBlockingDeque.java:583)
at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:442)
at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:363)
at redis.clients.util.Pool.getResource(Pool.java:48)
at redis.clients.jedis.JedisPool.getResource(JedisPool.java:99)
at redis.clients.jedis.JedisPool.getResource(JedisPool.java:12)
at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.fetchJedisConnector(JedisConnectionFactory.java:155)
at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.getConnection(JedisConnectionFactory.java:251)
at org.springframework.data.redis.connection.jedis.JedisConnectionFactory$$FastClassBySpringCGLIB$$648e8c34.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:651)
at org.springframework.data.redis.connection.jedis.JedisConnectionFactory$$EnhancerBySpringCGLIB$$852a9acd.getConnection(<generated>)
at tv.laizhan.dataSvr.helper.RedisHelper.getJedis(RedisHelper.java:66)
at tv.laizhan.dataSvr.helper.RedisHelper.process(RedisHelper.java:76)
at tv.laizhan.dataSvr.helper.RedisHelper.process(RedisHelper.java:70)
at tv.laizhan.dataSvr.redis.ConfigRedis.findByKeyname(ConfigRedis.java:27)
at tv.laizhan.dataSvr.center.ConfigCenter.findByKeyname(ConfigCenter.java:34)
at tv.laizhan.dataSvr.conf.RedisConfig.getOneDay_exp(RedisConfig.java:108)
at tv.laizhan.dataSvr.redis.UserRedis.lambda$setExpVal$2(UserRedis.java:49)
at tv.laizhan.dataSvr.redis.UserRedis$$Lambda$55/340856506.process(Unknown Source)
at tv.laizhan.dataSvr.helper.RedisHelper.process(RedisHelper.java:78)
at tv.laizhan.dataSvr.helper.RedisHelper.process(RedisHelper.java:70)
at tv.laizhan.dataSvr.redis.UserRedis.setExpVal(UserRedis.java:47)
at tv.laizhan.dataSvr.center.UserCenter.scoreExpVal(UserCenter.java:299)
at tv.laizhan.dataSvr.affair.LoginAffair.lambda$login$0(LoginAffair.java:131)
at tv.laizhan.dataSvr.affair.LoginAffair$$Lambda$18/1993346104.process(Unknown Source)
at tv.laizhan.dataSvr.affair.AbsAffair.process(AbsAffair.java:38)
at tv.laizhan.dataSvr.affair.AbsAffair.process(AbsAffair.java:30)
at tv.laizhan.dataSvr.affair.LoginAffair.login(LoginAffair.java:87)
at com.alibaba.dubbo.common.bytecode.Wrapper29.invokeMethod(Wrapper29.java)
at com.alibaba.dubbo.rpc.proxy.javassist.JavassistProxyFactory$1.doInvoke(JavassistProxyFactory.java:46)
at com.alibaba.dubbo.rpc.proxy.AbstractProxyInvoker.invoke(AbstractProxyInvoker.java:72)
at com.alibaba.dubbo.rpc.protocol.InvokerWrapper.invoke(InvokerWrapper.java:53)
at com.alibaba.dubbo.rpc.filter.ExceptionFilter.invoke(ExceptionFilter.java:64)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
at com.alibaba.dubbo.monitor.support.MonitorFilter.invoke(MonitorFilter.java:65)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
at com.alibaba.dubbo.rpc.filter.TimeoutFilter.invoke(TimeoutFilter.java:42)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
at com.alibaba.dubbo.rpc.protocol.dubbo.filter.TraceFilter.invoke(TraceFilter.java:78)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
at com.alibaba.dubbo.rpc.filter.ContextFilter.invoke(ContextFilter.java:70)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
at com.alibaba.dubbo.rpc.filter.GenericFilter.invoke(GenericFilter.java:132)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
at com.alibaba.dubbo.rpc.filter.ClassLoaderFilter.invoke(ClassLoaderFilter.java:38)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
at com.alibaba.dubbo.rpc.filter.EchoFilter.invoke(EchoFilter.java:38)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:91)
at com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol$1.reply(DubboProtocol.java:113)
at com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.handleRequest(HeaderExchangeHandler.java:84)
at com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.received(HeaderExchangeHandler.java:170)
at com.alibaba.dubbo.remoting.transport.DecodeHandler.received(DecodeHandler.java:52)
at com.alibaba.dubbo.remoting.transport.dispatcher.ChannelEventRunnable.run(ChannelEventRunnable.java:82)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)


然后就往redis方向找,优化了下配置。
然后还是不行,最后尝试在redis获取链接并执行回收加上synchronized
public synchronized <T> T process(IRedisFunction<T> function, IRedisErrorFunction<T> errorFunction) {
        T reslt = null;
        Exception ee = null;
        Jedis jedis = getJedis();
        try {
            reslt = function.process(jedis);
}
code代码
}
  然后再各种并发压力测试,果然一切正常了不报错了。
分析应该是 redis获取链接并执行回收的过程并发导致redis占用的线程死锁,骨牌效应之后的线程连续出现死锁,
最后导致dubbo线程池爆满拒绝所有到来的请求,服务器就卡死无法服务了。
为了在Java面试中全面展示对RedisDubbo、RocketMQ、JVM、数据库和并发的理解,结合项目经验进行深度回答,你需要系统性地学习相关技术,并能够将理论知识与实际操作经验相结合。《Java面试深度解析:技术广度与项目经验》这本书为你提供了一个系统的框架,帮助你深入理解这些中间件的原理和最佳实践。 参考资源链接:[Java面试深度解析:技术广度与项目经验](https://wenku.youkuaiyun.com/doc/3gs6d6ffqk) 在准备面试时,建议你首先温习和深入理解每个技术点的核心原理和使用场景。例如,对于Redis,你需要掌握其作为缓存系统、消息中间件等多方面的应用,以及它的数据结构、持久化机制、事务支持和集群特性。同时,结合实际项目案例,讲述在项目中如何利用Redis解决性能瓶颈或缓存一致性的挑战。 对于Dubbo,你应该熟悉它的服务治理能力,如何通过注册中心进行服务发现,负载均衡策略,以及容错处理机制等。讲述在服务化架构中如何实现高可用性和扩展性时,结合具体的业务场景说明Dubbo的使用。 在RocketMQ方面,深入理解其作为消息队列的核心价值,包括消息传输的保证机制、消息顺序性处理、以及分布式系统中的应用案例。结合你项目中的具体使用经验,如何确保消息的可靠投递,以及在出现异常时如何进行快速问题定位和处理。 此外,JVM调优知识和数据库优化策略也是面试中的常考知识点。你需要了解JVM的内存模型、垃圾回收机制、性能监控与故障诊断方法。对于数据库,掌握事务的ACID特性、索引优化、SQL编写技巧和锁机制等。 在并发编程方面,深入掌握Java内存模型、线程安全问题、锁机制(如synchronized和ReentrantLock)、以及并发集合的使用场景和性能考量。结合项目经验,讨论你如何处理高并发访问、资源同步、线程池的使用策略等。 最后,准备面试时,除了技术细节,还应该练习如何清晰、有条理地表达你的思路,如何将技术问题与项目实际相结合,展现你的问题解决能力和实际操作经验。通过这些准备工作,你将能在面试中展现出对Java技术的深刻理解和丰富的项目实践经验。 参考资源链接:[Java面试深度解析:技术广度与项目经验](https://wenku.youkuaiyun.com/doc/3gs6d6ffqk)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值