前期准备
我的三台服务器分别为: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
创建文件目录,三台服务器目录相同
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、重启各个实例