转载:https://blog.csdn.net/qq403580298/article/details/82937579
今天尝试Redis的分布式锁,因为没有分布式环境,使用多线程来代替,但是在使用多线程的时候,总是会有
redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketException: Socket closed或者
1
2
3
4
5
6
7
8
|
Caused by: redis.clients.jedis.exceptions.JedisException: Could not
return
the resource to the pool
at redis.clients.util.Pool.returnResourceObject(Pool.java:
69
)
at redis.clients.jedis.JedisPool.returnResource(JedisPool.java:
253
)
...
14
more
Caused by: java.lang.IllegalStateException: Object has already been returned to
this
pool or is invalid
at org.apache.commons.pool2.impl.GenericObjectPool.returnObject(GenericObjectPool.java:
538
)
at redis.clients.util.Pool.returnResourceObject(Pool.java:
67
)
...
15
more
|
1
2
3
4
5
6
7
8
9
10
|
redis.clients.jedis.exceptions.JedisDataException: ERR Protocol error: invalid bulk length
at redis.clients.jedis.Protocol.processError(Protocol.java:
127
)
at redis.clients.jedis.Protocol.process(Protocol.java:
161
)
at redis.clients.jedis.Protocol.read(Protocol.java:
215
)
at redis.clients.jedis.Connection.readProtocolWithCheckingBroken(Connection.java:
340
)
at redis.clients.jedis.Connection.getStatusCodeReply(Connection.java:
239
)
at redis.clients.jedis.Jedis.set(Jedis.java:
139
)
at com.sunxj.redis.DistributeLock.lock(DistributeLock.java:
85
)
at com.sunxj.redis.DistributedLockTest.lambda$createThread$
0
(DistributedLockTest.java:
32
)
at java.lang.Thread.run(Thread.java:
748
)
|
1
2
3
4
5
6
7
|
Exception in thread
"Thread-71"
java.lang.ClassCastException: java.lang.Long cannot be cast to [B
at redis.clients.jedis.Connection.getBinaryBulkReply(Connection.java:
259
)
at redis.clients.jedis.Connection.getBulkReply(Connection.java:
248
)
at redis.clients.jedis.Jedis.lpop(Jedis.java:
1055
)
at us.codecraft.webmagic.scheduler.RedisScheduler.poll(RedisScheduler.java:
77
)
at us.codecraft.webmagic.Spider.run(Spider.java:
308
)
at java.lang.Thread.run(Thread.java:
748
)
|
主要问题就是在于Redis是一个单线程,多线程操作的话就会产生错误。首先看了一下Jconsole,发现大多数的线程都是Block状态

但是他们运行的特别慢,看了一下Runnable的线程,

可以发现线程卡在了SocketRead,name可以断定是Redis的问题,redis一直被卡住,所以才非常慢。
通过查阅论坛和搜索,可以知道是因为set函数被挂起了,导致最后set不成功。前辈的解释:
而如果我们配置了TestOnBorrow或者TestOnReturn,就会检测这是不是一个活的jedis。但是高并发下就会很多失败,就没有一些所以会被一直卡住,无法从redis获得数据。(不知道解释的对不对)有知道答案的请告诉我。。。
那我们应该怎么办呢?
1. 最简单的办法就是为每一个线程建立一个jedis对象,并且lock或者release的的方法传入jedis。
2. 但是这样总是觉得很别扭,应为这是线程池的问题,因此,我们可以将TestOnBorrow或者TestOnReturn都设置为false,同时如果set或者release失败了,我们直接返回,就不等待了!
两种方法都可以的。