MongoDB分布式集群
MongDB分布式集群能夠對數據進行備份,提高數據安全性,以及提高集群提高讀寫服務的能力和數據存儲能力。主要通過副本集(replica)對數據進行備份,通過分片(sharding)對大的數據進行分割,分布式存儲在不同節點上。
副本集(replica)
副本集由若干台服務器組成,分為三種角色:主服務器、副服務器、仲裁服務器。根據集群搭建的需求,仲裁服務器不是必需的。主服務器提供主要的對外讀寫的功能,副服務器作為備份。當主服務器不可用時,其余服務器根據投票選出一個新的主服務器,提供讀寫功能。因此,副本集可以提高集群的可用性。
分片(sharding)
分片主要是為減小高數據量和高吞吐量的數據庫應用對單機性能造成的壓力。將大的數據分片存儲在不同節點上,外部讀寫只操作相應的一個或一小部分節點,一次減少每個分片節點村春的數據量和處理的請求數 。
MongoDB集群架構
其中每個分片是一個副本集,副本集的結構如下圖
Mongo集群部署
注意:在生產環境中,配置服務器務必使用三個,而不是一個;每個分片節點都部署成副本集,而不是一個單獨的Mongo服務器
配置文件
配置文件用於在啟動mongod時加載配置,也可以使用該命令行啟動項,不過配置項很多的時候,命令行參數很多。所以應該把配置項都寫到配置文件中。每個節點都有一個配置文件。
配置文件主要包括以下配置項:
- dbpath = \ 指定數據的存放位置,必需項
- logpath = \ 指定日志的存放位置
- logappend = \ 日志以追加方式寫入
- pidfilepath = \ 存放啟動mongod是分配的進程號
- bind_ip = \ mongod監聽的ip,可以不設置,不設置時,通過機器的ip訪問
- port = \監聽的端口號,務必設置,默認的端口不安全
- directoryperdb = \為每個數據庫的數據分配一個存儲目錄,建議設置,數據更好管理
- journal=\ 啟用恢復日志,如果mongod意外退出,下一次啟動時會根據恢復日志進行恢復,但恢復日志所占空間比較大。建議設置true
- keyFile = \指定使用的key的路徑,集群中的所有節點都要使用相同的key才能相互連接。(在集群搭建完成之前,不應當使用keyFile,否則在部署副本集和分片時會出現沒有權限操作的情況)
- auth = \ 是否使用授權認證機制,集群使用時,應當使用auth=true,但在集群部署時不應該使用auth=true
- noprealloc = \ 是否預分配空間,預分配空間比較占空間;不預分配空間可能對性能有影響。
- replSet = \節點所屬副本集的名稱
- fork 務必將fork選項設置為true,否則當啟動節點的終端意外退出時,節點的運行進程會被殺掉
副本集部署
以下以部署一個有三個節點(一個primary,一個secondary, 一個arbiter)1rs0的副本集為例,並假設三個節點的hostname是:hostname_primary:1111, hostname_secondary:2222, hostname_arbiter:3333。其中端口號按需求定;另外,假設三個節點配置文件的路徑分別為:config_path_primary, config_path_secondary, config_path_arbiter。此時,配置文件中不應該設置keyFile和auth兩個配置項
replSet配置項應該設置為rs0,否則在下面的步驟中會遇到下面的錯誤
{ "ok" : 0, "errmsg" : "Attempting to initiate a replica set with name rs0, but command line reports rs1; rejecting", "code" : 93 }
部署步驟:
1.啟動三個節點
mongod -f config_path_primary mongod -f config_path_secondary mongod -f config_path_arbiter
2.在primary節點所在的機器登陸上primary節點
mongo --port 1111
3.初始化
rs.initiate({_id : "rs0", members : [{_id : 0, host : "hostname_primary:1111"}]})
結果應該如下
{"ok" : 1}
4.添加secondary節點
rs.add("hostname_secondary:2222")
結果如下
{"ok" : 1}
5.添加仲裁節點
rs.addArb("hostname_arbiter:3333")
結果還是如下:
{"ok" : 1}
到了這里,一個三個節點的副本集rs0就部署好了^-^,如果需要部署更多節點,執行步驟4。
現在運行
rs.conf()
可以看到如下結果:
{ "_id" : "rs1", "version" : 3, "members" : [ { "_id" : 0, "host" : "localhost:4094", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : { }, "slaveDelay" : 0, "votes" : 1 }, { "_id" : 1, "host" : "localhost:4095", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : { }, "slaveDelay" : 0, "votes" : 1 }, { "_id" : 2, "host" : "localhost:4096", "arbiterOnly" : true, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : { }, "slaveDelay" : 0, "votes" : 1 } ], "settings" : { "chainingAllowed" : true, "heartbeatTimeoutSecs" : 10, "getLastErrorModes" : { }, "getLastErrorDefaults" : { "w" : 1, "wtimeout" : 0 } } }
分片部署
分片部署就是要將幾個不同的副本集聯系起來。現在部署一個有三個配置服務器,一個mongos,一個分片的集群。
1.部署配置服務器,三個配置服務器的配置文件分別為:配置服務器也是mongod實例,所以需要在配置文件中指示其作為配置服務器運行,加上選項
configsvr=true
不應該有選項
replSet=rs0
因為它不是作為副本集的節點運行。
設三個配置服務器的hostname分別為: hostname_config_1, hostname_config_2, hostname_config_3,端口分別為:4444, 5555, 6666
啟動三個配置服務器:
mongod -f config_path_conf1 mongod -f config_path_conf2 mongod -f config_path_conf3
2.部署mongos服務器,設其hostname為host_name_mongos,端口為8888。其配置文件路徑為config_path_mongos,由於mongos不存儲數據,所以不需要dbpath 選項。同時由於mongos要從配置服務器上獲取集群的配置信息,所以需要制定配置服務器的hostname和端口,加上選項configdb
configdb = hostname_config_1:4444, hostname_config_2 : 5555, hostname_config_3 : 6666
啟動mongos服務器
mongos -f config_path_mongos
注意這里是mongos,不是mongod。不是我打錯字了!
3.在mongos所在機器登陸mongos服務器
mongo –port 8888
此時,運行
sh.status()
你會發現,shards一項里什么都沒有,這是因為我們還沒有給這個集群加分片。
4.添加rs0成為集群的分片
sh.addShard("rs0/hostname_primary:1111")
這里括號里面只需要是副本集名加上一個副本集中的成員即可,不一定要是primary節點。如:
sh.addShard("rs0/hostname_secondary:2222") sh.addShard("rs0/hostname_arbiter:3333")
也是可以的。如果得到如下結果:
{“shardAdded” : “rs1”, “ok” : 1}
那么添加分片節點成功了。現在再運行
sh.status()
得到的結果為
sharding version: { "_id" : 1, "minCompatibleVersion" : 5, "currentVersion" : 6, "clusterId" : ObjectId("559f7fc9d8cec40f5a0f7609") } shards: { "_id" : "rs0", "host" : "rs0/hostname_primary:1111,hostname_secondary:2222" } balancer: Currently enabled: yes Currently running: no Failed balancer rounds in last 5 attempts: 0 Migration Results for the last 24 hours: No recent migrations databases: { "_id" : "admin", "partitioned" : false, "primary" : "config" }
shards不為空了,rs成為了一個shard節點
權限認證設置
權限認證是非常重要的,生產環境中的集群必需有權限認證,而且需要比較嚴格的權限認證。
1.創建第一個用戶
在上面部署成功的集群上執行以下步驟,在數據庫admin中創建第一個具有最高root權限的用戶root:
use admin db.createUser({user : "root", pwd : "q,.wemr213oiz923*(*LNY", roles : [{role : "root", db : "admin"}]})
2.關閉所有上面部署的節點,可以用
db.shutdownServer()
也可以暴力kill
3.產生keyFile,並復制到每個運行集群節點的服務器上。
openssl rand -base64 741 > mongodb-keyfile chmod 600 mongodb-keyfile
4.在每個節點的配置文件中加上選項:
keyFile = <key_file_path>
5.在出mongos外的所有節點的配置文件中加上選項
auth = true
6.重啟所有節點,到此權限認證已經搞完了,現在就可以插入數據庫,並按需求添加用戶,賦予相應的權限。進行認證授權的函數為db.auth(), 例如:
db.auth("root", "<password>")
此時擁有root權限,可以進行一切操作。
- 其實三個節點可以分為兩種角色: 存儲數據的節點(primary和secondary), 不存儲數據的節點(arbiter), primary和secondary角色在存儲數據的節點間是動態變化的。
