mongo部署分片服务器

在内网环境下, 部署了一组mongo分片服务器, 最终将各种脚本优化为一个python程序
项目github地址deploy-mongo

分片服务器组件信息

  • configsvr replset 1主2从
  • shardsvr replset 3组, 每一组都是1主2从
  • mongos 3个

环境如下

  • linux server 1: 192.168.0.100
  • linux server 2: 192.168.0.101
  • mongo version: 4.4
  • python 3.10

准备工作
安装python库 paramiko
pip install paramiko

初始化ssh client

1
2
3
ssh = paramiko.SSHClient()
policy = paramiko.AutoAddPolicy()
ssh.set_missing_host_key_policy(policy)

#####部分核心接口说明

远程执行shell命令接口

1
2
3
4
5
6
7
8
9
10
11
def exec_command(hostname, port, username, password, cmd):
print(hostname, cmd)
ssh.connect(
hostname = hostname,
port = port,
username = username,
password = password,
)
stdin, stdout, stderr = ssh.exec_command(cmd)
print(stdout.read().decode())
print(stderr.read().decode())

启动configsvr

1
2
3
4
5
6
7
8
def start_configsvr(hostname, sshport, username, password, index, mongoport):
dbpath = "%s-configsvr-%d" % (project, index)
replSet = "%s-configsvr" % (project)
logpath = "%s-configsvr-%d.log" % (project, index)
checkdir = "cd %s && mkdir -p %s " % (root, dbpath)
cmd = "%s && mongod --configsvr --replSet %s --bind_ip 0.0.0.0 --port %d --dbpath %s --logpath %s --fork" % \
(checkdir, replSet, mongoport, dbpath, logpath)
exec_command(hostname, sshport, username, password, cmd)

初始化configsvr

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def init_configsvr(addrs):
conf = {
"_id" : "%s-configsvr" % (project),
"configsvr" : True,
"members" : [],
}
index = 0
for addr in addrs:
conf["members"].append({"_id" : index, "host" : addr})
index = index + 1
s = json.dumps(conf).replace("\"", "'")
addr = addrs[0]
host, port = addr.split(':')
server = servers[host]
assert(server)
cmd = "cd %s && mongo --port %s --eval \"rs.initiate(%s)\"" % (root, port, s)
exec_command(host, server["port"], server["user"], server["password"], cmd)

启动shardsvr

1
2
3
4
5
6
7
8
def start_shardsvr(hostname, sshport, username, password, group, index, mongoport):
dbpath = "%s-shardsvr-%d-rs-%d" % (project, group, index)
replSet = "%s-shardsvr-%d" % (project, group)
logpath = "%s-shardsvr-%d-rs-%d.log" % (project, group, index)
checkdir = "cd %s && mkdir -p %s " % (root, dbpath)
cmd = "%s && mongod --shardsvr --replSet %s --bind_ip 0.0.0.0 --port %d --dbpath %s --logpath %s --fork" % \
(checkdir, replSet, mongoport, dbpath, logpath)
exec_command(hostname, sshport, username, password, cmd)

初始化shardsvr

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def init_shardsvr(addrs, group):
conf = {
"_id" : "%s-shardsvr-%d" % (project, group),
"members" : [],
}
index = 0
for addr in addrs:
conf["members"].append({"_id" : index, "host" : addr})
index = index + 1
s = json.dumps(conf).replace("\"", "'")
addr = addrs[0]
host, port = addr.split(':')
server = servers[host]
assert(server)
cmd = "cd %s && mongo --port %s --eval \"rs.initiate(%s)\"" % (root, port, s)
exec_command(host, server["port"], server["user"], server["password"], cmd)

启动mongos

1
2
3
4
5
6
7
def start_mongos(hostname, sshport, username, password, index, mongoport, configsvrs):
replSet = "%s-configsvr" % (project)
logpath = "%s-mongos-%d.log" % (project, index)
cddir = "cd %s" % (root)
cmd = "%s && mongos --configdb %s/%s --logpath .%s --logappend --verbose --fork --port %d" % \
(cddir, replSet, ",".join(configsvrs), logpath, mongoport)
exec_command(hostname, sshport, username, password, cmd)

初始化mongos

1
2
3
4
5
6
7
8
9
10
11
def init_mongos(addrs, shardsvrs):
group = 1
for addr in addrs:
host, port = addr.split(':')
replSet = "%s-shardsvr-%d" % (project, group)
array = shardsvrs[group - 1]
cmd = "cd %s && mongo --port %s --eval \"sh.addShard('%s/%s')\"" % (root, port, replSet, ",".join(array))
server = servers[host]
assert(server)
exec_command(host, server["port"], server["user"], server["password"], cmd)
group = group + 1

部署完毕后开始测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 连接到mongo
mongo --port mongos-port --host mongos-host

# 支持分片
sh.enableSharding(dbname)

# 加入分片
sh.shardCollection("testrs.datas", {shard_key: 1})

# 刷新路由
db.adminCommand("flushRouterConfig")

# 支持平衡
sh.enableBalancing("testrs.datas")

# 开启平衡
sh.startBalancer()

# 修改块大小为1M, 方便后续测试
use config
db.settings.save( { _id:"chunksize", value: 1})

# 插入数据测试
use testrs
for (var i = 10000; i < 20000; i++) {
db.datas.insertOne({shard_key : Math.random().toString(36).substring(2, 15), value : "qwertyuiopasdfghjklzxcvbnm", id : i})
}

# 查看数据分布
db.datas.getShardDistribution()

部署mongo分片服务器本身并不复杂, 一定要注意顺序:
启动configsvr –> 初始化configsvr –> 启动全部shardsvr –> 初始化每一组shardsvr分片 –> 启动mongos –> 初始化mongos