一、问题描述
通过多线程基于jedis客户端并发访问redis做数据更新操作报“redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketException: Connection reset by peer: socket write error..java.lang.ArrayIndexOutOfBoundsException: 10803..”异常,详细日志如下
redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketException: Connection reset by peer: socket write error@b@ at redis.clients.jedis.Protocol.sendCommand(Protocol.java:94)@b@ at redis.clients.jedis.Protocol.sendCommand(Protocol.java:74)@b@ at redis.clients.jedis.Connection.sendCommand(Connection.java:80)@b@ at redis.clients.jedis.BinaryClient.set(BinaryClient.java:92)@b@ at redis.clients.jedis.Client.set(Client.java:24)@b@ at redis.clients.jedis.Jedis.set(Jedis.java:62)@b@ at com.xwood.publisher.util.JedisUtil.set(JedisUtil.java:66)@b@ at com.xwood.publisher.util.JedisUtil.setEncode(JedisUtil.java:48)@b@ at com.xwood.publisher.master.PublishEntityDataHandler.pushRemoteRedis(PublishEntityDataHandler.java:58)@b@ at com.xwood.publisher.master.PublishEntityDataHandler.run(PublishEntityDataHandler.java:33)@b@ at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:439)@b@ at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)@b@ at java.util.concurrent.FutureTask.run(FutureTask.java:138)@b@ at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:98)@b@ at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:206)@b@ at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)@b@ at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)@b@ at java.lang.Thread.run(Thread.java:662)@b@Caused by: java.net.SocketException: Connection reset by peer: socket write error@b@ at java.net.SocketOutputStream.socketWrite0(Native Method)@b@ at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)@b@ at java.net.SocketOutputStream.write(SocketOutputStream.java:136)@b@ at redis.clients.util.RedisOutputStream.flushBuffer(RedisOutputStream.java:31)@b@ at redis.clients.util.RedisOutputStream.write(RedisOutputStream.java:38)@b@ at redis.clients.jedis.Protocol.sendCommand(Protocol.java:80)@b@ ... 17 more@b@@b@java.lang.ArrayIndexOutOfBoundsException: 10803@b@ at redis.clients.util.RedisOutputStream.write(RedisOutputStream.java:40)@b@ at redis.clients.jedis.Protocol.sendCommand(Protocol.java:80)@b@ at redis.clients.jedis.Protocol.sendCommand(Protocol.java:74)@b@ at redis.clients.jedis.Connection.sendCommand(Connection.java:80)@b@ at redis.clients.jedis.BinaryClient.set(BinaryClient.java:92)@b@ at redis.clients.jedis.Client.set(Client.java:24)@b@ at redis.clients.jedis.Jedis.set(Jedis.java:62)@b@ at com.xwood.publisher.util.JedisUtil.set(JedisUtil.java:66)@b@ at com.xwood.publisher.util.JedisUtil.setEncode(JedisUtil.java:48)@b@ at com.xwood.publisher.master.PublishEntityDataHandler.pushRemoteRedis(PublishEntityDataHandler.java:58)@b@ at com.xwood.publisher.master.PublishEntityDataHandler.run(PublishEntityDataHandler.java:33)@b@ at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:439)@b@ at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)@b@ at java.util.concurrent.FutureTask.run(FutureTask.java:138)@b@ at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:98)@b@ at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:206)@b@ at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)@b@ at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)@b@ at java.lang.Thread.run(Thread.java:662)
二、解决方法
1. 方法一:基于jedis的Pipeline,具体用法示例参考其他更多文章页
2. 方法二:将原有的异步多线程池处理改为主线程处理,在在性能上区别不大,具体修改对比如下
原来的代码如下
for(Map m:datas){@b@ waiting_ha_entitys.add(new PublishEntityDataHandler(ha_entity,ii));@b@}@b@ @b@ //多线程优化处理,降低数据库延时@b@ while(waiting_ha_entitys.remainingCapacity()>0){ @b@ if(waiting_ha_entitys.size()==0) @b@ break;@b@ @b@ f(SlaveProcesserHandler.getExecutor()!=null)@b@ SlaveProcesserHandler.getExecutor().execute(waiting_ha_entitys.poll()); @b@ } @b@ }
修改为
for(Map m:datas){@b@ waiting_ha_entitys.add(new PublishEntityDataHandler(ha_entity,ii,jpl));@b@ new PublishEntityDataHandler(ha_entity,ii).run(); //将PublishEntityDataHandler去掉Runable接口@b@}