? ? ? ? 負(fù)載均衡及高可用一直是我們線上服務(wù)架構(gòu)所關(guān)注的重點(diǎn)鹿驼,本文內(nèi)容乌叶,將介紹如何在 Docker 環(huán)境下實(shí)現(xiàn) MongoDB 的副本集及分片否副。
? ? ? ? 在 MongoDB 中壹粟,副本集是一組實(shí)現(xiàn)了復(fù)制功能的服務(wù)器伯铣,其中一個(gè)是主服務(wù)器(Primary)呻此,用于處理客戶端請(qǐng)求;其余為備份服務(wù)器(Secondary)腔寡,用于保存主服務(wù)器的副本焚鲜。如果主服務(wù)器出現(xiàn)故障,備份服務(wù)器將推舉出其中一個(gè)成員為主服務(wù)器,繼續(xù)響應(yīng)請(qǐng)求忿磅。分片(Sharding)是將數(shù)據(jù)拆分并分散存放在不同機(jī)器上糯彬,這樣不需要功能強(qiáng)大的大型計(jì)算機(jī)就可以存儲(chǔ)更多的數(shù)據(jù),處理更大的負(fù)載葱她。MongoDB 的分片機(jī)制允許你創(chuàng)建一個(gè)包含許多臺(tái)機(jī)器的集群撩扒,將數(shù)據(jù)子集分散在集群中,每個(gè)分片維護(hù)著一個(gè)數(shù)據(jù)集合的子集吨些。與單機(jī)服務(wù)器和副本集相比搓谆,集群架構(gòu)可以使應(yīng)用程序具有更大的數(shù)據(jù)處理能力。
? ? ? ? 副本集是讓多臺(tái)服務(wù)器都擁有同樣的數(shù)據(jù)副本豪墅,每一臺(tái)服務(wù)器都是其他服務(wù)器的鏡像泉手,而每一個(gè)分片都擁有和其他分片不同的數(shù)據(jù)子集。
? ? ? ? 分片的目標(biāo)之一是創(chuàng)建一個(gè)擁有5臺(tái)偶器、500臺(tái)甚至更多機(jī)器的集群斩萌,整個(gè)集群對(duì)應(yīng)用程序來(lái)說(shuō)就像是一臺(tái)單機(jī)服務(wù)器。為了對(duì)應(yīng)用程序隱藏?cái)?shù)據(jù)庫(kù)架構(gòu)的細(xì)節(jié)状囱,在分片之前要先執(zhí)行 mongos 進(jìn)行一次路由過(guò)程术裸。這個(gè)路由服務(wù)器維護(hù)著一個(gè)“內(nèi)容列表”,指明了每個(gè)分片包含哪些數(shù)據(jù)內(nèi)容亭枷。應(yīng)用程序只需要連接到路由服務(wù)器袭艺,就可以像使用單機(jī)服務(wù)器一樣進(jìn)行正常的請(qǐng)求了。
? ? ? ? 那么是不是在業(yè)務(wù)剛起步時(shí)就進(jìn)行分片呢叨粘?不然猾编。分片不止會(huì)增加部署的操作復(fù)雜度,還要求做出設(shè)計(jì)決策升敲,而該決策以后很難再更改答倡,所以不必太早分片,但也不宜在系統(tǒng)運(yùn)行太久之后分片驴党,因?yàn)樵谝粋€(gè)過(guò)載的系統(tǒng)上不停服進(jìn)行分片是非常困難的瘪撇。可以參考以下四點(diǎn)來(lái)決定何時(shí)分片:
????????????需要增加可用RAM
????????????增加可用磁盤空間
????????????減輕單臺(tái)服務(wù)器的負(fù)載
????????????處理單個(gè) mongod 無(wú)法承受的吞吐量
? ? ? ? MongoDB 集群包含三個(gè)組件:配置服務(wù)器港庄、mongos 服務(wù)器倔既、mongod 服務(wù)器。配置服務(wù)器相當(dāng)于集群的大腦鹏氧,保存著集群和分片的元數(shù)據(jù):集群中有哪些分片渤涌、分片的是哪些集合以及數(shù)據(jù)塊的分布等。mongos 需要從配置服務(wù)器獲取信息把还,因此配置服務(wù)器應(yīng)先于任何 mongos 進(jìn)程啟動(dòng)实蓬。配置服務(wù)器是獨(dú)立的 mongod 進(jìn)程茸俭,所以可以像啟動(dòng) mongod 一樣啟動(dòng)配置服務(wù)器,但在 MongoDB3.4 及以后的版本安皱,配置服務(wù)器必須部署為副本集的形式调鬓。
準(zhǔn)備環(huán)境
一:初始化宿主機(jī)系統(tǒng)
?1.安裝程序包
? ? ?yum -y install docker vim net-tools psmisc sysstat telnet wget lsof lrzsz
?????systemctl enable docker
?????setenforce 0
?????vim /etc/sysconfig/selinux ? ?修改Selinux為關(guān)閉狀態(tài)
?????vim /etc/security/limits.conf ? ?修改文件句柄數(shù)
?2.禁止內(nèi)存過(guò)度分配
echo 1 > /proc/sys/vm/overcommit_memory
vim /boot/grub2/grub.cfg
? ? numa=off
3.禁用zone_reclaim_mode
? ? cat /proc/sys/vm/zone_reclaim_mode
? ? ? ? 0
4.塊設(shè)備預(yù)讀大小
? ? blockdev --report
? ? blockdev --setra 16 /dev/sdb1
5.禁用大內(nèi)存頁(yè)面
? ? if test -f /sys/kernel/mm/transparent_hugepage/enabled; then
? ? echo never > /sys/kernel/mm/transparent_hugepage/enabled
? ? fi
? ? if test -f /sys/kernel/mm/transparent_hugepage/defrag; then
? ? echo never > /sys/kernel/mm/transparent_hugepage/defrag
? ? fi
6.修改文件描述符限制
? ? nofile 64000
? ? nproc? 64000
7.時(shí)鐘同步
? ? */2 * * * * ntpdate 1.sg.pool.ntp.org
8.禁用atime,默認(rèn)relatime
? ? ?vim /etc/fstab
? ? ?UUID=ef6ba050-6cdc-416a-9380-c14304d0d206 /? ? ? ? ? ? ? ? ? ? ? ?xfs? ? ?defaults,noatime? ? ? ? 0 0
? ? noatime,nodiratime?
9.創(chuàng)建所需目錄
mkdir -p /data/db/rs{1..3}
mkdir -p /data/db/conf{1..3}
mkdir -p /data/logs/rs{1..3}
chown -R mongo.mongo /data
二:構(gòu)建鏡像
1.Download Base Image centos7.3
?????docker pull docker.io/centos
2.start centos
?????docker run -d -it --name centos7 docker.io/centos /bin/bash
? ? ?docker run exec -it centos7? bash
? ? ?useradd? mongo
? ? ?usermod mongo -u 1021
? ? ?groupmod -g 1021 mongo
? ? ?mkdir -p /data/db
? ? ?mkdir -p /data/logs
? ? ?chown -R mongo.mongo /data
? ? ?ln -s? /usr/lib64/libsasl2.so.3 /usr/lib64/libsasl2.so.2
? ? ?ln -s /home/mongo/mongodb/bin/* /usr/bin/
?????su - mongo
?????mongo --hlep
? ? ?yum install -y crontabs
? ? ?su - root
? ? ?/usr/sbin/crond
3.docker commit centos 7 centos7
4.docker build -t mongod3.2.11 .
cat Dockerfile
####mongod####
FROM centos7
MAINTAINER Weiwendi
USER mongo
ENTRYPOINT ["/usr/bin/mongod"]
5.docker build -t mongos3.2.11 .?
cat Dockerfile
####mongos####
FROM centos7
MAINTAINER Weiwendi
USER mongo
ENTRYPOINT ["/usr/bin/mongos"]
分發(fā)配置文件
ConfigDB
-------------------------------------------------------------------
port? ? ? ? ? ? =? ?37019
pidfilepath? ? ?=? ?/data/mongodb/configdb/data/mongod.pid
fork? ? ? ? ? ? =? ?true
configsvr? ? ? ?=? ?true
dbpath? ? ? ? ? =? ?/data/mongodb/configdb/data
logpath? ? ? ? ?=? ?/data/mongodb/configdb/logs/mongod.log
logappend? ? ? ?=? ?true
logRotate? ? ? ?=? ?rename
journal? ? ? ? ?=? ?true
directoryperdb? =? ?true
nohttpinterface =? ?true
quiet? ? ? ? ? ?=? ?true
auth? ? ? ? ? ? =? ?true
keyFile? ? ? ? ?=? ?/data/mongodb/key/mongodb-keyfile
profile? ? ? ? ?=? ?1
slowms? ? ? ? ? =? ?2000
storageEngine? ?=? ?wiredTiger
wiredTigerDirectoryForIndexes = true
wiredTigerCacheSizeGB = 100
replSet? ? ? ? ?=? ?cfgdb
mongos
-------------------------------------------------------------------
port? ? ? ? ? ? =? ?47017
pidfilepath? ? ?=? ?/data/mongodb/mongos/data/mongos.pid
fork? ? ? ? ? ? =? ?true
configdb? ? ? ? =? ?cfgdb/192.168.17.128:37019,192.168.17.129:37019,192.168.17.131:37019
logpath? ? ? ? ?=? ?/data/mongodb/mongos/logs/mongos.log
logappend? ? ? ?=? ?true
logRotate? ? ? ?=? ?rename
quiet? ? ? ? ? ?=? ?true
keyFile? ? ? ? =? ?/data/mongodb/mongodb-keyfile
mongod
-----------------------------------------------------------------
port? ? ? ? ? ? =? ?27017
pidfilepath? ? ?=? ?/data/logs/mongod.pid
fork? ? ? ? ? ? =? ?true
dbpath? ? ? ? ? =? ?/data/db
logpath? ? ? ? ?=? ?/data/logs/rs1.log
logappend? ? ? ?=? ?true
logRotate? ? ? ?=? ?rename
journal? ? ? ? ?=? ?true
directoryperdb? =? ?true
nohttpinterface =? ?true
quiet? ? ? ? ? ?=? ?true
auth? ? ? ? ? ?=? ?true
keyFile? ? ? ? =? ?/data/mongodb/key/mongodb-keyfile
profile? ? ? ? ?=? ?1
slowms? ? ? ? ? =? ?2000
storageEngine? ?=? ?wiredTiger
wiredTigerDirectoryForIndexes = true
wiredTigerCollectionBlockCompressor = snappy
wiredTigerJournalCompressor = snappy
wiredTigerCacheSizeGB = 60
replSet? ? ? ?=? ?rs1
oplogSize? ? ?=? ?102400
在三臺(tái)主機(jī)上啟動(dòng)Docker容器
創(chuàng)建副本集
172.31.90.39? ?(副本集1)
docker run --name rs1_srv1 -p 21117:27017 --restart=always -v /data/db/rs1:/data/db -v /data/logs/rs1:/data/logs -v /data/conf/rs1:/data/conf -v /data/backup:/data/bak -d? registry.newborn-town.com:5000/wtmongodb3.2.11 -f /data/conf/mongodb.conf
docker run --name rs1_srv2 -p 21217:27017 --restart=always -v /data/db/rs2:/data/db -v /data/logs/rs2:/data/logs -v /data/conf/rs2:/data/conf -v /data/backup:/data/bak -d? registry.newborn-town.com:5000/wtmongodb3.2.11 -f /data/conf/mongodb.conf
docker run --name rs1_srv3 -p 21317:27017 --restart=always -v /data/db/rs3:/data/db -v /data/logs/rs3:/data/logs -v /data/conf/rs3:/data/conf -v /data/backup:/data/bak -d? registry.newborn-town.com:5000/wtmongodb3.2.11 -f /data/conf/mongodb.conf
172.31.90.64? (副本集2)
docker run --name rs2_srv1 -p 21117:27017 --restart=always -v /data/db/rs1:/data/db -v /data/logs/rs1:/data/logs -v /data/conf/rs1:/data/conf -v /data/backup:/data/bak -d? registry.newborn-town.com:5000/wtmongodb3.2.11 -f /data/conf/mongodb.conf
docker run --name rs2_srv2 -p 21217:27017 --restart=always -v /data/db/rs2:/data/db -v /data/logs/rs2:/data/logs -v /data/conf/rs2:/data/conf -v /data/backup:/data/bak -d? registry.newborn-town.com:5000/wtmongodb3.2.11 -f /data/conf/mongodb.conf
docker run --name rs2_srv3 -p 21317:27017 --restart=always -v /data/db/rs3:/data/db -v /data/logs/rs3:/data/logs -v /data/conf/rs3:/data/conf -v /data/backup:/data/bak -d? registry.newborn-town.com:5000/wtmongodb3.2.11 -f /data/conf/mongodb.conf
172.31.90.161? (副本集3)
docker run --name rs3_srv1 -p 21117:27017 --restart=always -v /data/db/rs1:/data/db -v /data/logs/rs1:/data/logs -v /data/conf/rs1:/data/conf -v /data/backup:/data/bak -d? registry.newborn-town.com:5000/wtmongodb3.2.11 -f /data/conf/mongodb.conf
docker run --name rs3_srv2 -p 21217:27017 --restart=always -v /data/db/rs2:/data/db -v /data/logs/rs2:/data/logs -v /data/conf/rs2:/data/conf -v /data/backup:/data/bak -d? registry.newborn-town.com:5000/wtmongodb3.2.11 -f /data/conf/mongodb.conf
docker run --name rs3_srv3 -p 21317:27017 --restart=always -v /data/db/rs3:/data/db -v /data/logs/rs3:/data/logs -v /data/conf/rs3:/data/conf -v /data/backup:/data/bak -d? registry.newborn-town.com:5000/wtmongodb3.2.11 -f /data/conf/mongodb.conf
配置服務(wù)器
172.31.90.39
? ? docker run --name cfg1 -p 37017:27017 --restart=always -v /data/db/conf1:/data/db -d registry.newborn-town.com:5000/mongod-3.2.10? --storageEngine wiredTiger --smallfiles --configsvr --dbpath /data/db --port 27017
172.31.90.64
? ? docker run --name cfg2 -p 37017:27017 --restart=always -v /data/db/conf2:/data/db -d registry.newborn-town.com:5000/mongod-3.2.10 --storageEngine wiredTiger --smallfiles --configsvr --dbpath /data/db --port 27017
172.31.90.161
? ? docker run --name cfg3 -p 37017:27017 --restart=always -v /data/db/conf3:/data/db -d registry.newborn-town.com:5000/mongod-3.2.10? --storageEngine wiredTiger --smallfiles --configsvr --dbpath /data/db --port 27017
mongos進(jìn)程
172.31.90.39
? ? docker run --name mongos1 -p 27017:27018 --restart=always -v /data/logs/rs1:/data/logs -d registry.newborn-town.com:5000/mongos-3.2.10? --logpath /data/logs/mongos.log --logappend --configdb 172.31.90.39:37017,172.31.90.64:37017,172.31.90.161:37017? --port 27018
172.31.90.64
? ? docker run --name mongos2 -p 27017:27018 --restart=always -v /data/logs/rs2:/data/logs -d registry.newborn-town.com:5000/mongos-3.2.10? --logpath /data/logs/mongos.log --logappend --configdb 172.31.90.39:37017,172.31.90.64:37017,172.31.90.161:37017? --port 27018
172.31.90.161
? ? docker run --name mongos3 -p 27017:27018 --restart=always -v /data/logs/rs3:/data/logs -d registry.newborn-town.com:5000/mongos-3.2.10? --logpath /data/logs/mongos.log --logappend --configdb 172.31.90.39:37017,172.31.90.64:37017,172.31.90.161:37017? --port 27018
以上啟動(dòng)Docker容器步驟练俐,可以通過(guò)docker compose來(lái)管理袖迎。
設(shè)置副本集(在mongodb上執(zhí)行)
172.31.90.39
mongo --port 21117
use admin
config_rs = {
? ?"_id":"rs1",
? ?"members": [
? ? ? ?{"_id":0,"host":"172.31.90.39:21117"},
? ? ? ?{"_id":1,"host":"172.31.90.64:21117"},
? ? ? ?{"_id":2,"host":"172.31.90.161:21117"}
? ?]
}
rs.initiate(config_rs)
172.31.90.64
mongo --port 21217
use admin
config_rs = {
? ?"_id":"rs2",
? ?"members": [
? ? ? ?{"_id":0,"host":"172.31.90.39:21217"},
? ? ? ?{"_id":1,"host":"172.31.90.64:21217"},
? ? ? ?{"_id":2,"host":"172.31.90.161:21217"}
? ?]
}
rs.initiate(config_rs)
172.31.90.161
mongo --port 21317
use admin
config_rs = {
? ?"_id":"rs3",
? ?"members": [
? ? ? ?{"_id":0,"host":"172.31.90.39:21317"},
? ? ? ?{"_id":1,"host":"172.31.90.64:21317"},
? ? ? ?{"_id":2,"host":"172.31.90.161:21317"}
? ?]
}
rs.initiate(config_rs)
設(shè)置分片(mongos上執(zhí)行)
use admin
sh.addShard("rs1/172.31.90.39:21117,172.31.90.64:21117,172.31.90.161:21117")
sh.addShard("rs2/172.31.90.39:21217,172.31.90.64:21217,172.31.90.161:21217")
sh.addShard("rs3/172.31.90.39:21317,172.31.90.64:21317,172.31.90.161:21317")
sh.enableSharding("kittylive")
use kittylive
db.user.createIndex({user_id:"hashed"})
db.bill.createIndex({bill_id:"hashed"})
db.giftRecord.createIndex({gift_id:"hashed"})
sh.shardCollection("kittylive.user",{"user_id":"hashed"})
sh.shardCollection("kittylive.bill",{"bill_id":"hashed"})
sh.shardCollection("kittylive.giftRecord",{"gift_id":"hashed"})
設(shè)置塊遷移窗口期
? ? ?use config
?????db.settings.update({ _id : "balancer" }, { $set : { activeWindow : { start : "22:00", stop : "02:00" } } }, true )
?????sh.getBalancerWindow()