前期准备

我的三台服务器分别为:10.10.105.198、10.10.105.199、10.10.105.200

10.10.105.198

10.10.105.199

10.10.105.200

mongos

mongos

mongos

config server

config server

config server

shard server1 主节点

shard server1 副节点

shard server1 仲裁

shard server2 仲裁

shard server2 主节点

shard server2 副节点

shard server3 副节点

shard server3 仲裁

shard server3 主节点

端口分配:

服务

端口

说明

mongos

20000

路由服务器

config

21000

配置服务器

shard1

27001

分片服务器1

shard2

27002

分片服务器2

shard3

27003

分片服务器3

下载mongodb,可自行到官网下载,我下载的是4.0版本的。官网地址:https://www.mongodb.com/download-center/community

 

mongodb集群配置权重_mongodb

创建文件目录,三台服务器目录相同

mkdir -p /usr/local/mongodb/conf #配置文件目录
mkdir -p /usr/local/mongodb/mongos/log #路由服务日志目录
mkdir -p /usr/local/mongodb/config/data #配置服务数据文件目录
mkdir -p /usr/local/mongodb/config/log #配置服务日志目录
mkdir -p /usr/local/mongodb/shard1/data #分片服务器数据文件目录
mkdir -p /usr/local/mongodb/shard1/log #分片服务器日志目录
mkdir -p /usr/local/mongodb/shard2/data
mkdir -p /usr/local/mongodb/shard2/log
mkdir -p /usr/local/mongodb/shard3/data
mkdir -p /usr/local/mongodb/shard3/log

配置环境变量

vi /etc/profile
# MongoDB 环境变量内容
export PATH=/usr/local/mongodb/bin:$PATH

使立即生效

source /etc/profile

搭建配置服务器

mongodb3.4以后要求配置服务器也需要创建副本集,不然集群搭建不成功。三台服务器配置相同。可使用scp命令将相同的文件直接拷贝到其它服务器目录。

scp /usr/local/mongodb/conf/shard1.conf root@10.10.105.199:/usr/local/mongodb/conf/

我是一台服务器的配置全配好后把整个mongodb目录拷贝到其它服务器。

添加配置文件

vi /usr/local/mongodb/conf/config.conf

配置文件内容

pidfilepath = /usr/local/mongodb/config/log/configsrv.pid
dbpath = /usr/local/mongodb/config/data
logpath = /usr/local/mongodb/config/log/congigsrv.log
logappend = true
bind_ip = 0.0.0.0
port = 21000
fork = true
#declare this is a config db of a cluster
configsvr = true
#副本集名称
replSet = configs
#设置最大连接数
maxConns = 20000

启动三台服务器的config server

mongod -f /usr/local/mongodb/conf/config.conf

初始化配置副本集

使用任意一台服务器,连接 MongoDB

mongo --port 21000

设置config 变量

config = {
    _id : "configs",
    members : [
    {_id : 0, host : "10.10.105.198:21000" },
    {_id : 1, host : "10.10.105.199:21000" },
    {_id : 2, host : "10.10.105.200:21000" }
    ]
}

初始化副本集

rs.initiate(config)

查询状态

rs.status()

搭建分片副本集

三台服务器配置一样,这里以shard1为例。shard2和shard3的配置与shard1相似,只是文件目录路径、端口号、副本集名称不同。

配置文件

vi /usr/local/mongodb/conf/shard1.conf

 配置文件内容

pidfilepath = /usr/local/mongodb/shard1/log/shard1.pid
dbpath = /usr/local/mongodb/shard1/data
logpath = /usr/local/mongodb/shard1/log/shard1.log
logappend = true
bind_ip = 0.0.0.0
port = 27001
fork = true
#副本集名称
replSet = shard1
#declare this is a shard db of a cluster;
shardsvr = true
#设置最大连接数
maxConns = 20000

启动三台服务器的shard1服务

mongod -f /usr/local/mongodb/conf/shard1.conf

初始化副本集

登陆任意一台服务器,连接 MongoDB

mongo --port 27001

使用admin数据库

use admin

定义副本集配置

config = {
    _id : "shard1",
     members : [
         {_id : 0, host : "10.10.105.198:27001" },
         {_id : 1, host : "10.10.105.199:27001" },
         {_id : 2, host : "10.10.105.200:27001" , arbiterOnly: true }
     ]
 }

初始化副本集配置

rs.initiate(config)

注:“arbiterOnly:true”是定义哪台服务器为仲裁者的参数,注意不能将你当前做配置的机器设为仲裁者,否则会报错。比如你想设置200这台机器为仲裁者,那么你只能在198或者199这台机器上去做初始化副本集配置。

配置路由服务器mongos

配置文件

vi /usr/local/mongodb/conf/mongos.conf

文件内容:

pidfilepath = /usr/local/mongodb/mongos/log/mongos.pid
logpath = /usr/local/mongodb/mongos/log/mongos.log
logappend = true
bind_ip = 0.0.0.0
port = 20000
fork = true
#监听的配置服务器,只能有1个或者3个 configs为配置服务器的副本集名字
configdb = configs/10.10.105.198:21000,10.10.105.199:21000,10.10.105.200:21000
#设置最大连接数
maxConns = 20000

启动mongos服务

注意要先启动配置服务器和分片服务器,最后启动路由服务器,三台服务器都启动

mongos -f /usr/local/mongodb/conf/mongos.conf

串联路由服务器

目前搭建了mongodb配置服务器、路由服务器,各个分片服务器,不过应用程序连接到mongos路由服务器并不能使用分片机制,还需要在程序里设置分片配置,让分片生效。

登陆任意一台mongos

mongo --port 20000

使用admin数据库

use admin

串联路由服务器与分配副本集

sh.addShard("shard1/10.10.105.198:27001,10.10.105.199:27001,10.10.105.。200:27001")
sh.addShard("shard2/10.10.105.198:27002,10.10.105.199:27002,10.10.105.。200:27002")
sh.addShard("shard3/10.10.105.198:27003,10.10.105.199:27003,10.10.105.。200:27003")

查看集群状态

sh.status()

响应内容如下

mongos> sh.status()
--- Sharding Status --- 
  sharding version: {
        "_id" : 1,
        "minCompatibleVersion" : 5,
        "currentVersion" : 6,
        "clusterId" : ObjectId("5dc921c1d179af58212256ed")
  }
  shards:
        {  "_id" : "shard1",  "host" : "shard1/10.10.105.199:27001,10.10.105.200:27001",  "state" : 1 }
        {  "_id" : "shard2",  "host" : "shard2/10.10.105.198:27002,10.10.105.199:27002",  "state" : 1 }
        {  "_id" : "shard3",  "host" : "shard3/10.10.105.198:27003,10.10.105.200:27003",  "state" : 1 }
  active mongoses:
        "4.0.13" : 3
  autosplit:
        Currently enabled: yes
  balancer:
        Currently enabled:  yes
        Currently running:  no
        Failed balancer rounds in last 5 attempts:  0
        Migration Results for the last 24 hours: 
                No recent migrations
  databases:
        {  "_id" : "config",  "primary" : "config",  "partitioned" : true }

启用集合分片生效

登陆任意一台mongos

mongo --port 20000

使用admin数据库

use admin

指定数据库分片生效

sh.enableSharding("yourdb")

指定数据库里需要分片的集合和片键

sh.shardCollection("yourdb.table1",{"id":hashed}) # id字段是片键。片键的选择:利于分块、分散写请求、查询数据。

分片方式可以是“1”或者“hashed"。设置为"1",mongodb会根据你的分片键的值去进行分片,设置为"hashed",mongodb会根据分片键的值的hash值进行分片。

这里我设置yourdb的table1表分片,根据id自动分片到shard1,shard2,shard3分片服务器。

测试分片配置结果

连接任意一台mongos路由服务器

mongo --port 20000

切换到你的数据库

use yourdb;

插入测试数据

for(i=1;i<=100000;i++){db.table1.insert({"id":i,"name":"the green arrow"})}; #循环插入10万条数据

查看分片情况

mongos> db.table1.stats();
{
    "sharded": true,
    "capped": false,
    "ns": "testdb.table1",
    "count": 100000,
    "size": 5200000,
    "storageSize": 1519616,
    "totalIndexSize": 3530752,
    "indexSizes": {
        "_id_": 892928,
        "id_hashed": 2637824
    },
    "avgObjSize": 52,
    "nindexes": 2,
    "nchunks": 6,
    "shards": {
        "shard1": {
            "ns": "testdb.table1",
            "size": 1755260,
            "count": 33755,
            "avgObjSize": 52,
            "storageSize": 532480,
            "capped": false,
            "wiredTiger": {
            ...
            }
        },
        "shard2": {
            "ns": "testdb.table1",
            "size": 1723436,
            "count": 33143,
            "avgObjSize": 52,
            "storageSize": 479232,
            "capped": false,
            "wiredTiger": {
            ...
            }
        },
        "shard3": {
            "ns": "testdb.table1",
            "size": 1721304,
            "count": 33102,
            "avgObjSize": 52,
            "storageSize": 507904,
            "capped": false,
            "wiredTiger": {
            ...
            }
        }
    },
    "ok": 1,
    "$clusterTime": {
        "clusterTime": Timestamp(1517488062, 350),
        "signature": {
            "hash": BinData(0, "AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId": NumberLong(0)
        }
    },
    "operationTime": Timestamp(1517488062, 350)
}
mongos> sh.status()
--- Sharding Status --- 
  sharding version: {
      "_id" : 1,
      "minCompatibleVersion" : 5,
      "currentVersion" : 6,
      "clusterId" : ObjectId("5a73053f896ba937d7beb807")
  }
  shards:
        {  "_id" : "shard1",  "host" : "shard1/10.10.105.199:27001,10.10.105.200:27001",  "state" : 1 }
        {  "_id" : "shard2",  "host" : "shard2/10.10.105.198:27002,10.10.105.199:27002",  "state" : 1 }
        {  "_id" : "shard3",  "host" : "shard3/10.10.105.198:27003,10.10.105.200:27003",  "state" : 1 }
  active mongoses:
        "3.6.2" : 3
  autosplit:
        Currently enabled: yes
  balancer:
        Currently enabled:  yes
        Currently running:  no
        Failed balancer rounds in last 5 attempts:  0
        Migration Results for the last 24 hours: 
                2 : Success
  databases:
        {  "_id" : "config",  "primary" : "config",  "partitioned" : true }
                config.system.sessions
                        shard key: { "_id" : 1 }
                        unique: false
                        balancing: true
                        chunks:
                                shard1    1
                        { "_id" : { "$minKey" : 1 } } -->> { "_id" : { "$maxKey" : 1 } } on : shard1 Timestamp(1, 0) 
        {  "_id" : "testdb",  "primary" : "shard1",  "partitioned" : true }
                testdb.table1
                        shard key: { "id" : "hashed" }
                        unique: false
                        balancing: true
                        chunks:
                                shard1    2
                                shard2    2
                                shard3    2
                        { "id" : { "$minKey" : 1 } } -->> { "id" : NumberLong("-6148914691236517204") } on : shard1 Timestamp(3, 2) 
                        { "id" : NumberLong("-6148914691236517204") } -->> { "id" : NumberLong("-3074457345618258602") } on : shard1 Timestamp(3, 3) 
                        { "id" : NumberLong("-3074457345618258602") } -->> { "id" : NumberLong(0) } on : shard2 Timestamp(3, 4) 
                        { "id" : NumberLong(0) } -->> { "id" : NumberLong("3074457345618258602") } on : shard2 Timestamp(3, 5) 
                        { "id" : NumberLong("3074457345618258602") } -->> { "id" : NumberLong("6148914691236517204") } on : shard3 Timestamp(3, 6) 
                        { "id" : NumberLong("6148914691236517204") } -->> { "id" : { "$maxKey" : 1 } } on : shard3 Timestamp(3, 7)

至此,mongodb分片副本集集群就搭建好了。

追加分片

如果以后还要再添加分片,可以做好分片配置和启动分片服务后,使用如下方法添加分片配置到路由:

sh.addShard("10.10.105.198:27004,10.10.105.199:27004,10.10.105.200:27004")

权限认证配置

创建账户

做完以上配置,目前访问mongodb是不需要密码验证的。接下来我们为mongodb设置访问权限。

进入主配置服务器的mongo命令行

mongo --port 21000

1、创建root账户,方便后面操作。root账户相当于超级管理员。

use admin
db.createUser({user:'root',pwd:'root.123',roles:[{role:'root',db:'admin'}]})

2、创建管理员账号

db.createUser({user:'admin', pwd:'admin.123', roles:[{role: 'userAdminAnyDatabase', db:'admin' }]})

3、创建集群管理员账号

db.createUser({user:'clusteradmin', pwd:'cluster.123', roles:[{role: 'clusterAdmin', db:'admin' }]})

4、创建自定义数据库操作账号

use yourdb
db.createUser({user:'test', pwd:'test.123', roles:[{role: 'readWrite', db:'yourdb' }]})

角色说明

数据库用户角色

read:允许用户读取指定的数据库
readWrite:允许用户读写指定数据库

数据库管理角色

dbAdmin:允许用户在指定数据库执行管理函数,创建索引,删除索引,查看统计.
userAdmin:允许用户向system.users集合写入,可以在指定数据库创建删除管理账号
dbOwner:指定数据库最大的权限,是readWrite+dbAdmin+userAdmin的和。

群集管理角色(只在admin数据库可用)

clusterAdmin:用户所有分片和复制集相关函数的管理权限
clusterManager:管理和监控群集。
clusterMonitor:只能访问监控工具。
hostManager:监视和管理。

备份和还原角色

所有角色(只在admin数据库可用)
readAnyDatabase:赋予用户所有数据库的读权限
readWriteAnyDatabase:赋予用户所有数据库的读写权限
userAdminAnyDatabase:赋予所有数据库的useradmin权限
dbAdminAnyDatabase:赋予所有数据库的dbadmin权限。
超级角色(只在admin可用)
root:超级账号,超级权限

用户创建完成后,接下来创建集群认证文件keyfile。ctrl+c退出mongo命令,回到当前目录,输入以下命令

openssl rand -base64 756 > mongo_keyfile
chmod 400 mongo_keyfile

在当前目录会生成一个名为“mongo_keyfile”的文件,将此文件拷贝至其它服务器中:

scp mongo_keyfile root@10.10.105.200:/usr/local/mongodb/

其它服务器操作相同。

认证配置

三台服务器都要修改,可以改好一台服务器后直接将conf文件夹拷贝到其它服务器对应目录。当前在mongodb目录下

1、修改config.conf文件

vi conf/config.conf
# 新增以下内容行
auth = true
keyFile = /usr/local/mongodb/mongo_keyfile

2、修改分片配置文件shard1.conf、shard2.conf、shard3.conf

vi conf/shard1.conf
# 新增以下内容行
auth = true
keyFile = /usr/local/mongodb/mongo_keyfile

另外两个相同的操作。

3、修改mongos.conf文件

vi conf/mongos.conf
# 新增以下内容行
keyFile = /usr/local/mongodb/mongo_keyfile

保存后,重启所有服务。以后数据库的操作均需要先使用db.auth()登陆认证。

注意:在停止服务时要先停止mongos服务,再停止shard和config的服务。

mongodb服务的启动与终止请查看

其它设置

以下内容参考的别人的博客的,未经测试,仅做记录,以备不时之需。

关闭自动均衡器(不建议)

mongos> sh.setBalancerState(false)

为均衡器设置均衡时间

mongos> db.settings.update({"_id":"balancer"},{"$set":{"activeWindow":{"start":"01:00","stop":"06:00"}}},true) #在凌晨1点到6点进行分片均衡操作

设置分片的块大小

默认块大小为64M

mongos> use yourdb
mongos> db.settings.find() #查看块大小
{ "_id" : "chunksize", "value" : 64 }
mongos> db.settings.save({"_id":"chunksize","value":32}) #设置块大小为32M

也可以在config配置文件中设置

手动迁移数据

sh.moveChunk("db.collection",{块地址},"新分片名称")

例如

mongos> db.chunks.find({"_id" : "abc.account-name_\"wPeFnJEvendSTbH\""}).pretty() #先到config.chunks上任意找一个块
{
    "_id" : "abc.account-name_\"wPeFnJEvendSTbH\"",
    "lastmod" : Timestamp(3, 1),
    "lastmodEpoch" : ObjectId("55a52ff1fdd9a605a0371327"),
    "ns" : "abc.account",
    "min" : {
        "name" : "wPeFnJEvendSTbH"              #被移动的块
    },
    "max" : {
        "name" : { "$maxKey" : 1 }
    },
    "shard" : "shard0000"                       #原先所在的分片
}
mongos> sh.moveChunk("abc.account",{"name" : "wPeFnJEvendSTbH"},"mablevi")  #把abc.account集合中包含name(片键)为""的快迁移到mablevi分片中
{ "millis" : 6800, "ok" : 1 }
mongos> db.chunks.find({"_id" : "abc.account-name_\"wPeFnJEvendSTbH\""}).pretty()  
{
    "_id" : "abc.account-name_\"wPeFnJEvendSTbH\"",
    "lastmod" : Timestamp(5, 0),
    "lastmodEpoch" : ObjectId("55a52ff1fdd9a605a0371327"),
    "ns" : "abc.account",
    "min" : {
        "name" : "wPeFnJEvendSTbH"
    },
    "max" : {
        "name" : { "$maxKey" : 1 }
    },
    "shard" : "mablevi"                        #已被迁移到新片
}

删除分片

mongos> use admin   #需要到admin下面删除
switched to db admin
mongos> db.runCommand({"removeshard":"shard1"})
{
    "msg" : "draining started successfully",
    "state" : "started",   #开始删除,数据正在转移
    "shard" : "shard1",
    "ok" : 1
}

如果分片数据较大,命令会执行一段时间,期间可以多次使用此命令查看是否删除完成。

mongos> db.runCommand({"removeshard":"shard1"})
{
    "msg" : "removeshard completed successfully",
    "state" : "completed",  #完成删除
    "shard" : "shard1",
    "ok" : 1
}

分片被删除之后,数据被移到其他分片中,不会丢失。要是想让主分片进行转移则可做如下操作

mongos> db.adminCommand({"movePrimary":"dbname","to":"shard2"}) #把dbname的主分片从shard1迁移到shard2

刷新下配置服务器:

db.adminCommand({"flushRouterConfig":1})

最后来查看下分片成员:

db.runCommand({ listshards : 1 })

分片备份、还原

因为分片机制会有均衡器来进行数据迁移,分片里的数据很可能会移动,所以在备份分片时需要先停止均衡器

备份数据库

1、停止均衡器的工作,并检查没有chunk move动作,保证dump的时候没有进行数据迁移。

mongo --port 20000
use admin
db.auth('admin':'admin.123') #如果需要认证
mongos> sh.stopBalancer()

2、锁定数据库,保证数据没有写入。在各个分片上和配置服务器上执行

mongos> use yourdb
mongos> db.fsyncLock()
{
    "info" : "now locked against writes, use db.fsyncUnlock() to unlock",
    "seeAlso" : "http://dochub.mongodb.org/core/fsynccommand",
    "ok" : 1
}

3、执行备份操作,备份各个分片服务器和配置服务器。

mongodump -utest -ptest.123 -d yourdb --authenticationDatabase admin -o backup/

4、解锁数据库,备份完成之后在分片和配置服务器上解锁数据库,允许修改。

> db.fsyncUnlock()
{ "ok" : 1, "info" : "unlock completed" }

当数据库出现问题,需要还原的时候,需要还原各个分片和配置服务器,并且重启MongoDB实例。

还原数据库

1、还原各个分片和配置服务器。

mongorestore --host=10.10.105.198 --port=21000 -utest -test.123 -d yourdb --authenticationDatabase admin --drop backup/yourdb

2、重启各个实例