MongoDB 3.4 shard 分片

數據壓力大到機器支撐不了的時候能否做到自動擴展?


在系統早期,數據量還小的時候不會引起太大的問題,但是隨着數據量持續增多,後續遲早會出現一臺機器硬件瓶頸問題的。而MongoDB主打的就是海量數據架構,他不能解決海量數據怎麼行!不行!“分片”就用這個來解決這個問題。


傳統數據庫怎麼做海量數據讀寫?其實一句話概括:分而治之。上圖看看就清楚了,如下 taobao嶽旭強在infoq中提到的 架構圖:


上圖中有個TDDL,是taobao的一個數據訪問層組件,他主要的作用是SQL解析、路由處理。根據應用的請求的功能解析當前訪問的sql判斷是在哪個業務數據庫、哪個表訪問查詢並返回數據結果。具體如圖:


說了這麼多傳統數據庫的架構,那Nosql怎麼去做到了這些呢?MySQL要做到自動擴展需要加一個數據訪問層用程序去擴展,數據庫的增加、刪除、備份還需要程序去控制。一但數據庫的節點一多,要維護起來也是非常頭疼的。不過mongodb所有的這一切通過他自己的內部機制就可以搞定!還是上圖看看mongodb通過哪些機制實現路由、分片:


從圖中可以看到有四個組件: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 副本集保證分片的可靠性。生產環境通常是 2個副本 + 1個仲裁。

說了這麼多,還是來實戰一下如何搭建高可用的mongodb集羣:

首先確定各個組件的數量,mongos 3個, config server 3個,數據分3片 shard server 3個,每個shard 有一個副本一個仲裁也就是 3 * 2 = 6 個,總共需要部署15個實例。這些實例可以部署在獨立機器也可以部署在一臺機器,我們這裏測試資源有限,只准備了 3臺機器,在同一臺機器只要端口不同就可以,看一下物理部署圖:


1、準備機器,IP分別設置爲: 192.168.4.200、192.168.4.201、192.168.4.202,並分別創建mongos 、config 、 shard1 、shard2、shard3對應目錄



#建立mongos及日誌目錄
mkdir -p /data/mongodbtest/mongos/log

#建立config server 數據文件存放目錄
mkdir -p /data/mongodbtest/config/data

#建立config server 日誌文件存放目錄
mkdir -p /data/mongodbtest/config/log

#建立shard1 數據文件存放目錄
mkdir -p /data/mongodbtest/shard1/data

#建立shard1 日誌文件存放目錄
mkdir -p /data/mongodbtest/shard1/log

#建立shard2 數據文件存放目錄
mkdir -p /data/mongodbtest/shard2/data

#建立shard2 日誌文件存放目錄
mkdir -p /data/mongodbtest/shard2/log

#建立shard3 數據文件存放目錄
mkdir -p /data/mongodbtest/shard3/data

#建立shard3 日誌文件存放目錄
mkdir -p /data/mongodbtest/shard3/log

2、規劃5個組件對應的端口號,由於一個機器需要同時部署 mongos、config server 、shard1、shard2、shard3,所以需要用端口進行區分。
這個端口可以自由定義,在本文 mongos爲 20000, config server 爲 21000, shard1爲 22001 , shard2爲22002, shard3爲22003.


3、在每一臺服務器分別啓動配置服務器(後臺運行)

/home/weixla/mongodb-3.4.0/bin/mongod --configsvr --replSet cfgReplSet --dbpath /data/mongodbtest/config/data --port 21000 --logpath /data/mongodbtest/config/log/config.log --fork


連接到任意一臺配置服務器上 

/home/weixla/mongodb-3.4.0/bin/mongo --host 192.168.4.200 --port 21000


創建配置服務器副本集

rs.initiate({_id:"cfgReplSet",configsvr:true,members:[{_id:0,host:"192.168.4.200:21000"},{_id:1,host:"192.168.4.201:21000"},{_id:2,host:"192.168.4.202:21000"}]})


4、在每一臺服務器分別啓動分片及副本集。(後臺運行)

在每一臺服務器分別以副本集方式啓動分片1

/home/weixla/mongodb-3.4.0/bin/mongod --shardsvr --replSet shard1ReplSet --port 22001 --dbpath /data/mongodbtest/shard1/data  --logpath /data/mongodbtest/shard1/log/shard1.log --fork --nojournal  


連接任意一臺分片服務器

/home/weixla/mongodb-3.4.0/bin/mongo --host 192.168.4.200 --port 22001


創建副本集並初始化

rs.initiate({_id:"shard1ReplSet",members:[{_id:0,host:"192.168.4.200:22001"},{_id:1,host:"192.168.4.201:22001"},{_id:2,host:"192.168.4.202:22001"}]})



同樣操作shar2  shard3

/home/weixla/mongodb-3.4.0/bin/mongod --shardsvr --replSet shard2ReplSet --port 22002 --dbpath /data/mongodbtest/shard2/data  --logpath /data/mongodbtest/shard2/log/shard2.log --fork --nojournal  

/home/weixla/mongodb-3.4.0/bin/mongod --shardsvr --replSet shard3ReplSet --port 22003 --dbpath /data/mongodbtest/shard3/data  --logpath /data/mongodbtest/shard3/log/shard3.log --fork --nojournal 


5、選擇一臺服務器啓動mongos路由服務。

/home/weixla/mongodb-3.4.0/bin/mongos  --configdbcfgReplSet/192.168.4.200:21000,192.168.4.201:21000,192.168.4.202:21000 --port  20000  --logpath  /data/mongodbtest/mongos/log/mongos.log --fork


登錄路由服務客戶端

/home/weixla/mongodb-3.4.0/bin/mongo --host 192.168.4.200 --port 20000


添加分片到集羣

sh.addShard("shard1ReplSet/192.168.4.200:22001,192.168.4.201:22001,192.168.4.202:22001")


依次添加shard2  shard3


sh.addShard("shard2ReplSet/192.168.4.200:22002,192.168.4.201:22002,192.168.4.202:22002")

sh.addShard("shard3ReplSet/192.168.4.200:22003,192.168.4.201:22003,192.168.4.202:22003")


6、Enable Sharding for a Database

sh.enableSharding("test")



7、Shard a Collection

sh.shardCollection("test.Log", { id: 1})



8、測試

use test

for(var i = 1; i <= 100000; i++){

  db.Log.save({id:i,"message":"message"+i});

}



從這個結果看來,1個分片 保存了1條,另一個分片保存了剩下的所有記錄,這是shard key的策略造成的,讓我們看下官方圖



那我們修改一下sharding key的策略爲hashed,重新插入數據


結果如下



這裏基本保持了數據的均衡。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章