1. 程式人生 > 資料庫 >workerman寫mysql連線池的例項程式碼

workerman寫mysql連線池的例項程式碼

首先要了解為什麼用連線池,連線池能為你解決什麼問題

連線池主要的作用:

1、減少與資料伺服器建立TCP連線三次握手及連線關閉四次揮手的開銷,從而降低客戶端和mysql服務端的負載,縮短請求響應時間

2、減少資料庫的併發連線數,即解決應用伺服器過多導致的資料庫 too many connections 問題

如果是為了解決問題1

則在workerman中資料庫連線池不是最高效的方法,反而是自找麻煩的做法。由於PHP是單程序單執行緒的,使用PHP實現資料庫連線池,肯定需要用單獨的程序去做,那麼就會涉及到程序間的通訊,使得原本和mysql直接通訊的過程變成 與連線池再到mysql的通訊,增加了應用端的負載。

解決問題1最高效的方法是為每個業務程序建立一個數據庫單例(例如workerman提供的DB類),實現資料庫長連線,這樣每個程序的所有請求都使用自己的這一個資料庫長連線,整個程序的生命週期只有一次TCP握手和斷開連線揮手的開銷,並且應用與mysql直接通訊,沒有連線池那樣中間一層程序間IPC通訊,效能是最高的,沒有之一。

如果是為了問題2

首先看下自己到底有多少臺應用伺服器,每臺伺服器與mysql有多收併發連線。假如你只有10臺應用伺服器,每個伺服器50個程序,每個程序1個數據庫連線,那麼到mysql服務端總共只有10*50=500個併發連線(並非活躍連線),500個併發連線對於mysql來說就是小菜一碟,為了解決問題2完全沒有使用連線池的必要。

假如你有1000臺應用伺服器,那麼連線池是有必要的,但是這個連線池不能是執行在本地應用伺服器上的連線池,因為1000臺應用伺服器就有1000個連線池,即使每個連線池只開10個連線,那麼資料庫的連線數也會輕鬆打滿。所以不要指望在當前伺服器上開幾個task程序實現的連線池就能解決這個問題。

1000臺應用伺服器的叢集,每臺伺服器上搞幾個程序實現連線池同樣是不靠譜的方法。真正能夠解決問題2的方法是建立一個獨立的資料庫連線池伺服器或者說叢集,全域性管理所有的資料庫連結。

綜上所述,

如果單獨是為了問題1實現php的mysql連線池,那麼資料庫單例是比所謂的連線池更簡單更高效的做法。

如果是為了實現問題2,那麼想必業務也有一定的規模了,如果真心是想用workerman做個單獨的連線池叢集,下面是大概簡單的做法,建立一些task程序,每個程序建立一個數據庫連線,task程序收到sql請求後傳送給mysql伺服器,mysql伺服器返回後task程序再把結果發給sql發起者。

連線池程式碼類似如下 如果是多臺伺服器組成的連線池叢集,前面最好加一個lvs:

// task worker,使用Text協議

$task_worker = new Worker('Text://0.0.0.0:1234');

$task_worker->count = 64;

$task_worker->name = 'MysqlTask';

$task_worker->onMessage = function($connection,$sql)

{

   // 執行sql.... 得到結果,這裡省略....

   $sql_result = your_mysql_query($sql);

   // 傳送結果

   $connection->send(json_encode($sql_result));

};

在workerman中呼叫:

use \Workerman\Connection\AsyncTcpConnection;

 

// 與遠端連線池服務建立非同步連結,ip為遠端連線池服務的ip,如果是叢集就是lvs的ip

$sql_connection = new AsyncTcpConnection('Text://ip:1234');

// 傳送sql

$sql_connection->send("SELECT ... FROM .....");

// 非同步獲得sql結果

$sql_connection->onMessage = function($sql_connection,$sql_result)

{

   // 這裡只是列印結果

   var_dump(json_decode($task_result));

};

// 執行非同步連結

$sql_connection->connect();

以上就是本次介紹的workerman寫mysql連線池全部知識點,有任何補充可以聯絡我們小編。