1.redis批量删除key    

redis-cli keys '*' | xargs redis-cli del

2.从连接池获取jedis链接,不需要进行关闭操作,如果关闭会报redis.clients.jedis.exceptions.JedisException: Could not return the resource to the pool异常,原因是多个线程会用同一个pedis连接,如果其中一个关闭了,另外一个还在用,那么会出错。

jedis=jedisConnectionFactory.getConnection().getNativeConnection();

3.could not get a resources from the pool

  连接池的资源用完了,无法获取链接了,原因是没有归还的原因。

  实际上使用jedisPool不需要进行归还资源,只需要在有异常的时候quit()或者disconnect();

4.redis java.lang.Long cannot be cast to [B

  这是因为多个线程同时使用一个jedis连接导致

具体原因:假设jedis在执行这个命令的时候,因为redis超负荷,jedis可能返回超时的异常,这个时候发生了什么,没有处理这个异常,直接将这个jedis的链接返回到了连接池,这样有没有问题呢? 

查看jedis源码发现他的connection中对网络输出流做了一个封装,其中自建了一个buffer,所以当发生异常的时候,这个buffer里还残存着上次没有发送或者发送不完整的命令,这个时候没有做处理,直接将该连接返回到连接池,那么重用该连接执行下次命令的时候,就会将上次没有发送的命令一起发送过去,所以才会出现上面的错误“返回值类型不对”; 

所以正确的写法应该是在发送异常的时候,销毁这个连接,不能再重用! 

5.redis中保存的key-set形式的都不需要设置过期时间,并且update之前要先删除,并且保存进redis时必须原子性,即要不全都保存,要不全都不保存进去。

6.

Cannot get Jedis connection; nested exception is redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool

使用jedis的时候,没有将jedis return,导致过多的client连接

8

.Request processing failed; nested exception is com.alibaba.fastjson.JSONException: syntax error, expect {, actual error, pos 0

jedis不是线程安全的,当多个线程使用同一个jedis链接的时候,返回值就会发生混乱。

jedis使用的时候应该每个线程都有自己独立的jedis对象,利用jedispool配置,在pool中获取jedis对象,在出错的时候应该将jedis释放,不出错的时候不需要释放,新版本已经做了自动释放。

以上各种异常总结,使用redis时需要使用连接池,并且在连接错误或发生失败时释放该连接池。并且每个线程的链接要独立。

从jedis源码中,我们可以看出,当链接异常时调用的是:jedisPool.returnBrokenResource(jedis);

当链接正常返回时调用的是:jedisPool.returnResource(jedis);

继续跟进去可以看到returnBrokenResource()方法最终调用的是GenericObjectPool.invalidateObject(),

源代码如下:

public void invalidateObject(T obj) throws Exception {
         PooledObject<T> p = allObjects.get(obj);
         if (p == null) {
             if (isAbandonedConfig()) {
                 return;
             } else {
                 throw new IllegalStateException(
                         "Invalidated object not currently part of this pool");
             }
         }
         synchronized (p) {
             if (p.getState() != PooledObjectState.INVALID) {
                 destroy(p);
             }
         }
     }

最终实际处理销毁的代码就是de story()方法,跟进去可以看到逻辑很清晰:


private void destroy(PooledObject<T> toDestory) throws Exception {
         toDestory.invalidate();
         idleObjects.remove(toDestory);
         allObjects.remove(toDestory.getObject());
         try {
             factory.destroyObject(toDestory);
         } finally {
             destroyedCount.incrementAndGet();
             createCount.decrementAndGet();
         }
     }

如果是正常返回的链接,调用的returnResource()方法,实际上最终执行的方法是:

resource.resetState();
 returnResourceObject(resource);

主要做如下处理:把链接返回到连接池,如果连接池设置了maxIdle最大空闲连接数,如果连接池中最大空闲连接数已经等于maxIdle,则会销毁这个链接;如果连接池设置了testOnReturn=true,则在返回前会先校验这个链接有效性,如果无效会被销毁。