ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
[TOC] 参考 :[https://cnodejs.org/topic/599e1c1fbae6f2ed6f7e4cb5](https://cnodejs.org/topic/599e1c1fbae6f2ed6f7e4cb5) ### MongoDB分片集群 **(Sharding)** ***** Sharding cluster是一种可以水平扩展的模式,在数据量很大时特给力,实际大规模应用一般会采用这种架构去构建 **MongoDB分片群集主要有如下三个组件:** * Shard:分片服务器,用于存储实际的数据块,实际生产环境中一个shard server 角色可以由几台服务器组成一个Peplica Set 承担,防止主机单点故障。 * Config Server:配置服务器,存储了整个分片群集的配置信息,其中包括chunk信息。 * Routers:前端路由,客户端由此接入,且让整个群集看上去像单一数据库,前端应用可以透明使用。 **为何需要水平分片** 1)减少单机请求数,将单机负载,提高总负载 2)减少单机的存储空间,提高总存空间 ` ` #### Linux下构建 虚拟机一 | **角色** | **IP** | **端口** | **副本集名称** | | --- | --- | --- | --- | | mongos| 192.168.0.174|27017| | | shard1| 192.168.0.174|27018| rep_shard1| | shard2| 192.168.0.174|27019| rep_shard2| | confserver| 192.168.0.174|2000| rep_confsvr| ``` docker run -it --net=mynet --ip=192.168.0.174 -p 17017:27017 -p 17018:27018 -p 17019:27019 -p 10000:20000 -v /root/Docker/Mongodb/sd174/:/data/ --privileged=true --name mongo_v1 mongo:latest /bin/bash ``` 虚拟机二 | **角色** | **IP** | **端口** | **副本集名称** | | --- | --- | --- | --- | | mongos| 192.168.0.175|27017| | | shard1| 192.168.0.175|27018| rep_shard1| | shard2| 192.168.0.175|27019| rep_shard2| | confserver| 192.168.0.175|2000| rep_confsvr| ``` docker run -it --net=mynet --ip=192.168.0.175 -p 27017:27017 -p 27018:27018 -p 27019:27019 -p 20000:20000 -v /root/Docker/Mongodb/sd175/:/data --privileged=true --name mongo_v2 mongo:latest /bin/bash ``` 虚拟机三 | **角色** | **IP** | **端口** | **副本集名称** | | --- | --- | --- | --- | | shard1| 192.168.0.176|27018| rep_shard1| | shard2| 192.168.0.176|27019| rep_shard2| | confserver| 192.168.0.176|2000| rep_confsvr| ``` docker run -it --net=mynet --ip=192.168.0.176 -p 37017:27017 -p 37018:27018 -p 37019:27019 -p 30000:20000 -v /root/Docker/Mongodb/sd176/:/data/ --privileged=true --name mongo_v3 mongo:latest /bin/bash ``` ` ` ##### 搭建配置服务器 因为Mongodb3.4版本后需要配置服务器必须配置为副本集,所以需要给**配置服务器配置副本集** 分别在三台机器上创建config01目录 ``` >mkdir config01 ``` 在三台机器上分别执行命令: ``` mongod --dbpath config01 --replSet conServer --configsvr --port 20000 --bind_ip_all ``` 然后通过mongo随意进入一个副本集成员,并为配置服务器的副本集进行配置: ``` mongo --port 20000 --host localhost > var conf = { _id: 'conServer', version: 1, members: [ { _id: 0, host: '192.168.0.174:20000' }, { _id: 1, host: '192.168.0.175:20000' }, { _id: 2, host: '192.168.0.176:20000' } ] }; > rs.initiate(conf); var conf = { _id: 'conServer', version: 1, members: [ { _id: 0, host: '192.168.0.90:27100' }, { _id: 1, host: '192.168.0.90:27101' }, { _id: 2, host: '192.168.0.90:27102' } ] }; ``` 至此我们的配置服务器配置完成。 ` ` ##### 搭建分片服务器 官方建议我们的分片服务区至少在3个或以上才能发挥出更好的性能,我们这里也创建三个分片服务器。 下面创建三个空数据库目录,然后启动它们,在启动的时候需要加上[`--shardsvr`]以表示这是一个分片服务器(没有强制是副本集)分别在三台机器上创建分片副本集**shardServer0**, **shardServer1**, **shardServer2**: ``` $ mkdir sd01 sd02 $ mongod --dbpath sd01 --shardsvr --port 27018 --replSet rep_shard1 --bind_ip_all $ mongod --dbpath sd02 --shardsvr --port 27019 --replSet rep_shard2 --bind_ip_all ``` 启动每台虚拟机的 27018 实例即分片 1 并配置副本集: ``` >mongo --port 27018 --host localhost >var conf = { _id: 'rep_shard1', version: 1, members: [ { _id: 0, host: '192.168.0.174:27018 ' }, { _id: 1, host: '192.168.0.175:27018' }, { _id: 2, host: '192.168.0.176:27018' } ] }; > rs.initiate(conf); var conf = { _id: 'rep_shard3', version: 1, members: [ { _id: 0, host: '192.168.0.90:27022' } ] }; ``` 启动每台虚拟机的 27019 实例即分片 2 并配置副本集: ``` >mongo --port 27019 --host localhost >var conf = { _id: 'rep_shard2', version: 1, members: [ { _id: 0, host: '192.168.0.174:27019 ' }, { _id: 1, host: '192.168.0.175:27019' }, { _id: 2, host: '192.168.0.176:27019' } ] }; > rs.initiate(conf); ``` 启动虚拟机一和虚拟机二的 27017 实例即 mongos 路由,注意这里是通过 mongos 启动非 mongod ` ` ` ` ##### 搭建路由服务器 mongodb提供了一个路由工具,它会随着我们下载包一起下载,名字为`mongos`或`mongos.exe`,通过它配置路由功能。 启动路由我们需要加上参数[`--configdb`](https://docs.mongodb.com/manual/reference/program/mongos/),它的语法为: ``` --configdb 配置服务器副本集名称/配置服务器1地址端口,配置服务器1地址端口... ``` 启动路由,并为路由指定一个端口,用于开放给客户端链接: ``` $ mongos --configdb conServer/192.168.0.174:20000,192.168.0.175:20000,192.168.0.176:20000 --port 27017 --bind_ip_all ``` 登录虚拟机一的 mongos 终端,和普通登录 MongoDB 一样,只需将端口改成 mongos 的端口 27017 即可,运行以下命令将 rep_shard1 和 rep_shard2 分片加入集群,到此一个分片环境已经搭建完成: ``` sh.addShard("rep_shard1/192.168.0.174:27018,192.168.0.175:27018,192.168.0.176:27018") sh.addShard("rep_shard2/192.168.0.174:27019,192.168.0.175:27019,192.168.0.176:27019") ``` ` ` ##### 验证分片集群是否搭建成功 通过运行`sh.status()`命令可以查看分片相关信息,如有以下输出,说明分片集群搭建成功。 ` ` ##### 创建新用户 这里的登录密码就是config集群配置的用户名和密码;上面介绍的两种登录方式在这里也适用;这里用mongo连接的时候 端口可以不指定 因为mongo默认的启动端口就是27017 和我们这边设置的相同; 这里使用root用户登录: ``` mongo; use admin; db.auth('root','root'); ``` 登录到任意一台route服务器,已root用户登录,并创建新用户; ``` mongo; use admin; db.auth('root','root'); use database01; db.createUser( { user: "readWrite", pwd: "readWrite", roles: [ { role: "readWrite", db: "database01" } ] } ) ``` ` ` #### 单机构建分片 ***** ##### 搭建配置服务 首先建立三个空的数据库目录,用于搭建配置服务器的副本集,并分别启动它们,在启动的时候需要加上我们副本集的名称和[`--configsvr`](https://docs.mongodb.com/manual/reference/program/mongod/)来表示这是一个配置服务器,并分别指定不同的端口: ``` mkdir config01 config02 config03 mongod --dbpath C:\Users\Administrator\Desktop\Pkg\mongodb\config01 --replSet conServer --configsvr --port 10000 --bind_ip_all mongod --dbpath C:\Users\Administrator\Desktop\Pkg\mongodb\config02 --replSet conServer --configsvr --port 10001 --bind_ip_all mongod --dbpath C:\Users\Administrator\Desktop\Pkg\mongodb\config03 --replSet conServer --configsvr --port 10002 --bind_ip_all ``` 随便进入哪一个副本: ``` mongo --port 10000 --host localhost ``` 添加其他副本集: ``` var conf = { _id: 'conServer', version: 1, members: [ { _id: 0, host: 'localhost:10000' }, { _id: 1, host: 'localhost:10001' }, { _id: 2, host: 'localhost:10002' } ] }; rs.initiate(conf); ``` ` ` ##### 搭建分片服务器 创建三个空目录,在启动的时候需要加上[`--shardsvr`](https://docs.mongodb.com/manual/reference/program/mongod/)以表示这是一个分片服务器: ``` mkdir sh0 sh1 sh2 mongod --dbpath C:\Users\Administrator\Desktop\Pkg\mongodb\shard01 --shardsvr --port 20000 mongod --dbpath C:\Users\Administrator\Desktop\Pkg\mongodb\shard02 --shardsvr --port 20001 mongod --dbpath C:\Users\Administrator\Desktop\Pkg\mongodb\shard03 --shardsvr --port 20003 ``` ` ` ##### 搭建路由服务器 启动路由,并为路由指定一个端口,用于开放给客户端链接: ``` mongos --configdb conServer/localhost:10000,localhost:10001,localhost:10002 --port 3000 --bind_ip_all ``` 添加分片服务 ``` mongo --port 3000 --host localhost > sh.addShard('ip:20000'); > sh.addShard('ip:20001'); > sh.addShard('ip:20002'); ``` 如果你可以通过`rs.status()`方法中返回的`shards`字段看是否添加成功。 删除分片 ``` db.adminCommand( { removeShard: "shard0000" } ) ``` ` ` ##### 配置片键 到目前为止,分片服务器已经搭建完成,但是目前分片服务器无法正常工作,我们所有的操作都将在随机的一个主分片上操作,这是因为分片服务器不知道怎么进行分片,所以我们还需要配置片键来告诉分片服务器按照什么来分片。 分片是基于数据库集合中的文档的一个键进行分片的,比如选择username键,那么会根据这个键的顺序就行分片,而mongodb会自动平衡分片的数据。 Mongodb要求作为片键的键必须是索引过的,所以我们在建立片键之前需要对键进行索引,建立后片键就是集合中的最重要的索引。 在生产环境中建议先想好数据建构建立索引和片键后开始操作数据,这样会减轻分片服务器的负载。 首先我们在需要进行分片的数据库上开启分片功能,通过`sh.enableSharding`方法开启。 ``` mongo --port 3000 --host localhost sh.enableSharding('test'); ``` 然后在开启分片的数据库中的test集合插入测试数据,注意此时我们还没有进行配置片键,所以所有的数据操作都在分片服务器随机分配的一个主分片上面进行的。 ``` for(var i = 0; i < 100; i++){ db.test.insert({ username: 'user' + i, idNum: i }) } ``` 这时候以username为片键,通过[`sh.shardCollection`](https://docs.mongodb.com/manual/reference/method/sh.shardCollection/)方法进行建立,它的语法为: ``` sh.shardCollection(namespace, key, unique, options) ``` 首先给我们要建立的片键建立索引: ``` > db.test.ensureIndex({'username': 1}); ``` 然后建立片键: ``` > sh.shardCollection('test.test', {username:1}); ``` 等待几分钟后,可以通过`sh.status`方法查看数据分片的情况了,可以从中很清楚的看见哪些数据在哪个分片服务器上面,并且通过[`explain`](https://wuyizhou.com/2017/08/mongodb-index-one.html)方法来查看我们查询的过程中哪些分片服务器参与了查询。 ### 分片 [分片](https://s0docs0mongodb0com.icopy.site/manual/reference/glossary/#term-sharding)是一种用于在多台计算机之间分配数据的方法. MongoDB使用分片来支持具有非常大的数据集和高吞吐量操作的部署. ### MongoDB分片集群 MongoDB分片[群集](https://s0docs0mongodb0com.icopy.site/manual/reference/glossary/#term-sharded-cluster)由以下组件组成: ``` * 碎片:每个碎片包含碎片数据的子集. 每个分片都可以部署为[副本集] * mongos:`mongos`充当查询路由器,在客户端应用程序和分片群集之间提供接口. * config服务器:配置服务器存储集群的元数据和配置设置. 从MongoDB 3.4开始,必须将配置服务器部署为副本集(CSRS). ``` ### 分片key MongoDB使用分片[键]在各个分片之间分发集合的文档. 分片[键](https://s0docs0mongodb0com.icopy.site/manual/reference/glossary/#term-shard-key)由目标集合中每个文档中存在的一个或多个字段组成. 1. 在分片集合时选择分片键. 分片后不能更改分片键的选择. 分片集合只能有*一个分片*密钥. 请参阅分片[密钥规范](https://s0docs0mongodb0com.icopy.site/manual/core/sharding-shard-key/#sharding-shard-key-creation). 2. 要分片非空集合,该集合必须具有以分片键开头的[索引]. 对于空集合,如果集合尚不具有指定分片键的适当索引,则MongoDB会创建索引. 3. 分片密钥的选择会影响分片群集的性能,效率和可伸缩性. 选择分片密钥可以使具有最佳硬件和基础结构的群集成为瓶颈.[分片]密钥及其后备索引的选择也会影响群集可以使用的[分片策略](https://s0docs0mongodb0com.icopy.site/manual/sharding/#sharding-strategy). ![dGh0JO.png](https://s1.ax1x.com/2020/08/20/dGh0JO.png)