mongodb分片機制原理前端
1、概念: mongodb
分片(sharding)是指將數據庫拆分,將其分散在不一樣的機器上的過程。將數據分散到不一樣的機器上,不須要功能強大的服務器就能夠存儲更多的數據和處理更大的負載。基本思想就是將集合切成小塊,這些塊分散到若干片裏,每一個片只負責總數據的一部分,最後經過一個均衡器來對各個分片進行均衡(數據遷移)。經過一個名爲mongos的路由進程進行操做,mongos知道數據和片的對應關係(經過配置服務器)。大部分使用場景都是解決磁盤空間的問題,對於寫入有可能會變差,查詢則儘可能避免跨分片查詢。使用分片的時機: docker
1,機器的磁盤不夠用了。使用分片解決磁盤空間的問題。數據庫
2,單個mongod已經不能知足寫數據的性能要求。經過分片讓寫壓力分散到各個分片上面,使用分片服務器自身的資源。centos
3,想把大量數據放到內存裏提升性能。和上面同樣,經過分片使用分片服務器自身的資源。bash
2、分片集羣架構(來自官網)服務器
上圖中主要有以下所述三個主要組件:網絡
Shard:分片服務器 架構
用於存儲實際的數據塊,實際生產環境中一個shard server角色可由幾臺機器組個一個replica set承擔,防止主機單點故障 運維
Config Server:配置服務器
mongod實例,存儲了整個 分片羣集的配置信息,其中包括 chunk信息。
Query Routers:前端路由
客戶端由此接入,且讓整個集羣看上去像單一數據庫,前端應用能夠透明使用
這裏的兩個shard(分片)至關於mongodb節點服務器,內部的塊是將order集合再切割的結果,隨着數據量的的增大,分片會分割和遷移,以知足數據的均勻分佈。
請求分流:經過路由節點將請求分發到對應的分片和塊中
數據分流:內部提供平衡器保證數據的均勻分佈,這是數據平均分佈式、請求平均分佈的前提
塊的拆分:3.4版本塊的最大容量爲64M或者10w的數據,當到達這個閾值,觸發塊的拆分,一分爲二
塊的遷移:爲保證數據在分片節點服務器分片節點服務器均勻分佈,塊會在節點之間遷移。通常相差8個分塊的時候觸發
MongoDB分片優點:
減小單個分片須要處理的請求數,提升羣集的存儲容量和吞吐量 好比,當插入一條數據時,應用只須要訪問存儲這條數據的分片 減小單分片存儲的數據,提升數據可用性,提升大型數據庫查詢服務的性能。 當MongoDB單點數據庫服務器存儲和性能成爲瓶頸,或者須要部署大型應用以充分利用內存時,可使用分片技術
環境準備
docker、docker-compose、lunux。版本問題應該不大,我用的是Docker version 18.09.0, build 4d60db四、docker-compose version 1.23.0-rc3, buildea3d406e、centos7.2。
本套Mongodb搭建分片集羣是基於mongodb4.0.5,直接從官方鏡像倉庫拉取docker pull mongo:4.0.5便可
完成準備以後,docker images看一下,mongodb.鏡像是否搞定了。
1.編寫yaml文件,這裏我命名fates-mongo-compose.yaml
version: '2' services: shard1: image: mongo:4.0.5 container_name: mongo_shard1 # --shardsvr: 這個參數僅僅只是將默認的27017端口改成27018,若是指定--port參數,可用不須要這個參數 # --directoryperdb:每一個數據庫使用單獨的文件夾 command: mongod --shardsvr --directoryperdb --replSet shard1 volumes: - /etc/localtime:/etc/localtime - /data/base/fates/mongo/shard1:/data/db privileged: true mem_limit: 16000000000 networks: - mongo shard2: image: mongo:4.0.5 container_name: mongo_shard2 command: mongod --shardsvr --directoryperdb --replSet shard2 volumes: - /etc/localtime:/etc/localtime - /data/base/fates/mongo/shard2:/data/db privileged: true mem_limit: 16000000000 networks: - mongo shard3: image: mongo:4.0.5 container_name: mongo_shard3 command: mongod --shardsvr --directoryperdb --replSet shard3 volumes: - /etc/localtime:/etc/localtime - /data/base/fates/mongo/shard3:/data/db privileged: true mem_limit: 16000000000 networks: - mongo config1: image: mongo:4.0.5 container_name: mongo_config1 # --configsvr: 這個參數僅僅是將默認端口由27017改成27019, 若是指定--port可不添加該參數 command: mongod --configsvr --directoryperdb --replSet fates-mongo-config --smallfiles volumes: - /etc/localtime:/etc/localtime - /data/base/fates/mongo/config1:/data/configdb networks: - mongo config2: image: mongo:4.0.5 container_name: mongo_config2 command: mongod --configsvr --directoryperdb --replSet fates-mongo-config --smallfiles volumes: - /etc/localtime:/etc/localtime - /data/base/fates/mongo/config2:/data/configdb networks: - mongo config3: image: mongo:4.0.5 container_name: mongo_config3 command: mongod --configsvr --directoryperdb --replSet fates-mongo-config --smallfiles volumes: - /etc/localtime:/etc/localtime - /data/base/fates/mongo/config3:/data/configdb networks: - mongo mongos: image: mongo:4.0.5 container_name: mongo_mongos # mongo3.6版默認綁定IP爲127.0.0.1,此處綁定0.0.0.0是容許其餘容器或主機能夠訪問 command: mongos --configdb fates-mongo-config/config1:27019,config2:27019,config3:27019 --bind_ip 0.0.0.0 --port 27017 ports: - 27017:27017 volumes: - /etc/localtime:/etc/localtime depends_on: - config1 - config2 - config3 networks: - mongo networks: mongo: external: true
具體含義看註釋
2.編寫deploy-and-start.sh腳本
#!/bin/sh docker-compose -f fates-mongo-compose.yaml up -d #睡眠兩分鐘,等待mongodb全部容器起來以後將它們配置加入分片 sleep 30s docker-compose -f fates-mongo-compose.yaml exec config1 bash -c "echo 'rs.initiate({_id: \"fates-mongo-config\",configsvr: true, members: [{ _id : 0, host : \"config1:27019\" },{ _id : 1, host : \"config2:27019\" }, { _id : 2, host : \"config3:27019\" }]})' | mongo --port 27019" docker-compose -f fates-mongo-compose.yaml exec shard1 bash -c "echo 'rs.initiate({_id: \"shard1\",members: [{ _id : 0, host : \"shard1:27018\" }]})' | mongo --port 27018" docker-compose -f fates-mongo-compose.yaml exec shard2 bash -c "echo 'rs.initiate({_id: \"shard2\",members: [{ _id : 0, host : \"shard2:27018\" }]})' | mongo --port 27018" docker-compose -f fates-mongo-compose.yaml exec shard3 bash -c "echo 'rs.initiate({_id: \"shard3\",members: [{ _id : 0, host : \"shard3:27018\" }]})' | mongo --port 27018" docker-compose -f fates-mongo-compose.yaml exec mongos bash -c "echo 'sh.addShard(\"shard1/shard1:27018\")' | mongo" docker-compose -f fates-mongo-compose.yaml exec mongos bash -c "echo 'sh.addShard(\"shard2/shard2:27018\")' | mongo" docker-compose -f fates-mongo-compose.yaml exec mongos bash -c "echo 'sh.addShard(\"shard3/shard3:27018\")' | mongo"
該腳本流程詳細描述一下
1)先啓動mongodb分片容器組
2) 睡眠30s等待容器所有徹底啓動(可能不須要30s)
3)操做config1,配置config副本集,將config*容器組做爲config角色,此時config1做爲config副本集裏的主節點
4)操做shard一、shard二、shard3,將shard*容器組做爲shard角色。
5)將shard一、shard二、shard3加入分片集羣組。
3.運行
執行腳本
# sh deploy-and-start.sh 等待腳本啓動完成,若是出現connect fail報錯,檢查一下網絡,再次啓動一次腳本便可。
到這裏,單機版的mongodb的分片集羣,就搭建好了,通常真正的運維環境,Mongodb集羣應該分佈在不一樣的機器,可是隻要熟悉這套部署方案的機制,只要稍做修改,就能夠實現。
可是,Mongodb庫默認是不會將你的表進行分片的,是須要手動配置的,若是不配置,數據都會所有存放在主節點,不會均勻分配到各個分片。
如今手動將一個表作分片,就拿um_t_staff表做爲例子
//前提是分片的片鍵必須是索引
sh.enableSharding("'mongodbDemo")//先讓當前庫支持分片
sh.shardCollection('mongodbDemo.um_t_staff',{timestamp:1})//當前集合加入分片,遞增片鍵(timestamp已經做爲索引了)
db.adminCommand("flushRouterConfig")//刷新路由
sh.enableBalancing("mongodbDemo.um_t_staff")//讓當前分片支持平衡
sh.startBalancer() //開啓平衡
sh.status({"verbose":1})//查看詳細分片信息
db.um_t_staff.getShardDistribution()//查看該表分片數據信息
OK 。docker-compose搭建分片集羣已經大功告成了。
感謝前輩的技術輸出。參考博文: http://www.javashuo.com/article/p-qgrjmyxx-hh.html