天天看點

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,如需轉載請自行聯系原作者