一、软件介绍
1.1软件需求背景
高数据量和吞吐量的数据库应用会对单机的性能造成较大压力,大的查询量会将单机的CPU耗尽,大的数据量对单机的存储压力较大,最终会耗尽系统的内存而将压力转移到磁盘IO上。
为了解决这些问题,有两个基本的方法: 垂直扩展和水平扩展。
垂直扩展:增加更多的CPU和存储资源来扩展容量。
水平扩展:将数据集分布在多个服务器上。水平扩展即分片。
和MySQL分区方案相比,MongoDB的最大区别在于它几乎能自动完成所有事情,只要告诉MongoDB要分配数据,它就能自动维护数据在不同服务器之间的均衡。
1.2功能
MongoDB提供高性能的数据持久性。
对嵌入式数据模型的支持减少了数据库系统上的I / O活动。
索引支持更快的查询,并且可以包括来自嵌入式文档和数组的键
MongoDB支持丰富的查询语言,以支持读写操作(CRUD)
MongoDB的复制工具(称为副本集)提供: 自动故障转移 、数据冗余。
MongoDB提供水平可伸缩性作为其核心 功能的一部分:
分片在一组计算机集群分布数据。
从3.4开始,MongoDB支持基于shard键创建数据区域。在平衡群集中,MongoDB仅将区域覆盖的读写定向到区域内的那些分片。
MongoDB支持多个存储引擎:
WiredTiger存储引擎(包括对静态加密的支持 )
内存中存储引擎。
另外,MongoDB提供可插拔的存储引擎API,允许第三方为MongoDB开发存储引擎。
二、运行坏境
2.1软件坏境
测试环境使用docker启动,镜像为mongo:4.2.3
在rancher启动方式与docker启动大同小异,rancher需要使用宿主机的网络模式启动
数据目录为/data/db
端口设置为
mongos:27017
config:27000
shard01:27001
shard02:27002
shard03:27003
2.2支持的软件
Docker版本 18.9.8
2.3软件安装注意事项
注意容器所在的宿主机端口、数据目录是已经被占用。docker是否安装启动
三、安装过程
3.1安装前检查工作
A:软件产品检查:直接使用官方mongo:4.2.3 镜像
B:网络连通性检查:确认各主机之间通讯正常
3.2软件安装
第一步:集群端口及目录规划
172.20.101.157 mongos 27017 congfig 27000
172.20.101.160 mongos 27017 congfig 27000
172.20.101.164 mongos 27017 congfig 27000
172.20.101.165 shard01 27001 shard02 27002 shard03 27003
172.20.101.166 shard01 27001 shard02 27002 shard03 27003
172.20.101.167 shard01 27001 shard02 27002 shard03 27003
创建数据目录
172.20.101.157 mkdir -p /data/mongos/log /data/mongconf/log
172.20.101.160 mkdir -p /data/mongos/log /data/mongconf/log
172.20.101.164 mkdir -p /data/mongos/log /data/mongconf/log
172.20.101.165 mkdir -p /data/shard0{1..3}/log
172.20.101.166 mkdir -p /data/shard0{1..3}/log
172.20.101.167 mkdir -p /data/shard0{1..3}/log
第二步:部署shard节点并配置副本集
2.1、以下三个docker命令需要在172.20.101.165 172.20.101.166 172.20.101.167 三台主机上依次执行
docker run -d -p 27001:27001 --name="shard01" -v /data/shard01:/data/db -v /data/shard01/log:/data/db/log mongo:4.2.3 /usr/bin/mongod --shardsvr --replSet shard1 --port 27001 --bind_ip_all --dbpath /data/db --logpath /data/db/shard1.log --oplogSize 10 --wiredTigerCacheSizeGB 4
docker run -d -p 27002:27002 --name="shard02" -v /data/shard02:/data/db -v /data/shard02/log:/data/db/log mongo:4.2.3 /usr/bin/mongod --shardsvr --replSet shard2 --port 27002 --bind_ip_all --dbpath /data/db --logpath /data/db/shard2.log --oplogSize 10 --wiredTigerCacheSizeGB 4
docker run -d -p 27003:27003 --name="shard03" -v /data/shard03:/data/db -v /data/shard03/log:/data/db/log mongo:4.2.3 /usr/bin/mongod --shardsvr --replSet shard3 --port 27003 --bind_ip_all --dbpath /data/db --logpath /data/db/shard3.log --oplogSize 10 --wiredTigerCacheSizeGB 4
2.1、配置副本集
在shard01任意节点执行
use admin
config = {
_id : "shard1",
members : [
{_id : 0, host : "172.20.101.165:27001" },
{_id : 1, host : "172.20.101.166:27001" },
{_id : 2, host : "172.20.101.167:27001" , arbiterOnly: true}
]
}
rs.initiate(config);
在shard02任意节点执行
use admin
config = {
_id : "shard2",
members : [
{_id : 0, host : "172.20.101.165:27002" },
{_id : 1, host : "172.20.101.166:27002", arbiterOnly: true },
{_id : 2, host : "172.20.101.167:27002" }
]
}
rs.initiate(config);
在shard03任意节点执行
use admin
config = {
_id : "shard3",
members : [
{_id : 0, host : "172.20.101.167:27003" },
{_id : 1, host : "172.20.101.166:27003" },
{_id : 2, host : "172.20.101.165:27003" , arbiterOnly: true}
]
}
rs.initiate(config);
说明:
1、arbiterOnly: true 参数是将此节点设置为仲裁节点,仲裁节点不参与选举并且不会储存数据
2、如果选择使用仲裁节点,配置副本集是不能在指定的仲裁节点上进行配置,不然会报错
启动参数请参考: https://www.itsiv.com/2020/03/09/mongo配置文件详解/
第三步:部署config节点及副本集
3.1、在172.20.101.157 172.20.101.160 172.20.101.164 上分别执行以下docker命令
docker run -d -p 27000:27000 --name="mongoconfig" -v /data/mongconf:/data/db -v /data/mongconf/log:/data/db/log mongo:4.2.3 /usr/bin/mongod --configsvr --replSet myset --bind_ip_all --dbpath /data/db --port 27000 --logpath /data/db/log/config.log --wiredTigerCacheSizeGB 1
3.2、配置副本集
Use admin
config = {
_id : "myset",
members : [
{_id : 0, host : "172.20.101.157:27000" },
{_id : 1, host : "172.20.101.160:27000" },
{_id : 2, host : "172.20.101.164:27000" }
]
}
rs.initiate(config)
第四步:部署mongos
4.1、在172.20.101.157 172.20.101.160 172.20.101.164 上分别执行以下docker命令
docker run -d -p 27017:27017 --name="mongos" -v /data/mongos:/data/db mongo:4.2.3 mongos --configdb myset/172.20.101.157:27000,172.20.101.160:27000,172.20.101.164:27000 --port 27017 --bind_ip_all
4.2、启动分片
use admin
sh.addShard("shard1/172.20.101.165:27001,172.20.101.166:27001,172.20.101.167:27001")
sh.addShard("shard2/172.20.101.165:27002,172.20.101.166:27002,172.20.101.167:27002")
sh.addShard("shard3/172.20.101.165:27003,172.20.101.166:27003,172.20.101.167:27003")
#查看集群状态
sh.status()
第五步:mongodb分片测试
5.1、创建测试库
mongos> use test
switched to db test
5.2、指定test分片生效
mongos> sh.enableSharding("test")
{
"ok" : 1,
"operationTime" : Timestamp(1583738738, 4),
"$clusterTime" : {
"clusterTime" : Timestamp(1583738738, 4),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
mongos> sh.shardCollection("test.user",{name:"hashed"})
{
"collectionsharded" : "test.user",
"collectionUUID" : UUID("afbabe17-50ca-4797-8ea9-a15c60162a30"),
"ok" : 1,
"operationTime" : Timestamp(1583738752, 26),
"$clusterTime" : {
"clusterTime" : Timestamp(1583738752, 26),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
5.3、插入500条测试数据
mongos> for(i=1;i<=500;i++){db.user.insert({"id":i,"name":"jack"+i})}
WriteResult({ "nInserted" : 1 })
5.4、确认数据量
mongos> sh.status()
--- Sharding Status ---
sharding version: {
"_id" : 1,
"minCompatibleVersion" : 5,
"currentVersion" : 6,
"clusterId" : ObjectId("5e60cd2819c199fdcc0c402a")
}
...
databases:
test.user
shard key: { "name" : "hashed" }
unique: false
balancing: true
chunks:
shard1 2
shard2 1
shard3 1
...
}
shard1:PRIMARY> db.user.stats()
{
"ns" : "test.user",
"size" : 8601,
"count" : 166,
shard2:PRIMARY> db.user.stats()
{
"ns" : "test.user",
"size" : 8750,
"count" : 169,
"avgObjSize" : 51,
shard3:PRIMARY> db.user.stats()
{
"ns" : "test.user",
"size" : 8541,
"count" : 165,
"avgObjSize" : 51,
三个count加起来正好是我们插入的500条数据
5.5 删除shard02 查看数据是否完整
mongos> db.runCommand({"removeshard":"172.20.101.167:27002"})
{
"ok" : 0,
"errmsg" : "Shard 172.20.101.167:27002 not found",
"code" : 70,
"codeName" : "ShardNotFound",
"operationTime" : Timestamp(1583740841, 2),
"$clusterTime" : {
"clusterTime" : Timestamp(1583740841, 2),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
出现 “errmsg” : “Shard 172.20.101.167:27002 not found”, 表示删除成功
mongos> sh.status()
--- Sharding Status ---
….
test.user
shard key: { "name" : "hashed" }
unique: false
balancing: true
chunks:
shard1 3
shard3 3
….
shard1:PRIMARY> db.user.stats()
{
"ns" : "test.user",
"size" : 12901,
"count" : 249,
"avgObjSize" : 51,
shard3:PRIMARY> db.user.stats()
{
"ns" : "test.user",
"size" : 12991,
"count" : 251,
"avgObjSize" : 51,
与5.4相比chunks 已经迁移 shard1和shard2数据相加仍是500 ,数据没有丢失
第六步:mongodb复制集测试
6.1、利用前面插入的数据进行测试,查看复制集状态
shard3:PRIMARY> rs.status()
{
...
"members" : [
{
"_id" : 0,
"name" : "172.20.101.167:27003",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 337845,
...
},
{
"_id" : 1,
"name" : "172.20.101.166:27003",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
...
},
{
"_id" : 2,
"name" : "172.20.101.165:27003",
"health" : 1,
"state" : 7,
"stateStr" : "ARBITER",
...
}
],
"ok" : 1,
查看现在数据信息:
shard3:PRIMARY> use test
switched to db test
shard3:PRIMARY> db.user.stats()
{
"ns" : "test.user",
"size" : 12991,
"count" : 251,
"avgObjSize" : 51,
6.2、删除停止shard3的主节点
[root@cnvs-kubnode-101-166 ptmind]# docker stop shard03
Shard03
6.3、查看shard3的复制集信息
shard3:PRIMARY> rs.status()
{
"set" : "shard3",
},
"members" : [
{
"_id" : 0,
"name" : "172.20.101.167:27003",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
...
},
{
"_id" : 1,
"name" : "172.20.101.166:27003",
"health" : 0,
"state" : 8,
"stateStr" : "(not reachable/healthy)",
...
{
"_id" : 2,
"name" : "172.20.101.165:27003",
"health" : 1,
"state" : 7,
"stateStr" : "ARBITER",
…
}
shard3:PRIMARY> use test
switched to db test
shard3:PRIMARY> db.user.stats()
{
"ns" : "test.user",
"size" : 12991,
"count" : 251,
"avgObjSize" : 51,
数据跟5.5的数一致,没有丢失
6.4插入mongdb数据,查看shard3是否插入成功
往test里面在插入500条数据
mongos> use test
插入数据
for(i=1;i<=500;i++){db.user.insert({"id":i,"name":"jak"+i})}
shard3:PRIMARY> db.user.stats()
{
"ns" : "test.user",
"size" : 24933,
"count" : 491,
说明副本集节点宕机后,对写入的数据无影响。
第七步:测试config故障
7.1、停止config主节点
[root@cnvs-kubnode-101-160 ~]# docker stop mongoconfig
Mongoconfig
7.2、测试数据写入是否正常
mongos> use test
switched to db test
mongos> for(i=1;i<=500;i++){db.user.insert({"id":i,"name":"rk"+i})}
WriteResult({ "nInserted" : 1 })
数据写入成功
7.3、在停止一个config节点,并测试数据写入是否正常
[root@cnvskubm-101-157 ~]# docker stop mongoconfig
测试写入数据
mongos> use test
switched to db test
mongos> for(i=1;i<=50;i++){db.user.insert({"id":i,"name":"rok"+i})}
WriteResult({ "nInserted" : 1 })
数据写入正常