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時,想要執行數據庫操作,需要先進行登陸驗證。
你可以在連接字符串中知道用戶名和密碼進行登陸。
當連接關閉,驅動程序會自動嘗試重新建立連接並且登陸。
當然也可以使用MongoDB::authenticate():方法進行登陸驗證。
此方法登陸驗證的數據庫連接在失效后,仍會自動嘗試建立連接,但不會自動嘗試重新進行登陸驗證。
<?php
$m
=
new
Mongo();
$db
=
$m
->admin;
$db
->authenticate(
$username
,
$password
);
?>
|
Replica Sets
指定一個或多個數據庫服務器,且使用replicaSet選項連接。
<?php
?>
|
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。
如果你想通過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默認設置會顯示異常和錯誤信息)。