docker-compose创建mongodb分片集群
向大佬们学习: 分布式NoSQL数据库MongoDB初体验-v5.0.5 - itxiaoshen - 博客园 (cnblogs.com) MongoDB–副本集 MongoDB 数据库高级进阶 - 集群和安全
1、mongodb基础
1.1 mongodb特点?
- 面向文档,具有动态ddl能力,更为灵活;
- 完全的分布式、高可用、高性能,基于内存的数据查询;
- 容易扩展,基于分片可以进行海量数据存储,实现自动分片和水平扩展;
- API丰富,支持索引、管道聚合、地理空间数据、事务、join等;
- 支持多种语言;
1.2 bson和json区别?
bson是一种二进制形式的存储格式,采用了相似于C 语言结构体的名称、对表示方法,支持内嵌的文档对象和数组对象,具备轻量性、可遍历性、高效性的特色,能够有效描述非结构化数据和结构化数据,有点相似于Google的Protocol Buffer。
- 更快的遍历速度:对json格式来讲,太大的json结构会导致数据遍历变慢;在json中要跳过一个文档进行数据读取,须要对此文档进行扫描匹配比如括号的匹配,而bson将每个元素的长度存在元素的头部,这样就可快速读到指定位置。
- 操做更简易:对json来讲数据存储是无类型的,比如你要修改值9为10这样就从一个字符变成了两个字符,也即是后面的内容都要后移一位因此增加开销。而使用bson可以指定这个列为数字类型,那么数字从9改为10甚至是10000,这样都只是在存储数字上修改,不会致使数据总长度变化。当时在MongoDB中若是数字从整形增大到长整型那仍是会致使数据总长度变大的。
- 增加额外的数据类型:json是一个很方便的数据交换格式,可是其类型比较有限;bson在其基础上增长了“byte array”数据类型,这使得二进制的存储再也不需要先base64转换后再存成json,大大减小了计算开销和数据大小。下图为bson支持数据类型
1.3 和关系型数据库区别?
- database-数据库,与关系型数据库(database)概念相同,一个数据库包含多个集合(表)。
- collection-集合,相当于关系型数据库中的表(table),一个集合可以存放多个文档(行)。不同之处就在于集合的结构(schema)是动态的,不需要预先声明一个严格的表结构。更重要的是默认情况下MongoDB 并不会对写入的数据做任何schema的校验。
- document-文档,相当于关系型数据库中的行(row),一个文档由多个字段(列)组成,并采用bson(json)格式表示。
- field-字段,相当于关系型数据库中的列(column),相比普通column的差别在于field的类型可以更加灵活比如支持嵌套的文档、数组,区分大小写。
- 其他说明
- id-主键,MongoDB 默认生成id 字段来保证文档的唯一性。
- reference-引用,勉强可以对应于外键(foreign key) 的概念,但reference 并没有实现任何外键约束,只是由客户端(driver)自动进行关联查询、转换的一个特殊类型。
- view-视图,MongoDB 3.4 开始支持视图,这个和关系型数据库的视图没有什么差异,视图是基于集合之上进行动态查询的一层对象,可以是虚拟的,也可以是物理的(物化视图)。
- index-索引,与关系型数据库的索引相同。
- $lookup-聚合操作符,可以用于实现类似关系型数据库-join连接的功能。
- transaction-事务,从 MongoDB 4.0 版本开始,提供了对于事务的支持。
- aggregation-聚合,MongoDB 提供了强大的聚合计算框架,group by是其中的一类聚合操作。
1.4 什么是复制集?
复制集是一组拥有相同数据的mongodb节点,由两台及以上的mongodb实例组成的集群,包括primary主节点(读写能力)、secondary从节点(读能力)、投票节点3种角色。 复制集提供了数据冗余、备份能力,提高了数据的可用性,保证了数据的安全性。
1.5 复制集原理?
MongoDB副本集同步原理
primary主节点记录所有操作到oplog中,该文件存储在local数据库中。 全量同步:第一次加入或者secondary落后的数据超过了oplog的大小 复制:拉取和重放oplog采用不同线程完成
1.6 什么是分片?
将大量数据,对于mongodb来说就是大数据量的collection按照一定规则切分后存放到不同服务器上,通过更多的服务器提升对数据的处理能力。
1.7 为什么要分片?
- 单机磁盘容量有限,无法存放更多数据;
- 单机处理能力有限,无法有效处理更多请求;
- 单机内存有限,导致较多请求从磁盘查询数据、效率低下;
- 副本集具有数量限制
1.8 分片原理?
分片集群由3部分组成:
- config server:配置服务器,存储所有的数据库元数据(分片、路由)信息;可以配置副本;
- shard server:分片服务器,由一个或多个mongod进程组成,存储数据;可以配置副本;
- router server:路由服务器,分片集群的入口,所有的请求都由router(mongos)路由到指定的shard服务器上;可以配置副本;
分片键(shard key):
- 为了在多个shard server中分片,使用分片键进行分割数据,分片键必须是每个记录都包含的字段、且是建立了索引的单个或者多个字段。
- 一旦集合设置了分片键,那么插入数据后,分片键和分片键的值都是不可改变的。如若修改,必须先删除文档,然后重新设置分片键,再插入数据。
- 分片键不支持地理空间索引、全文索引、数组索引。
分片算法:
-
基于范围:
-
定义:基于范围的分片键是根据分片键值把数据分成一个个邻接的范围,如果没有指定特定的分片类型,则基于范围的分片键是默认的分片类型。 -
特点:基于范围的分片键对于范围类型的查询比较高效,给定一个片键的范围,分发路由可以很简单地确定哪个数据块存储了请求需要的数据,并将请求转发到相应的分片中。 -
使用场景:建议在分片键基数较大,频率较低,并且分片键值不是单调变化的情况下使用基于范围的分片键。 -
操作:
sh.enableSharding(database)
sh.shardCollection(namespace, key)
-
基于hash:
-
定义:基于哈希的分片键是指MongoDB数据库计算一个字段的哈希值,并用这个哈希值来创建数据块。 -
特点:保证了集群中数据的均衡。哈希值的随机性使数据随机分布在每个数据块中,因此也随机分布在不同分片中。 -
使用场景:如果分片键值的基数较大,拥有大量不一样的值,或者分片键值是单调变化的,则建议使用基于哈希的分片键。 -
操作: 然后再使用如下命令创建基于哈希的分片键
sh.enableSharding(database)
sh.shardCollection("<database>.<collection>", { <shard key> : "hashed" }* , false, {numInitialChunks: 预置的chunk个数})
db.collection.createIndex()
sh.shardCollection()
1.9 限制
- mongodb的bson数据嵌套不超过100层;
- 32位系统只能寻址4GB内存,意味着数据集包含元数据和存储达到4GB,Mongodb就无法存储额外的数据了
- 由于数据库名称在MongoDB中不区分大小写,因此数据库名称不能仅因字符的大小写而不同。
- 命名
- 数据库 名称也不能包含空字符。数据库名称不能为空,并且必须少于64个字符。
- 集合 名称应以下划线或字母字符开头,并且不能包含$、不能包含空字符串、不能以system.前缀开头。集合名称空间的最大长度为120个字节,其中包括数据库名称,点(.)分隔符和集合名称(即.)
- 字段 名称不能包含null字符,顶级字段名称不能以美元符号($)字符开头。
- 在Mongodb3.0中 副本集 成员最最多支持50个,也就是说副本集做大支持50个节点,副本集每个节点数据支持32T,副本集每个实例建议数据不要超过4T,数据量大备份恢复时间会很长。
- 我们通常 分片 会使用默认的chunk大小为64M,如果我们的分片key (片键)values值是512字节,分片节点支持最大32768个也就是最大支持数据量为32768TB。一个片键大小不能超过512字节。
- 从MongoDB 3.6开始,服务器允许存储包含点(即.)和美元符号(即$)的字段名称
2、使用docker编排文件创建mongodb分片集群
集群结构:
文件夹结构:
docker-compose.yaml mongo |-- config |-- |-- config0 |-- |-- |-- data |-- |-- |-- log |-- |-- config1 |-- |-- |-- data |-- |-- |-- log |-- |-- config2 |-- |-- |-- data |-- |-- |-- log |-- |-- conf |-- |-- |-- mongod.conf |-- shard |-- |-- conf0 |-- |-- |-- mongod.conf |-- |-- conf1 |-- |-- |-- mongod.conf |-- |-- shard00 |-- |-- |-- data |-- |-- |-- log |-- |-- shard01 |-- |-- |-- data |-- |-- |-- log |-- |-- shard02 |-- |-- |-- data |-- |-- |-- log |-- |-- shard10 |-- |-- |-- data |-- |-- |-- log |-- |-- shard11 |-- |-- |-- data |-- |-- |-- log |-- |-- shard12 |-- |-- |-- data |-- |-- |-- log |-- mongos |-- |-- conf |-- |-- |-- mongod.conf |-- |-- |-- data |-- |-- |-- log
2.1 生成keyFile
- MongoDB使用keyfile认证,副本集中的每个mongod实例使用keyfile内容作为认证其他成员的共享密码。mongod实例只有拥有正确的keyfile才可以加入副本集。
- keyFile的内容必须是6到1024个字符的长度,且副本集所有成员的keyFile内容必须相同。
- 有一点要注意是的:在UNIX系统中,keyFile必须没有组权限或完全权限(也就是权限要设置成X00的形式)。Windows系统中,keyFile权限没有被检查。
- 可以使用任意方法生成keyFile。例如,如下操作使用openssl生成复杂的随机的1024个字符串。然后使用chmod修改文件权限,只给文件拥有者提供读权限。
openssl rand -base64 756 > mongodb.key
chmod 400 mongodb.key
2.2 mongodb配置文件
config/conf/mongod.conf
storage:
dbPath: /data/db
journal:
enabled: true
directoryPerDB: true
engine: wiredTiger
wiredTiger:
engineConfig:
cacheSizeGB: 0.25
directoryForIndexes: true
systemLog:
destination: file
logAppend: true
path: /var/log/mongodb/mongod.log
security:
keyFile: /etc/key.key
clusterAuthMode: "keyFile"
authorization: enabled
net:
port: 27019
bindIp: 0.0.0.0
processManagement:
timeZoneInfo: /usr/share/zoneinfo
replication:
oplogSizeMB: 256
replSetName: cfg
sharding:
clusterRole: configsvr
shard/conf0/mongod.conf
storage:
dbPath: /data/db
journal:
enabled: true
directoryPerDB: true
engine: wiredTiger
wiredTiger:
engineConfig:
cacheSizeGB: 0.25
directoryForIndexes: true
systemLog:
destination: file
logAppend: true
path: /var/log/mongodb/mongod.log
security:
keyFile: /etc/key.key
clusterAuthMode: "keyFile"
authorization: enabled
net:
port: 27018
bindIp: 0.0.0.0
processManagement:
timeZoneInfo: /usr/share/zoneinfo
replication:
oplogSizeMB: 256
replSetName: rs0
sharding:
clusterRole: shardsvr
shard/conf1/mongod.conf
storage:
dbPath: /data/db
journal:
enabled: true
directoryPerDB: true
engine: wiredTiger
wiredTiger:
engineConfig:
cacheSizeGB: 0.25
directoryForIndexes: true
systemLog:
destination: file
logAppend: true
path: /var/log/mongodb/mongod.log
security:
keyFile: /etc/key.key
clusterAuthMode: "keyFile"
authorization: enabled
net:
port: 27018
bindIp: 0.0.0.0
processManagement:
timeZoneInfo: /usr/share/zoneinfo
replication:
oplogSizeMB: 256
replSetName: rs1
sharding:
clusterRole: shardsvr
mongs/conf/mongod.conf
systemLog:
destination: file
logAppend: true
path: /var/log/mongodb/mongod.log
security:
keyFile: /etc/key.key
clusterAuthMode: "keyFile"
net:
port: 27017
bindIp: 0.0.0.0
processManagement:
timeZoneInfo: /usr/share/zoneinfo
sharding:
configDB: cfg/mongo-config0:27019,mongo-config1:27019,mongo-config1:27019
2.3 docker编排文件
docker-compose.yaml
执行 docker-compose -f docker-compose.yaml up -d
version: "3.9"
services:
# docker-compose部署单机版本分片mongo https://cloud.tencent.com/developer/article/1717360
# docker部暑mongodb_4.4.8 sharding集群(arm64和amd64),mongodb_consistent_backup备份与恢复 https://blog.csdn.net/u010533742/article/details/119754119
# 分布式NoSQL数据库MongoDB初体验-v5.0.5 https://www.cnblogs.com/itxiaoshen/p/15728782.html
# https://docs.mongodb.com/manual/
mongo-config0:
image: mongo:latest
privileged: true
hostname: mongo-config0
container_name: mongo-config0
volumes:
- /etc/timezone:/etc/timezone:ro
- ./mongo/config/config0/data:/data/db
- ./mongo/config/config0/log:/var/log/mongodb
- ./mongo/key.key:/etc/key.key
- ./mongo/config/conf:/etc/mongod
command: -f /etc/mongod/mongod.conf
networks:
basenetwork:
ipv4_address: 172.18.0.30
mongo-config1:
image: mongo:latest
privileged: true
hostname: mongo-config1
container_name: mongo-config1
volumes:
- /etc/timezone:/etc/timezone:ro
- ./mongo/config/config1/data:/data/db
- ./mongo/config/config1/log:/var/log/mongodb
- ./mongo/key.key:/etc/key.key
- ./mongo/config/conf:/etc/mongod
command: -f /etc/mongod/mongod.conf
networks:
basenetwork:
ipv4_address: 172.18.0.31
mongo-config2:
image: mongo:latest
privileged: true
hostname: mongo-config2
container_name: mongo-config2
volumes:
- /etc/timezone:/etc/timezone:ro
- ./mongo/config/config2/data:/data/db
- ./mongo/config/config2/log:/var/log/mongodb
- ./mongo/key.key:/etc/key.key
- ./mongo/config/conf:/etc/mongod
command: -f /etc/mongod/mongod.conf
networks:
basenetwork:
ipv4_address: 172.18.0.32
mongo-shard0-0:
image: mongo:latest
privileged: true
hostname: mongo-shard0-0
container_name: mongo-shard0-0
volumes:
- /etc/timezone:/etc/timezone:ro
- ./mongo/shard/shard00/data:/data/db
- ./mongo/shard/shard00/log:/var/log/mongodb
- ./mongo/key.key:/etc/key.key
- ./mongo/shard/conf0:/etc/mongod
command: -f /etc/mongod/mongod.conf
networks:
basenetwork:
ipv4_address: 172.18.0.33
mongo-shard0-1:
image: mongo:latest
privileged: true
hostname: mongo-shard0-1
container_name: mongo-shard0-1
volumes:
- /etc/timezone:/etc/timezone:ro
- ./mongo/shard/shard01/data:/data/db
- ./mongo/shard/shard01/log:/var/log/mongodb
- ./mongo/key.key:/etc/key.key
- ./mongo/shard/conf0:/etc/mongod
command: -f /etc/mongod/mongod.conf
networks:
basenetwork:
ipv4_address: 172.18.0.34
mongo-shard0-2:
image: mongo:latest
privileged: true
hostname: mongo-shard0-2
container_name: mongo-shard0-2
volumes:
- /etc/timezone:/etc/timezone:ro
- ./mongo/shard/shard02/data:/data/db
- ./mongo/shard/shard02/log:/var/log/mongodb
- ./mongo/key.key:/etc/key.key
- ./mongo/shard/conf0:/etc/mongod
command: -f /etc/mongod/mongod.conf
networks:
basenetwork:
ipv4_address: 172.18.0.35
mongo-shard1-0:
image: mongo:latest
privileged: true
hostname: mongo-shard1-0
container_name: mongo-shard1-0
volumes:
- /etc/timezone:/etc/timezone:ro
- ./mongo/shard/shard10/data:/data/db
- ./mongo/shard/shard10/log:/var/log/mongodb
- ./mongo/key.key:/etc/key.key
- ./mongo/shard/conf1:/etc/mongod
command: -f /etc/mongod/mongod.conf
networks:
basenetwork:
ipv4_address: 172.18.0.36
mongo-shard1-1:
image: mongo:latest
privileged: true
hostname: mongo-shard1-1
container_name: mongo-shard1-1
volumes:
- /etc/timezone:/etc/timezone:ro
- ./mongo/shard/shard11/data:/data/db
- ./mongo/shard/shard11/log:/var/log/mongodb
- ./mongo/key.key:/etc/key.key
- ./mongo/shard/conf1:/etc/mongod
command: -f /etc/mongod/mongod.conf
networks:
basenetwork:
ipv4_address: 172.18.0.37
mongo-shard1-2:
image: mongo:latest
privileged: true
hostname: mongo-shard1-2
container_name: mongo-shard1-2
volumes:
- /etc/timezone:/etc/timezone:ro
- ./mongo/shard/shard12/data:/data/db
- ./mongo/shard/shard12/log:/var/log/mongodb
- ./mongo/key.key:/etc/key.key
- ./mongo/shard/conf1:/etc/mongod
command: -f /etc/mongod/mongod.conf
networks:
basenetwork:
ipv4_address: 172.18.0.38
mongos:
image: mongo:latest
privileged: true
hostname: mongos
container_name: mongos
volumes:
- /etc/timezone:/etc/timezone:ro
- ./mongo/mongos/log:/var/log/mongodb
- ./mongo/key.key:/etc/key.key
- ./mongo/mongos/conf:/etc/mongod
command: mongos -f /etc/mongod/mongod.conf
ports:
- "27017:27017"
networks:
basenetwork:
ipv4_address: 172.18.0.39
networks:
basenetwork:
external: true
2.3 添加用户、分片等操作
docker exec -i mongos mongo --port 27017
use admin
db.createUser(
{
user: "root",
pwd: "123456",
roles: [ { role: "userAdminAnyDatabase", db: "admin" }, "readWriteAnyDatabase" , {role: 'root', db: 'admin'}]
}
);
db.auth('root','123456')
sh.addShard("rs0/mongo-shard0-0:27018,mongo-shard0-1:27018,mongo-shard0-2:27018");
sh.addShard("rs1/mongo-shard1-0:27018,mongo-shard1-1:27018,mongo-shard1-2:27018");
sh.status();
use admin
db.auth('root','123456')
use springboot
db.createUser(
{
user: "admin",
pwd: "123456",
roles: [ { role: "dbOwner", db: "springboot" } ]
}
);
sh.enableSharding("springboot")
sh.shardCollection("springboot.user", { _id : "hashed" } )
sh.status()
use springboot
for(var i=1;i<=1000;i++){
db.user.insert({
name:i,
age:Math.round(Math.random() * 100),
score1:Math.round(Math.random() * 100),
score2:Math.round(Math.random() * 100),
score3:Math.round(Math.random() * 100),
score4:Math.round(Math.random() * 100),
score5:Math.round(Math.random() * 100)
});
}
db.user.stats()
db.serverStatus().connections; //连接数查看
show collections //查看表信息
db.test_shard.find().count() //查看table1数据长度
db.test_shard.remove({}) //删除数据表
db.stats() //查看所有的分片服务器状态
db.adminCommand( { listShards: 1 } ) //分片列表
db.test_shard.find({ age: 36 }).explain() //精确查询
db.test_shard.find({ age: { $gte : 36 ,$lt : 73 } }).explain() //范围查询
sh.enableSharding('testdb') //开启数据库testdb分片
sh.shardCollection('testdb.users',{uid:1}) //按testdb.users的uid字段分片
sh.shardCollection("testdb.test_shard",{"age": 1}) //按ranged分片
sh.shardCollection("testdb.test_shard2",{"age": "hashed"}) //按hash分片
sh.status() //查看分片节点
sh.addShard() //向集群中添加一个 shard
sh.getBalancerState() //查看平衡器
sh.disableBalancing() //禁用平衡器
sh.enableBalancing() //启用平衡器
db.runCommand( { removeShard: "mongodb0" } ) //删除分片mongodb0,迁移数据查看命令
db.runCommand( { movePrimary: "test", to: "mongodb1" }) //将数据库test未分片mongodb0的数据,迁移到mongodb1主分片。
db.adminCommand("flushRouterConfig") //处理分片后,刷新路由数据。
use config
db.databases.find() //查看所有数据库使用分片
db.settings.save({_id:"chunksize",value:1}) //将 chunk 的大小调整为 1MB
db.serverStatus().sharding
rs.status() //查看成员的运行状态等信息
rs.config() //查看配置信息
rs.slaveOk() //允许在SECONDARY节点上进行查询操作,默认从节点不具有查询功能
rs.isMaster() //查询该节点是否是主节点
rs.add({}) //添加新的节点到该副本集中
rs.remove() //从副本集中删除节点
rs.stepDown //降级节点
db.printSlaveReplicationInfo() //查看同步情况
rs.addArb("172.20.0.16:27038") //添加仲裁节点
config=rs.conf()
config.members=[config.members[0],config.members[1],{_id:5,host:"127.0.0.1:27023",priority:5,arbiterOnly:"true"}]
rs.reconfig(config,{force:true})
cfg = rs.conf()
cfg.members[0].priority = 0.5
cfg.members[1].priority = 0.5
cfg.members[2].priority = 1
rs.reconfig(cfg)
mongodump -h 127.0.0.1:27017 -d test -o /data/backup/
mongorestore -h 127.0.0.1:27017 -d test --dir /data/db/test
|