天天看点

Reids客户端Jedis的JedisSentinelPool关闭问题

  JedisSentinelPool使用一组MasterListener线程做主从复制的主服务器选举工作。其父类Pool的close, destory方法用来关闭正真的redis客户端连接池的对象。在JedisSentinelPool对象中重写了destory方法内容是在关闭选举线程之后,调用了父类destory方法;但是没有重写close方法,因而调用close方法不能关闭的掉MasterLinstener线程。Pool的另一个子类JedisPool则没有对close,destory方法做任何变动。

 JedisSentinelPool,JedisPool以及Pool之间的关系如下类图:

 查看Pool中close和destory的源码:

1

2

3

4

<code>@Override</code>

<code>public</code> <code>void</code> <code>close() {</code>

<code>  </code><code>closeInternalPool();</code>

<code>}</code>

<code>public</code> <code>void</code> <code>destroy() {</code>

 close方法实现自java.io.Closeable接口,Closeable是可以关闭的数据源或目标。调用 close 方法可释放对象保存的资源(如打开文件)从这一点看是没有问题的,如果是JDK1.7+的话,那更好了该接口继承了AutoCloseable接口。对于JedisPool而言调用close方法和调用destory效果是一样的,但JedisSentinelPool就不同了,创建JedisSentinelPool是启动了MasterLinstener线程,所以得调用destory方法来完成JedisSentinelPool所持有的资源释放,线程关闭。

 JedisSentinelPool的destory方法:

5

6

7

<code>  </code><code>for</code> <code>(MasterListener m : masterListeners) {</code>

<code>    </code><code>m.shutdown();</code>

<code>  </code><code>}</code>

<code>  </code><code>super</code><code>.destroy();</code>

 结论:如果要关闭的仅仅是Pool(Reids客户端连接池)则调用close,而要关闭主从复制中的主机检测即彻底关闭JedisSentinelPool则要调用destory方法。 

 意外想当然的调用close方法,并没能关闭MasterLinstener线程,并且MasterLinstener线程没有起个好名字,排查是看到的名字叫Thread-xx (xx是数字),这样很不方便排错。!!!所以启动线程起个好名字真的非常必要,这将对排错,诊断,系统监控有莫大的帮助。

本文转自 secondriver 51CTO博客,原文链接:http://blog.51cto.com/aiilive/1682260,如需转载请自行联系原作者