1. 程式人生 > >連接池的實現

連接池的實現

init true strong map lock 可能 實施 避免 ret

1. 背景

工程架構中有很多訪問下遊的需求,下遊包括但不限於服務/數據庫/緩存,其通訊步驟為:

(1)與下遊建立一個連接

(2)通過這個連接,收發請求

(3)交互結束,關閉連接,釋放資源

2. 為什麽需要連接池?

當並發量很低的時候,建立連接和關閉連接的過程是沒問題的,但當服務單機QPS達到幾百、幾千的時候,建立連接和銷毀連接就會成為瓶頸,此時如何優化?

結論很簡單,服務啟動的時候,先建立好若幹連接Array[Connection],但有請求過來的時候,從Array中取出一個,執行下遊操作,執行完再放回,從而避免反復的建立和銷毀連接,以提升性能。

而這個對Array[Connection]進行維護的數據結構,就是連接池

3. 連接池核心接口和實現

通過上面的討論,可以看到連接池ConnectionPool主要有三個核心接口

(1)Init:初始化好Array[Connection],這個接口只在服務啟動時調用一次;

(2)GetConnection:請求每次需要訪問數據庫時,不是connect一個連接,而是通過連接池的這個接口拿連接;

(3)FreeConnection:請求每次訪問完數據庫時,不是關閉一個連接,而是把這個連接放回連接池。

連接池核心數據結構

(1)連接數據Array[Connection]

(2)互斥鎖數組Array lock[N]

連接池核心接口實現:

Init() {
 for i = 1 to N {
  Array Connection [i] = new();
  Array Connection [i]->connect();
  Array lock[i] = 0;
 }
}
說明:把所有連接和互斥鎖初始化

GetConnection()
 for i = 1 to N {
  if(Array lock[i] == 0) {
   Array lock[i] = 1;
   return Array Connection[i];
   }
 }
}
說明:找一個可用的連接,鎖住,並返回連接

FreeConnection(c)
 for i = 1 to N {
 if(Array Connection [i] == c) {
   Array lock[i] = 0;
   }
  }
}
說明:找到連接,把鎖釋放

技術分享圖片

4. 細節

(1)如果連接全部被占用,是返回失敗,還是讓上遊等待?

(2)需要實施連接可用性檢測;

(3)為了讓調用方更友好,可能還需要包裝一層DAO層,讓“連接”對調用方都是黑盒的;

(4)通過freeArray,connectionMap可以讓取連接和放回連接都達到O(1)時間復雜度;

(5)可以通過hash實現id串行化;

(6)負載均衡、故障轉移、服務自動擴容都可以在這一層實現。

連接池的實現