使用 Docker 构建 MongoDB 分片及副本集

        负载均衡及高可用一直是我们线上服务架构所关注的重点,本文内容,将介绍如何在 Docker 环境下实现 MongoDB 的副本集及分片。

        在 MongoDB 中,副本集是一组实现了复制功能的服务器,其中一个是主服务器(Primary),用于处理客户端请求;其余为备份服务器(Secondary),用于保存主服务器的副本。如果主服务器出现故障,备份服务器将推举出其中一个成员为主服务器,继续响应请求。分片(Sharding)是将数据拆分并分散存放在不同机器上,这样不需要功能强大的大型计算机就可以存储更多的数据,处理更大的负载。MongoDB 的分片机制允许你创建一个包含许多台机器的集群,将数据子集分散在集群中,每个分片维护着一个数据集合的子集。与单机服务器和副本集相比,集群架构可以使应用程序具有更大的数据处理能力。

        副本集是让多台服务器都拥有同样的数据副本,每一台服务器都是其他服务器的镜像,而每一个分片都拥有和其他分片不同的数据子集。

        分片的目标之一是创建一个拥有5台、500台甚至更多机器的集群,整个集群对应用程序来说就像是一台单机服务器。为了对应用程序隐藏数据库架构的细节,在分片之前要先执行 mongos 进行一次路由过程。这个路由服务器维护着一个“内容列表”,指明了每个分片包含哪些数据内容。应用程序只需要连接到路由服务器,就可以像使用单机服务器一样进行正常的请求了。

        那么是不是在业务刚起步时就进行分片呢?不然。分片不止会增加部署的操作复杂度,还要求做出设计决策,而该决策以后很难再更改,所以不必太早分片,但也不宜在系统运行太久之后分片,因为在一个过载的系统上不停服进行分片是非常困难的。可以参考以下四点来决定何时分片:

            需要增加可用RAM

            增加可用磁盘空间

            减轻单台服务器的负载

            处理单个 mongod 无法承受的吞吐量

        MongoDB 集群包含三个组件:配置服务器、mongos 服务器、mongod 服务器。配置服务器相当于集群的大脑,保存着集群和分片的元数据:集群中有哪些分片、分片的是哪些集合以及数据块的分布等。mongos 需要从配置服务器获取信息,因此配置服务器应先于任何 mongos 进程启动。配置服务器是独立的 mongod 进程,所以可以像启动 mongod 一样启动配置服务器,但在 MongoDB3.4 及以后的版本,配置服务器必须部署为副本集的形式。

准备环境

一:初始化宿主机系统

 1.安装程序包

     yum -y install docker vim net-tools psmisc sysstat telnet wget lsof lrzsz

     systemctl enable docker

     setenforce 0

     vim /etc/sysconfig/selinux    修改Selinux为关闭状态

     vim /etc/security/limits.conf    修改文件句柄数

 2.禁止内存过度分配

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.块设备预读大小

    blockdev --report

    blockdev --setra 16 /dev/sdb1

5.禁用大内存页面

    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.时钟同步

    */2 * * * * ntpdate 1.sg.pool.ntp.org

8.禁用atime,默认relatime

     vim /etc/fstab

     UUID=ef6ba050-6cdc-416a-9380-c14304d0d206 /                       xfs     defaults,noatime        0 0

    noatime,nodiratime 

9.创建所需目录

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

二:构建镜像

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"]


分发配置文件

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


在三台主机上启动Docker容器

创建副本集

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

配置服务器

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进程

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

以上启动Docker容器步骤,可以通过docker compose来管理。

设置副本集(在mongodb上执行)

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)

设置分片(mongos上执行)

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"})

设置块迁移窗口期

     use config

     db.settings.update({ _id : "balancer" }, { $set : { activeWindow : { start : "22:00", stop : "02:00" } } }, true )

     sh.getBalancerWindow()

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容