天天看點

MongoDB(4.0)分片——大資料的處理之道

什麼是分片

高資料量和吞吐量的資料庫應用會對單機的性能造成較大壓力,大的查詢量會将單機的CPU耗盡,大的資料量對單機的存儲壓力較大,最終會耗盡系統的記憶體而将壓力轉移到磁盤IO上。

MongoDB分片是使用多個伺服器存儲資料的方法,以支援巨大的資料存儲和對資料進行操作。分片技術可以滿足MongoDB資料量大量增長的需求,當一台MongoDB伺服器不足以存儲海量資料或者不足以提供可接受的讀寫吞吐量時,我們就可以通過在多台伺服器上分割資料,使得資料庫系統能存儲和處理更多的資料。

MongoDB分片優勢

分片為應對高吞吐量與大資料量提夠了方法

  • 使用分片減少了每個分片需要處理的請求數,是以,通過水準擴充,群集可以提高自己的存儲容量。比如,當插入一條資料時,應用隻需要通路存儲這條資料的分片。
  • 使用分片減少了每個分片村存儲的資料

    分片的優勢在于提供類似線性增長的架構,提高資料可用性,提高大型資料庫查詢伺服器的性能。當MongoDB單點資料庫伺服器存儲成為瓶頸、單點資料庫伺服器的性能成為瓶頸或需要部署大型應用以充分利用記憶體時,可以使用分片技術。

    MongoDB分片群集的組成

  • Shard:分片伺服器,用于存儲實際的資料塊,實際生産環境中一個shard server 角色可以由幾台伺服器組成一個Peplica Set 承擔,防止主機單點故障。
  • Config Server:配置伺服器,存儲了整個分片群集的配置資訊,其中包括chunk資訊。
  • Routers:前端路由,用戶端由此接入,且讓整個群集看上去像單一資料庫,前端應用可以透明使用。

環境準備

  • 系統版本:CenTos 7
  • 軟體版本:MongoDB4.0
  • 關閉防火牆及selinux
    systemctl stop firewalld.service
    setenforce 0           
IP:172.16.10.26 IP:172.16.10.27 IP:172.16.10.29
mongos(27017)
config(30000)
shard1主節點(40001) shard1副節點(40001) shard1仲裁節點(40001)
shard2仲裁節點(40002) shard2主節點(40002) shard2副節點(40002)
shard1副節點(40003) shard1仲裁節點(40003) shard1主節點(40003)

部署MongoDB分片群集

群集部署的搭建思路,利用三台伺服器,分别安裝mongodb資料庫,每台伺服器建立五個執行個體(mongos、configs、shard1、shard2、shard3)。三台不同的伺服器上的相同名稱的執行個體,建立為一個複制集,分别包括主節點,副節點,仲裁節點。mongos不需建立複制集,config不需指定主副節點及仲裁節點,但是要建立複制集。三台伺服器的操作步驟略有差别,但是大多是都是重複操作,步驟完全一緻。

安裝MongoDB資料庫

安裝支援軟體和mongodb

yum install openssl-devel -y
tar zxf mongodb-linux-x86_64-rhel70-4.0.0.tgz -C /usr/local
mv /usr/local/mongodb-linux-x86_64-rhel70-4.0.0 /usr/local/mongodb  //解壓即完成安裝           

建立資料存儲目錄和日志存儲目錄

路由伺服器不存儲資料,是以就不需要建立資料存儲目錄,隻需建立config、shard1、shaed2、shard3即可,日志檔案建立完成之後還需要給予權限。

mkdir -p /data/mongodb/logs/
mkdir /etc/mongodb/
mkdir /data/mongodb/config/
mkdir /data/mongodb/shard{1,2,3}
touch /data/mongodb/logs/shard{1,2,3}.log
touch /data/mongodb/logs/mongos.log
touch /data/mongodb/logs/config.log
chmod 777 /data/mongodb/logs/*.log           

建立管理使用者,修改目錄權限

useradd -M -u 8000 -s /sbin/nologin mongo
chown -R mongo.mongo /usr/local/mongodb
chown -R mongo.mongo /data/mongodb           

設定環境變量

echo "PATH=/usr/local/mongodb/bin:$PATH" >> /etc/profile
source /etc/profile           

系統記憶體優化

ulimit -n 25000
ulimit -u 25000
sysctl -w vm.zone_reclaim_mode=0
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag  //*注意*這些優化都是臨時的,重新開機失效           

部署配置伺服器

建立配置檔案

#vim /etc/mongodb/config.conf
pidfilepath = /data/mongodb//logs/config.pid           //pid檔案位置
dbpath = /data/mongodb/config/                             //資料檔案存放位置
logpath = /data/mongodb//logs/config.log               //日志檔案位置
logappend = true                 
bind_ip = 0.0.0.0                                                     //監聽位址
port = 30000                                                           //端口号
fork = true 
replSet=configs                                                      //複制集名稱
configsvr = true
maxConns=20000                                                  //最大連接配接數           

将配置檔案發送到其他伺服器

scp /etc/mongodb/config.conf [email protected]:/etc/mongodb/
scp /etc/mongodb/config.conf [email protected]:/etc/mongodb/           
MongoDB(4.0)分片——大資料的處理之道

啟動config執行個體

mongod -f /etc/mongodb/config.conf  //三台伺服器操作一緻           

配置複制集(任一台操作即可)

mongo --port 30000                    //建議三台伺服器都進入資料庫,友善檢視角色變更
config={_id:"configs",members:[{_id:0,host:"172.16.10.26:30000"},{_id:1,host:"172.16.10.27:30000"},{_id:2,host:"172.16.10.29:30000"}]}    //建立複制集
rs.initiate(config)                //初始化複制集           
MongoDB(4.0)分片——大資料的處理之道
MongoDB(4.0)分片——大資料的處理之道

部署shard1分片伺服器

#vim /etc/mongodb/shard1.conf
pidfilepath = /data/mongodb//logs/shard1.pid
dbpath = /data/mongodb/shard1/
logpath = /data/mongodb//logs/shard1.log
logappend = true
journal = true
quiet = true
bind_ip = 0.0.0.0
port = 40001
fork = true
replSet=shard1
shardsvr = true
maxConns=20000           

scp /etc/mongodb/shard1.conf [email protected]:/etc/mongodb/
scp /etc/mongodb/shard1.conf [email protected]:/etc/mongodb/           

啟動shard1執行個體

mongod -f /etc/mongodb/shard1.conf  //三台伺服器操作一緻           

配置shard1複制集

在shard分片伺服器的建立中,需要注意的點是,不是在任一台伺服器上建立都能成功的,如果選擇在預先設定為仲裁節點的伺服器上建立複制集會報錯。以shard1分片伺服器為例,可以在172.16.10.26和172.16.10.27伺服器上建立複制集,在172.16.10.29上建立則會失敗,因為在複制集建立之前,172.16.10.29已經被設定為仲裁節點。

MongoDB(4.0)分片——大資料的處理之道
mongo --port 40001    //建議三台伺服器都進入資料庫,友善檢視角色變更
use admin
config={_id:"shard1",members:[{_id:0,host:"172.16.10.26:40001",priority:2},{_id:1,host:"172.16.10.27:40001",priority:1},{_id:2,host:"172.16.10.29:40001",arbiterOnly:true}]}
rs.initiate(config)           

部署shard2分片伺服器

#vim /etc/mongodb/shard2.conf
pidfilepath = /data/mongodb//logs/shard2.pid
dbpath = /data/mongodb/shard2/
logpath = /data/mongodb//logs/shard2.log
logappend = true
journal = true
quiet = true
bind_ip = 0.0.0.0
port = 40002
fork = true
replSet=shard2
shardsvr = true
maxConns=20000           

scp /etc/mongodb/shard2.conf [email protected]:/etc/mongodb/
scp /etc/mongodb/shard2.conf [email protected]:/etc/mongodb/           

啟動shard2執行個體

mongod -f /etc/mongodb/shard2.conf  //三台伺服器操作一緻           

配置shard複制集(非仲裁節點伺服器)

mongo --port 40002    //建議三台伺服器都進入資料庫,友善檢視角色變更
use admin
config={_id:"shard2",members:[{_id:0,host:"172.16.10.26:40002",arbiterOnly:true},{_id:1,host:"172.16.10.27:40002",priority:2},{_id:2,host:"172.16.10.29:40002",priority:1}]}
rs.initiate(config)           

部署shard3分片伺服器

#vim /etc/mongodb/shard3.conf
pidfilepath = /data/mongodb//logs/shard3.pid
dbpath = /data/mongodb/shard3/
logpath = /data/mongodb//logs/shard3.log
logappend = true
journal = true
quiet = true
bind_ip = 0.0.0.0
port = 40003
fork = true
replSet=shard3
shardsvr = true
maxConns=20000           

scp /etc/mongodb/shard3.conf [email protected]:/etc/mongodb/
scp /etc/mongodb/shard3.conf [email protected]:/etc/mongodb/           

啟動shard3執行個體

mongod -f /etc/mongodb/shard3.conf  //三台伺服器操作一緻           

mongo --port 40003    //建議三台伺服器都進入資料庫,友善檢視角色變更
use admin
config={_id:"shard3",members:[{_id:0,host:"172.16.10.26:40003",priority:1},{_id:1,host:"172.16.10.27:40003",arbiterOnly:true},{_id:2,host:"172.16.10.29:40003",priority:2}]}
rs.initiate(config);           

部署路由伺服器

pidfilepath = /data/mongodb/logs/mongos.pid
logpath=/data/mongodb/logs/mongos.log
logappend = true
bind_ip = 0.0.0.0
port = 27017
fork = true
configdb = configs/172.16.10.26:30000,172.16.10.27:30000,172.16.10.29:30000
maxConns=20000           

scp /etc/mongodb/mongos.conf [email protected]:/etc/mongodb/
scp /etc/mongodb/mongos.conf [email protected]:/etc/mongodb/           

啟動mongos執行個體

mongos -f /etc/mongodb/mongos.conf  //三台伺服器操作一緻*注意*這裡是“mongos”而非“mongod”           

啟用分片功能

mongo    //因為預設端口即是27017,是以此處不接端口号
mongos> use admin
mongos> sh.addShard("shard1/172.16.10.26:40001,172.16.10.27:40001,172.16.10.29:40001")
mongos> sh.addShard("shard2/172.16.10.26:40002,172.16.10.27:40002,172.16.10.29:40002")
mongos> sh.status()           //檢視群集狀态
//此處先添加兩各分片伺服器,還有一個,待會添加           
MongoDB(4.0)分片——大資料的處理之道

測試伺服器分片功能

設定分片chunk大小

mongos> use config
switched to db config
mongos> db.settings.save({"_id":"chunksize","value":1})   //設定塊大小為1M是友善實驗,不然就需要插入海量資料
WriteResult({ "nMatched" : 0, "nUpserted" : 1, "nModified" : 0, "_id" : "chunksize" })           

模拟寫入資料

mongos> use python
switched to db python
mongos> show collections
mongos> for(i=1;i<=50000;i++){db.user.insert({"id":i,"name":"jack"+i})}
//在python庫的user表中循環寫入五萬條資料
WriteResult({ "nInserted" : 1 })           

啟用資料庫分片

mongos>sh.enableSharding("python")
//資料庫分片就有針對性,可以自定義需要分片的庫或者表,畢竟也不是所有資料都是需要分片操作的           
MongoDB(4.0)分片——大資料的處理之道

為表建立的索引

建立索引的規則是不能一緻性太高,要具有唯一性,例如序号,比如性别這一類重複性太高的就不适合做索引

mongos> db.user.createIndex({"id":1})   //以”id“為索引           

啟用表分片

mongos> sh.shardCollection("python.user",{"id":1})           

檢視分片情況

mongos> sh.status()
--- Sharding Status --- 
            ···省略内容
  shards:
        {  "_id" : "shard1",  "host" : "shard1/172.16.10.26:40001,172.16.10.27:40001",  "state" : 1 }
        {  "_id" : "shard2",  "host" : "shard2/172.16.10.27:40002,172.16.10.29:40002",  "state" : 1 }
            ···省略内容
                        chunks:
                                shard1  3
                                shard2  3
                        { "id" : { "$minKey" : 1 } } -->> { "id" : 9893 } on : shard1 Timestamp(2, 0) 
                        { "id" : 9893 } -->> { "id" : 19786 } on : shard1 Timestamp(3, 0) 
                        { "id" : 19786 } -->> { "id" : 29679 } on : shard1 Timestamp(4, 0) 
                        { "id" : 29679 } -->> { "id" : 39572 } on : shard2 Timestamp(4, 1) 
                        { "id" : 39572 } -->> { "id" : 49465 } on : shard2 Timestamp(1, 4) 
                        { "id" : 49465 } -->> { "id" : { "$maxKey" : 1 } } on : shard2 Timestamp(1, 5)            

手動添加分片伺服器,檢視分片情況是否發生變化

mongos> use admin
switched to db admin
mongos> sh.addShard("172.16.10.26:40003,172.16.10.27:40003,172.16.10.29:40003")
mongos> sh.status()
--- Sharding Status --- 
           ···省略内容
  shards:
        {  "_id" : "shard1",  "host" : "shard1/172.16.10.26:40001,172.16.10.27:40001",  "state" : 1 }
        {  "_id" : "shard2",  "host" : "shard2/172.16.10.27:40002,172.16.10.29:40002",  "state" : 1 }
        {  "_id" : "shard3",  "host" : "shard3/172.16.10.26:40003,172.16.10.29:40003",  "state" : 1 }
           ···省略内容
                        chunks:
                                shard1  2
                                shard2  2
                                shard3  2
                        { "id" : { "$minKey" : 1 } } -->> { "id" : 9893 } on : shard3 Timestamp(6, 0) 
                        { "id" : 9893 } -->> { "id" : 19786 } on : shard1 Timestamp(6, 1) 
                        { "id" : 19786 } -->> { "id" : 29679 } on : shard1 Timestamp(4, 0) 
                        { "id" : 29679 } -->> { "id" : 39572 } on : shard3 Timestamp(5, 0) 
                        { "id" : 39572 } -->> { "id" : 49465 } on : shard2 Timestamp(5, 1) 
                        { "id" : 49465 } -->> { "id" : { "$maxKey" : 1 } } on : shard2 Timestamp(1, 5)