一、分片集群簡介:
關於MongoDB的復制集,復制集主要用來實現自動故障轉移從而達到高可用的目的,然而,隨着業務規模的增長和時間的推移,業務數據量會越來越大,當前業務數據可能只有幾百GB不到,一台DB服務器足以搞定所有的工作,而一旦業務數據量擴充大幾個TB幾百個TB時,就會產生一台服務器無法存儲的情況,此時,需要將數據按照一定的規則分配到不同的服務器進行存儲、查詢等,即為分片集群。分片集群要做到的事情就是數據分布式存儲。
二、集群示意圖及相關概念:
從圖中可以看到有四個組件:mongos、config server、shard、replica set;
- mongos,數據庫集群請求的入口,所有的請求都通過mongos進行協調,不需要在應用程序添加一個路由選擇器,mongos自己就是一個請求分發中心,它負責把對應的數據請求請求轉發到對應的shard服務器上。在生產環境通常有多mongos作為請求的入口,防止其中一個掛掉所有的mongodb請求都沒有辦法操作。
- config server,顧名思義為配置服務器,存儲所有數據庫元信息(路由、分片)的配置。mongos本身沒有物理存儲分片服務器和數據路由信息,只是緩存在內存里,配置服務器則實際存儲這些數據。mongos第一次啟動或者關掉重啟就會從 config server 加載配置信息,以后如果配置服務器信息變化會通知到所有的 mongos 更新自己的狀態,這樣 mongos 就能繼續准確路由。在生產環境通常有多個 config server 配置服務器,因為它存儲了分片路由的元數據,這個可不能丟失!就算掛掉其中一台,只要還有存貨, mongodb集群就不會掛掉。
shard,這就是傳說中的分片了。上面提到一個機器就算能力再大也有天花板,就像軍隊打仗一樣,一個人再厲害喝血瓶也拼不過對方的一個師。俗話說三個臭皮匠頂個諸葛亮,這個時候團隊的力量就凸顯出來了。在互聯網也是這樣,一台普通的機器做不了的多台機器來做,如下圖:
一台機器的一個數據表 Collection1 存儲了 1T 數據,壓力太大了!在分給4個機器后,每個機器都是256G,則分攤了集中在一台機器的壓力。也許有人問一台機器硬盤加大一點不就可以了,為什么要分給四台機器呢?不要光想到存儲空間,實際運行的數據庫還有硬盤的讀寫、網絡的IO、CPU和內存的瓶頸。在mongodb集群只要設置好了分片規則,通過mongos操作數據庫就能自動把對應的數據操作請求轉發到對應的分片機器上。在生產環境中分片的片鍵可要好好設置,這個影響到了怎么把數據均勻分到多個分片機器上,不要出現其中一台機器分了1T,其他機器沒有分到的情況,這樣還不如不分片!
- replica set,上兩節已經詳細講過了這個東東,怎么這里又來湊熱鬧!其實上圖4個分片如果沒有 replica set 是個不完整架構,假設其中的一個分片掛掉那四分之一的數據就丟失了,所以在高可用性的分片架構還需要對於每一個分片構建 replica set 副本集保證分片的可靠性。
三、集群環境搭建:
- 集群架構:如圖:
(仲裁節點暫時不要)
- 系統環境:Centos7.5、MongoDB4.0.12、關閉防火牆
三台機器的配置服務(27018)形成復制集,分片1、2、3也在各機器都部署一個實例,它們之間形成復制集,客戶端直接連接3個路由服務與之交互,配置服務和分片服務對客戶端是透明的。
- 環境准備好了,准備安裝:
- 防火牆關閉並重啟服務器: 1>systemctl stop firewalld//臨時關閉 ;systemctl disable firewalld//禁止開機啟動;
2>重啟linux服務器命令:reboot; 確保服務器互通;
- 分別在每台機器新建mongo目錄 (sudo -s ) -->(cd /usr/local/softs)--> (mkdir mongo) ;切換到mongo目錄 (cd mongo);
- 下載解壓mongodb至mongo目錄,我用的是 mongodb-linux-x86_64-4.0.12.tgz;(tar xvzf mongodb-linux-x86_64-4.0.12.tgz)
- 分別在每台機器的mongo目錄下建立完整目錄:
#配置、節點1、2、3的數據庫存放目錄mkdir -p data/config
mkdir -p data/shard1
mkdir -p data/shard2
mkdir -p data/shard3#配置、路由、節點1、2、3的日志存放目錄
touch log/config.log
touch log/mongos.log
touch log/shard1.log
touch log/shard2.log
touch log/shard3.log#配置、路由、節點1、2、3的配置文件存放目錄
touch conf/config.conf
touch conf/mongos.conf
touch conf/shard1.conf
touch conf/shard2.conf
touch conf/shard3.conf - chmod -R 777 /usr/local/softs/mongo/ 目錄文件夾授權命令,如:chmod -R 777 /usr/local/softs/mongo/ 為mongo文件夾下的文件可見,可編輯
- config服務器部署:(3台服務器執行相同操作) 打開conf/config.conf文件(若沒權限執行授權命令)將如下數據拷貝:dbpath=/usr/local/softs/mongo/data/config
logpath=/usr/local/softs/mongo/log/config.log
port=27018
logappend=true
fork=true
maxConns=5000
#復制集名稱
replSet=configs
#置參數為true
configsvr=true
#允許任意機器連接
bind_ip=0.0.0.0 - mongos服務器部署:(3台服務器執行相同操作)打開conf/mongos.conf文件(若沒權限執行授權命令)將如下數據拷貝: systemLog:
destination: file
logAppend: true
path: /usr/local/softs/mongo/log/mongos.log
processManagement:
fork: true
# pidFilePath: /var/log/nginx/mongodbmongos.pid
# network interfaces
net:
port: 27017
bindIp: 0.0.0.0
#監聽的配置服務器,只能有1個或者3個 configs為配置服務器的副本集名字
sharding:
configDB: configs/10.238.220.135:27018,10.238.220.208:27018,10.238.220.237:27018 - 配置各分片服務器的副本集:(3台服務器執行相同操作)打開conf/shard1(shard2、shard3).conf文件(若沒權限執行授權命令)將如下數據拷貝: dbpath=/usr/local/softs /mongo/data/shard1 #其他2個分片對應修改為shard2、shard3文件夾
logpath=/usr/local/softs/mongo/log/shard1.log #其他2個分片對應修改為shard2.log、shard3.log
port=27001 #其他2個分片對應修改為27002、27003
logappend=true
fork=true
maxConns=5000
storageEngine=mmapv1
shardsvr=true
replSet=shard1 #其他2個分片對應修改為shard2、shard3
bind_ip=0.0.0.0 - 目前為止,各服務器的mongos、config、shard1、shard2、shard3都已配置完成,接下來我們需要一一啟動,初始化順序 shard1->shard2->shard3->config->mongos
分別啟動三台服務器的分片1(shard1)服務:
mongodb-linux-x86_64-4.0.12/bin/mongod -f conf/shard1.conf
連接mongo,只需在任意一台機器執行即可:
mongodb-linux-x86_64-4.0.12/bin/mongo --port 27001
使用admin數據庫:use admin
其他2個分片對應修改為shard2、shard3;
config = { _id:"shard1", members:[
{_id:0,host:"10.238.220.135:27001"},
{_id:1,host:"10.238.220.208:27001"},
{_id:2,host:"10.238.220.237:27001"}
]
}
#初始化副本集配置 rs.initiate(config);
#查看j狀態:rs.status()
分別啟動三台服務器的配置(config)服務:
mongodb-linux-x86_64-4.0.12/bin/mongod -f conf/config.conf
mongodb-linux-x86_64-4.0.12/bin/mongo --port 27018
config = { _id:"configs", members:[
{_id:0,host:"10.238.220.135:27018"},
{_id:1,host:"10.238.220.208:27018"},
{_id:2,host:"10.238.220.237:27018"}
]
}
rs.initiate(config);rs.status()
分別啟動三台服務器的路由(mongos)服務:
mongodb-linux-x86_64-4.0.12/bin/mongos -f conf/mongos.conf
mongodb-linux-x86_64-4.0.12/bin/mongo --port 27017
config = { _id:"shard1", members:[
{_id:0,host:"10.238.220.135:27018"},
{_id:1,host:"10.238.220.208:27018"},
{_id:2,host:"10.238.220.237:27018"}
]
}
rs.initiate(config);rs.status()
#在任意一台路由服務器執行:
sh.addShard("shard1/10.238.220.135:27001,10.238.220.208:27001,10.238.220.237:27001")
sh.addShard("shard2/10.238.220.135:27002,10.238.220.208:27002,10.238.220.237:27002")
sh.addShard("shard3/10.238.220.135:27003,10.238.220.208:27003,10.238.220.237:27003")
sh.status();
測試:
use ycsb
sh.enableSharding("ycsb");
sh.shardCollection("ycsb.usertable",{"_id":"hashed"});
for(i=1;i<=50000;i++){db.usertable.insert({"id":i})}
db.stats();
問題總結:
數據庫集合的片鍵必須預置,集合有數據之后在設置片鍵會出現不自動分片的問題