PHP - MongoDB連接攻略


http://blog.163.com/lgh_2002/blog/static/44017526201261111044608/ 

使用PHP的Mongo擴展連接MongoDB。通過new Mongo對象建立數據庫連接。

class Mongo {
     public function __construct( $servers , $options = array ());
}

參數$server是PHP-MongoDB-Driver標准連接字符串格式
mongodb://[username:password@]host1[:port1][,host2[:port2:],…]/database

參數$options是一個數組。不同於標准MongoDB連接字符串,PHP-Mongo-Driver不將options拼接到連接字串中。

參數$options默認值:

$options = array (
     'connect' => true
);

可選配置:

$options = array (
     'connect' => true, // true表示Mongo構造函數中建立連接。
     'timeout' =>xxxx, // 配置建立連接超時時間,單位是ms
     'replicaSet' => 'name' , // 配置replicaSet名稱
     'username' => '' , // 覆蓋$server字符串中的username段,如果username包含冒號:時,選用此種方式。
     'password' => '' , // 覆蓋$server字符串中的password段,如果password包含符號@時,選用此種方式。
     'db' => '' // 覆蓋$server字符串中的database段
);

登陸驗證
MongoDB啟動參數包含—auth或—keyFile時,想要執行數據庫操作,需要先進行登陸驗證。
你可以在連接字符串中知道用戶名和密碼進行登陸。
當連接關閉,驅動程序會自動嘗試重新建立連接並且登陸。

<?php
$m = new Mongo( "mongodb://${username}:${password}@localhost" );
?>

當然也可以使用MongoDB::authenticate():方法進行登陸驗證。
此方法登陸驗證的數據庫連接在失效后,仍會自動嘗試建立連接,但不會自動嘗試重新進行登陸驗證。

<?php
$m = new Mongo();
$db = $m ->admin;
$db ->authenticate( $username , $password );
?>

Replica Sets
指定一個或多個數據庫服務器,且使用replicaSet選項連接。

<?php
$m = new Mongo( "mongodb://localhost:27017" , array ( 'replicaSet' => 'myReplicaSetName' ));
?>

PHP-Mongo-Driver會查詢在列出的數據庫服務器中,到底哪個是主服務器。列出的服務器中包含master服務器才能成功建立連接。如 果無法連接到所有列出服務器或在這些服務器中沒有找到master,將拋出MongoConnectionException異常。

當master出現異常,不能正常工作時,slaves會花一段時間來推選一台slave為新的master。在選舉期間,連接到數據庫的任何寫操作將被禁止(除到slaves讀操作不受影響)。

一旦master選舉完成,驅動程序在讀寫操作時將主動探測誰是新master,然后將以此作為主庫連接繼續常規操作。

關於更多Replica Sets,可以參考http://www.mongodb.org/display/DOCS/Replication

支持Socket連接(Domain Socket Support)
如果在本地運行MongoDB,那么可以通過socket文件連接到MongoDB。MongoDB默認會自動打開一個本地socket文件:/tmp/mongodb- .sock。

<?php
$m = new Mongo( "mongodb:///tmp/mongo-27017.sock" );
?>

如果你想通過socket進行驗證登錄需要顯示指定port為0以表示socket文件位置描述的結束。

連接池(connection pool)
建立連接是Driver最費時的工作。即時網絡良好,建立連接還是會花費數百毫秒。驅動程序建立了連接池增加連接復用,幫助你減少建立連接的開銷。

當創建一個Mongo實例,所有需要的鏈接都將從連接池中獲取(ReplicaSets模式下可能需要用到復數個連接,因為到每個成員都有一個連接)。
Mongo實例析構時,連接返回到連接池。PHP進程退出時會關閉連接池中所有的連接。

為什么我打開了那么多連接?
連接池可以保持大量的連接。事實上連接池確實保持了大量連接,我們來估算一下。

連接數和三方面有關:
connections_per_pool
理論上連接池對能保持連接數沒有限制(直到耗盡文件句柄限制為止)。但實際應用中,使用完的連接將返回到連接池以便重復利用。在同一scope中新建新多個連接,這樣就無法重復利用連接池了,這么做需要慎重。
通過MongoPool::info()函數可以查看當前使用的連接數。連接數的修改統計到”in use”和”in pool”兩個域,分別表示使用中的連接數 和 空閑的連接數。

pools_per_process
對於每台MongoDB服務器地址都有自己的連接池。
例如通過”example.net”, “example.net:27017″, “localhost:27017″, “/tmp/mongodb-27017.sock”會對應生成3個連接池。詳情參見MongoPool::info()。

processes
PHP進程間的連接池都是獨立的。php-fpm和Apache一般會有N個php子進程。確認配置文件中設置的php-fpm最大子進程數。
使用PHP-FPM的情況,保險起見,以max_children和spare_servers+start_servers中較大者為最大處理子進程數,也就是最多有那么多組連接池。

估算最大的連接數,用上面三個變量相乘:

connections_per_pool*pools_per_process*processes

假設我們每個連接池有30個連接,每個PHP進程有10個連接池,總共有128個PHP進程。那么這台機器就有38400個連接。操作系統的最大文件句柄數限制要設置得足夠高。
點擊查看更多MongoPool信息。

長連接(Persistent Connections)
注:本節特性適用於1.2.0或以上版本。1.2.0+后,所有連接都是持久連接並且由連接池管理。

使用長連接的直接原因是效率高。因為連接復用而省去了大量的創建連接的開銷。長連接由PHP進程維護。

舉個簡單的例子,寫段程序連接1000次數據庫:

<?php
for ( $i =0; $i <1000; $i ++) {
   $m = new Mongo();
}
?>

這段代碼執行了大約18秒。我們看看改用長連接的情況:

<?php
for ( $i =0; $i <1000; $i ++) {
   $m = new Mongo( "localhost:27017" , array ( "persist" => "x" ));
}
?>

執行代碼花費時間小於0.2秒,因為只建立了一個數據庫連接。

建立長連接需要一個標識字串(如上例中的x)確保唯一性。需要復用一個長連接,域名、端口、標識字串、用戶名和密碼(如果有密碼的話)都需要完全匹配。否則就會創建一個不同的長連接。

記得在生產環境中總是推薦使用長連接,除非你有強而有力的理由讓你不那么做。這些理由多數和關系型數據庫有關,而且和MongoDB沒有半毛錢關系。

最佳實踐
強烈建議在新建Mongo對象時加上try/catch,因為如果連接失敗時在輸出的異常信息里會包含username/password對(php默認設置會顯示異常和錯誤信息)。

try {
$m = new Mongo( "mongodb://${username}:${password}@host" );
} catch (Exception $e ){


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM