mirror of
https://github.com/tiennm99/zfoo.git
synced 2026-05-19 23:26:50 +00:00
427 lines
13 KiB
Markdown
427 lines
13 KiB
Markdown
# 一、分片的搭建
|
||
|
||
## 1.MongoDB环境准备
|
||
|
||
- config服务器三台,虚拟机的静态ip分别设置为
|
||
|
||
```
|
||
192.168.1.40 mongodb-config0
|
||
192.168.1.41 mongodb-config1
|
||
192.168.1.42 mongodb-config2
|
||
```
|
||
|
||
- route服务器三台,虚拟机的静态ip分别设置为
|
||
|
||
```
|
||
192.168.1.45 mongodb-route0
|
||
192.168.1.46 mongodb-route1
|
||
192.168.1.47 mongodb-route2
|
||
```
|
||
|
||
- shard服务器三台,虚拟机的静态ip分别设置为
|
||
|
||
```
|
||
192.168.1.50 mongodb-shard0
|
||
192.168.1.51 mongodb-shard1
|
||
192.168.1.52 mongodb-shard2
|
||
```
|
||
|
||
- shard副本集服务器三台,虚拟机的静态ip分别设置为
|
||
|
||
```
|
||
192.168.1.55 mongodb-shard3-replica0
|
||
192.168.1.56 mongodb-shard3-replica1
|
||
192.168.1.57 mongodb-shard3-replica2
|
||
```
|
||
|
||
- 设置好ip后还需要把ip与主机名对应起来
|
||
|
||
```
|
||
hostname # 查看主机名使用命令
|
||
|
||
vim /etc/sysconfig/network,修改主机名,在最后一行加上HOSTNAME=mongodb-config0,其它的服务器同理
|
||
|
||
vim /etc/hosts,修改为我们设置的主机名,不同的主机对应不同的mongodb
|
||
127.0.0.1 localhost mongodb-config0 localhost4 localhost4.localdomain4
|
||
::1 localhost mongodb-config0 localhost6 localhost6.localdomain6
|
||
|
||
192.168.1.30 mongodb0
|
||
192.168.1.31 mongodb1
|
||
192.168.1.32 mongodb2
|
||
|
||
192.168.1.40 mongodb-config0
|
||
192.168.1.41 mongodb-config1
|
||
192.168.1.42 mongodb-config2
|
||
|
||
192.168.1.45 mongodb-route0
|
||
192.168.1.46 mongodb-route1
|
||
192.168.1.47 mongodb-route2
|
||
|
||
192.168.1.50 mongodb-shard0
|
||
192.168.1.51 mongodb-shard1
|
||
192.168.1.52 mongodb-shard2
|
||
192.168.1.55 mongodb-shard3-replica0
|
||
192.168.1.56 mongodb-shard3-replica1
|
||
192.168.1.57 mongodb-shard3-replica2
|
||
```
|
||
|
||
- 重启服务器后生效,使用hostname命令验证主机名,使用ping命令验证三个虚拟机之间相互可以使用主机名ping通。
|
||
- 开启防火墙端口。
|
||
|
||
## 2.config服务器
|
||
|
||
- mongodb-config0,mongodb-config1,mongodb-config2使用命令
|
||
|
||
```
|
||
mkdir -p /data/mongodb/db # 存放数据的目录
|
||
mkdir -p /data/mongodb/logs # 存放日记的目录
|
||
mkdir -p /data/mongodb/key # 存放密钥的目录
|
||
```
|
||
|
||
- vim /usr/local/mongodb/mongodb.config,修改配置文件如下
|
||
|
||
```
|
||
dbpath=/data/mongodb/db
|
||
|
||
logpath=/data/mongodb/logs/mongodb.log
|
||
logappend=true
|
||
|
||
port=22400
|
||
fork=true
|
||
|
||
configsvr=true
|
||
replSet=mongodbConfigSet
|
||
|
||
#keyFile默认会开启auth=true
|
||
#auth=true
|
||
#keyFile=/data/mongodb/key/myKey.txt
|
||
|
||
#生产环境需要设置ip:bind_ip=127.0.0.1,本机ip
|
||
bind_ip=0.0.0.0
|
||
```
|
||
|
||
- 创建副本集
|
||
|
||
```
|
||
mongo --port 22400 # 进入mongodb0
|
||
config = {_id: "mongodbConfigSet", members: [
|
||
{_id: 0, host:"mongodb-config0:22400"},
|
||
{_id: 1, host:"mongodb-config1:22400"},
|
||
{_id: 2, host:"mongodb-config2:22400"}
|
||
]}
|
||
rs.initiate(config) # 初始化副本集
|
||
```
|
||
|
||
- 观察副本集
|
||
|
||
```
|
||
rs.conf() # 副本集配置
|
||
rs.status() # 副本集状态
|
||
```
|
||
|
||
## 3.route路由服务器
|
||
|
||
- mongodb-route0,mongodb-route1,mongodb-route2使用命令
|
||
|
||
```
|
||
mkdir -p /data/mongodb/db # 存放数据的目录
|
||
mkdir -p /data/mongodb/logs # 存放日记的目录
|
||
mkdir -p /data/mongodb/key # 存放密钥的目录
|
||
```
|
||
|
||
- vim /usr/local/mongodb/mongodb.config,修改配置文件如下
|
||
|
||
```
|
||
logpath=/data/mongodb/logs/mongodb.log
|
||
logappend=true
|
||
|
||
port=22400
|
||
fork=true
|
||
|
||
#必须是1个或则3
|
||
configdb=mongodbConfigSet/mongodb-config0:22400,mongodb-config1:22400,mongodb-config2:22400
|
||
|
||
#keyFile默认会开启auth=true
|
||
#keyFile=/data/mongodb/key/myKey.txt
|
||
|
||
#生产环境需要设置ip:bind_ip=127.0.0.1,本机ip
|
||
bind_ip=0.0.0.0
|
||
```
|
||
|
||
- vim /usr/lib/systemd/system/mongodb.service,修改启动脚本
|
||
|
||
```bash
|
||
[Unit]
|
||
#服务描述
|
||
Description=High-performance, schema-free document-oriented database
|
||
#指定了在systemd在执行完那些target之后再启动该服务
|
||
After=network.target
|
||
|
||
[Service]
|
||
#定义Service的运行类型,一般是forking(后台运行)
|
||
Type=forking
|
||
|
||
ExecStart=/usr/local/mongodb/bin/mongos --config /usr/local/mongodb/mongodb.config
|
||
ExecReload=
|
||
ExecStop=/usr/bin/pkill mongos
|
||
|
||
[Install]
|
||
#多用户
|
||
WantedBy=multi-user.target
|
||
```
|
||
|
||
- systemctl daemon-reload,重新加载服务
|
||
- systemctl restart mongodb
|
||
|
||
## 4.shard分片服务器
|
||
|
||
- mongodb-shard0,mongodb-shard1,mongodb-shard2使用命令
|
||
|
||
```
|
||
mkdir -p /data/mongodb/db # 存放数据的目录
|
||
mkdir -p /data/mongodb/logs # 存放日记的目录
|
||
mkdir -p /data/mongodb/key # 存放密钥的目录
|
||
```
|
||
|
||
- vim /usr/local/mongodb/mongodb.config,修改配置文件如下
|
||
|
||
```
|
||
dbpath=/data/mongodb/db
|
||
|
||
logpath=/data/mongodb/logs/mongodb.log
|
||
logappend=true
|
||
|
||
port=22400
|
||
fork=true
|
||
|
||
shardsvr=true
|
||
|
||
#keyFile默认会开启auth=true
|
||
#auth=true
|
||
#keyFile=/data/mongodb/key/myKey.txt
|
||
|
||
#生产环境需要设置ip:bind_ip=127.0.0.1,本机ip
|
||
bind_ip=0.0.0.0
|
||
```
|
||
|
||
- systemctl restart mongodb
|
||
|
||
## 5.配置sharding
|
||
|
||
- mongo客户端进入mongos服务所在的端口,在其中一台机子中进入mongos
|
||
|
||
```
|
||
mongo --port 22400
|
||
use admin # 需要先切换到admin数据库,才能进行分片的添加
|
||
sh.addShard("mongodb-shard0:22400")
|
||
sh.addShard("mongodb-shard1:22400")
|
||
sh.addShard("mongodb-shard2:22400")
|
||
|
||
# 单节点分片的缺点是如果其中一个分片挂了,会导致整个分片集群不可用,所以建议每个分片都使用副本集
|
||
sh.addShard("mongodbShard3Set/mongodb-shard3-replica0:22400,mongodb-shard3-replica1:22400,mongodb-shard3-replica2:22400")
|
||
```
|
||
|
||
## 6.使用分片数据库和使用分片集合
|
||
|
||
- 在任节点中进入mongos
|
||
|
||
```
|
||
mongo --port 22400 # 切换到admin数据库
|
||
use admin
|
||
sh.enableSharding("test")
|
||
|
||
sh.shardCollection("test.student", { _id: "hashed" }) # 把test数据库student集合的_id字段设置为哈希片键
|
||
sh.shardCollection("test.student", { _id:1 }) # 把test数据库student集合的_id字段设置为区间片键
|
||
```
|
||
|
||
- 标签片键
|
||
|
||
```
|
||
标签片键比较特别,通过对分片节点打标签,再将片键按范围对应到这些标签上,对应片键范围的集合中的数据就会落在这个分片节点上。
|
||
首先需要对分片打标签,对分片打标签需要知道分片的_id,在mongos中使用命令查看:
|
||
sh.status()
|
||
|
||
|
||
这里分片_id分别为: shard0000, shard0001, shard0002,则对分片打标签命令如下:
|
||
sh.addShardTag("shard0000", "tag1")
|
||
sh.addShardTag("shard0001", "tag2")
|
||
sh.addShardTag("shard0002", "tag3")
|
||
|
||
|
||
然后student的学号字段code设置标签片键范围。
|
||
这样设置后学号code为1到600的会存储在分片shard0001或者shard0002中,学号为601到5000的会存储在分片shard0000中。
|
||
sh.addTagRange("test.student", { _id: 0 }, { _id: 1000 }, "tag1")
|
||
sh.addTagRange("test.student", { _id: 1001 }, { _id: 9000 }, "tag2")
|
||
sh.addTagRange("test.student", { _id: 9001 }, { _id: 10000 }, "tag3")
|
||
|
||
查看标签的分片,在mongos中使用命令
|
||
use config
|
||
db.shards.find()
|
||
|
||
查看标签的片键值范围,使用命令
|
||
use config
|
||
db.tags.find()
|
||
|
||
|
||
移除某个分片的标签使用命令
|
||
sh.removeShardTag("shard0000", "tag1")
|
||
sh.removeShardTag("shard0001", "tag2")
|
||
sh.removeShardTag("shard0002", "tag3")
|
||
|
||
```
|
||
|
||
## 7.分片数据测试
|
||
|
||
- 集合测试
|
||
|
||
```
|
||
mongo --port 22400
|
||
use test
|
||
for(var i=0; i<10000; i++) db.student.insert({ _id:i, name:"jaysunxiao", addr:"myAddress", country:"myCountry" })
|
||
执行可能需要一段会时间,我们直接在工具中查看config集合中的chunks元数据信息,就可以看到随着数据的写入分了多少片,以及片键的最小到最大的范围。
|
||
|
||
3个shard服务器里可以看到都有了mytest数据库以及student集合。
|
||
```
|
||
|
||
## 8.分片的管理
|
||
|
||
- 移除Shard Server,回收数据,分片被删除之后,数据被移到其他分片中,不会丢失
|
||
|
||
```
|
||
use admin
|
||
# 如果是区间片键,已经指定了区间了,数据迁移会失败,会导致分片一直draining,因为找不到区间分片的节点
|
||
db.runCommand( { removeShard: "shard0002" } )
|
||
# 检查迁移的状态,再次在 admin 数据库运行 removeShard 命令,因为数据多的话要一处的节点需要很长时间迁移数据
|
||
db.runCommand( { removeShard: "shard0002" } )
|
||
|
||
db.runCommand({"moveprimary": "test", "to": "shard0000"}) # 要是原来分片是一个主分片,则需要执行movePrimary
|
||
```
|
||
|
||
## 9.均衡器
|
||
|
||
- 均衡器:均衡器负责数据迁移,周期性的检查分片是否存在不均衡。 config.locks集合里的state表示均衡器是否找正在运行,0表示非活动状态,2表示正在均衡。
|
||
均衡迁移数据的过程会增加系统的负载:目标分片必须查询源分片的所有文档,将文档插入目标分片中,再清除源分片的数据。 可以关闭均衡器(不建议):关闭会导致各分片数据分布不均衡,磁盘空间得不到有效的利用。
|
||
|
||
```
|
||
sh.setBalancerState(false) #关闭自动均衡器,手动均衡
|
||
sh.setBalancerState(true)
|
||
|
||
use config
|
||
db.settings.find() #查看均衡器状态
|
||
|
||
# 移动块的时候必须关闭均衡器,否则可能导致死循环
|
||
use admin
|
||
sh.moveChunk("db.collection",{块地址},"新片名称") #手动均衡
|
||
sh.moveChunk("test.student",{"_id": "test.student-_id_6148914691236517204"},"shard0000")
|
||
use config
|
||
db.chunks.find().pretty()
|
||
```
|
||
|
||
## 10.认证分配
|
||
|
||
- 首先创建账号(Root角色),其中route(mongos)不需要创建账号,需要两种权限
|
||
|
||
```
|
||
userAdminAnyDatabase # 管理员权限,用来管理其它的账号
|
||
clusterAdmin # 分片管理员权限
|
||
```
|
||
|
||
- 再生成一个KeyFile文件
|
||
- config,shard节点修改配置,vim /usr/local/mongodb/mongodb.config
|
||
|
||
```
|
||
#keyFile默认会开启auth=true
|
||
auth=true
|
||
keyFile=/data/mongodb/key/myKey.txt
|
||
```
|
||
|
||
- route节点修改配置,vim /usr/local/mongodb/mongodb.config
|
||
|
||
```
|
||
#因为mongos本来就是从config里加载数据的,所以只需要添加keyfile文件即可
|
||
keyFile=/data/mongodb/key/myKey.txt
|
||
```
|
||
|
||
- 重新启动各个节点
|
||
|
||
```
|
||
systemctl restart mongodb
|
||
```
|
||
|
||
## 11.分片备份、还原
|
||
|
||
- 先停止平衡器的工作,并检查没有chunk move动作,保证dump的时候没有进行数据迁移。
|
||
|
||
```
|
||
sh.stopBalancer()
|
||
```
|
||
|
||
- 锁定数据库,保证数据没有写入:在各个分片上和配置服务器上执行。
|
||
|
||
```
|
||
db.fsyncLock()
|
||
```
|
||
|
||
- 执行备份操作mongodump,备份各个分片服务器和配置服务器。
|
||
|
||
- 解锁数据库,备份完成之后在分片和配置服务器上解锁数据库,允许修改。
|
||
|
||
```
|
||
db.fsyncUnlock()
|
||
```
|
||
|
||
- 备份还原mongorestore各个分片和配置服务器
|
||
- 重启各个实例
|
||
|
||
# 二、原理解析
|
||
|
||
## 1.分片实现了数据的分布式存储,负载均衡,这些都是海量数据的云存储平台不可或缺的功能
|
||
|
||
- 配置服务器
|
||
|
||
```
|
||
是一个独立的mongod进程,保存集群和分片的元数据,即各分片包含了哪些数据的信息。
|
||
最先开始建立,启用日志功能。像启动普通的mongod一样启动配置服务器,指定configsvr选项。
|
||
不需要太多的空间和资源,配置服务器的1KB空间相当于真实数据的200MB。保存的只是数据的分布表。
|
||
当服务不可用,则变成只读,无法分块、迁移数据。
|
||
```
|
||
|
||
- 路由服务器
|
||
|
||
```
|
||
即mongos,起到一个路由的功能,供程序连接。
|
||
本身不保存数据,在启动时从配置服务器加载集群信息,开启mongos进程需要知道配置服务器的地址,指定configdb选项。
|
||
```
|
||
|
||
- 分片服务器
|
||
|
||
```
|
||
是一个独立普通的mongod进程,保存数据信息。可以是一个副本集也可以是单独的一台服务器。
|
||
```
|
||
|
||
## 2.mongodb什么时候开始分片?
|
||
|
||
MongoDB的分片是基于范围的,也就是说任何一个文档一定位于指定片键的某个范围。一旦片键选择好后,chunks就会按照片键来将一部分documents从逻辑上组合在一起。
|
||
由于chunks的大小默认的阈值是64 MB或100000个文档,一旦达到这个阈值就会根据片键分片。
|
||
片键一般是是索引,如果没有指定索引,则用集合默认的_id索引作为片键。
|
||
|
||
## 3.分片适用的场景
|
||
|
||
1,机器的磁盘不够用了。使用分片解决磁盘空间的问题。 2,单个mongod已经不能满足写数据的性能要求。通过分片让写压力分散到各个分片上面,使用分片服务器自身的资源。
|
||
3,想把大量数据放到内存里提高性能。和上面一样,通过分片使用分片服务器自身的资源。
|
||
|
||
## 4.集群dump备份恢复策略,对集群的备份就可以转化为对各复制集的备份:
|
||
|
||
1. 禁用平衡器,命令:sh.stopBalancer();因为分片集群上会有一个balancer进程在后台维护各个片上数据块数量的均衡,如果不禁用平衡器可能会导致备份数据的重复或缺失
|
||
2. 停止毎个片(副本集)上的某个secondary节点,利用此节点进行备份;停止其中某个配置服务器(所有配置服务器的数据一样),保证备份时配务器上元数据不会改变,备份可以当作一单节点的实例
|
||
3. 重启所有停掉的复制集成员,它们会自动从primary节点上的oplog同步数据,最终数据会达到一致性
|
||
4. 重启分片集群的平衡器。通过mongo连接到mongos上,执行命令如下。use config;sh.startBalancer()
|
||
|
||
## 5.集群恢复流程
|
||
|
||
1. 停止集群上的所有mongod实例和mongos实例。
|
||
2. 利用上面备份的dump文件,依次恢复片中的每个副本集
|
||
3. 恢复配置服务器。
|
||
4. 重启所有mongod实例与mongos实例。
|
||
5. 通过mongo连接上mongos,执行以下命令确保集群是可操作的:db.printShardingStatus()
|