自建MongoDB实践:MongoDB 分片集群
垂直扩容的主要缺点是它有限制:它不能无限扩大,这取决于多方面的因素。诸如:硬件已达到其物理极限、云提供商不能为我们提供更强大的服务器。
提高性能的第二种方法是使用具有相同容量的服务器并增加其数量,一般我们称之为水平扩容(或横向扩容)。
当数据量比较大的时候,我们需要把数据分片运行在不同的机器中,以降低 CPU、内存和 IO 的压力,Sharding 就是数据库分片技术。
MongoDB 分片技术类似 MySQL 的水平切分和垂直切分,数据库主要由两种方式做 Sharding:垂直扩展和横向切分。
垂直扩展:添加更多的 CPU,内存,磁盘空间等。
横向切分:则是通过数据分片的方式,通过集群统一提供服务。
一个 MongoDB 分片集群由以下组件组成:
- shard: 每个分片都包含分片数据的一个子集。每个分片以副本集部署。
- mongos: Mongos 充当查询路由器,在客户端应用程序和分片集群之间提供接口。从 MongoDB 4.4 开始,mongos 可以支持 hedged 读取,以尽量减少延迟。
- config servers: 配置服务器存储集群的元数据和配置信息。
MongoDB 在 Collection 级别进行分片处理,在集群中的分片之间分发这些 Collection 数据。
一个生产环境的集群,请确保数据的冗余性及系统的高可用性。对于一个生产级别的分片集群,需要考虑一下几点:
- 部署一个 3 成员的复制集作为一个配置中心服务
- 每个分片部署为一个 3 成员的复制集
- 部署一个或多个 mongos 路由
环境准备
- 开始演示:
主机名 | IP | 角色 |
mongo01.tyun.cn | 10.20.20.19 | mongos1(27017),config1(27000),shard1 primary(27010) |
mongo02.tyun.cn | 10.20.20.11 | mongos2(27017),config2(27000),shard1 secondary(27010) |
mongo03.tyun.cn | 10.20.20.41 | mongos3(27017),config3(27000),shard1 secondary(27010) |
mongo04.tyun.cn | 10.20.20.14 | shard2 primary(27010) |
mongo05.tyun.cn | 10.20.20.53 | shard2 secondary(27010) |
mongo06.tyun.cn | 10.20.20.61 | shard2 secondary(27010) |
mongo07.tyun.cn | 10.20.20.62 | shard3 primary(27010) |
mongo08.tyun.cn | 10.20.20.89 | shard3 secondary(27010) |
mongo09.tyun.cn | 10.20.20.99 | shard3 secondary(27010) |
如果大家在演示该文档时,手头上的机器资源不充足的话,可以安排一台多个角色即可(使用不同的端口号),不一定非得一台机器一个角色。
- 环境拓扑如下:
这里我们使用了静态 DNS 解析,如果有条件,可以用 DNS 服务进行域名的配置解析。/etc/hosts 文件如下:
配置 Config Server
01准备配置文件
在 3 台配置节点上分别创建配置文件 /etc/mongo-cfg.conf,内容如下:
02启动 Config Server
在 3 台配置节点上分别执行如下命令:
检查一下进程是否已经启动成功:
03初始化 Config Server
登录到第一个节点上,这时还没有创建用户及密码,所以登录时没有指定密码也是可以登录的。
除了创建用户,其实什么也不能操作。接下来的第一件事情是创建用户及密码:
接着初始化 Config Server:
需要等待 10 秒钟左右,3 个 Config Server 会通过选举产生主节点。
注意提示符变化:
至此,Config Server 配置完成。
配置 Replica Set
Replica Set 的配置请参考 Replica Set 章节。分片 1 的集群节点为:
- mongo04.tyun.cn:27010
- mongo05.tyun.cn:27010
- mongo06.tyun.cn:27010
配置 Mongos
01准备 mongos 配置文件
一个相对完整的配置文件(以 mongos1 为例):
02启动 mongos
mongos 也可以通过配置文件的形式启动:
启动命令如下:
添加 shard1 分片到分片集
增加第一个分片 shard1 到集群中:
创建分片表
接下来我们创建一个测试库 test,然后在 test 库上创建集合 shard,并开启分片。
我们可以看到 shard1 中有 2 chunk。
插入测试数据:
这时我们也可以登录到 shard1 复本集里面查看一下数据(找到主节点进行登录):
添加 shard2 分片到分片集
Replica Set 的配置请参考 Replica Set 章节。分片 1 的集群节点为:
- mongo07.tyun.cn:27010
- mongo08.tyun.cn:27010
- mongo09.tyun.cn:27010
shard2 复本集验证:
接着把 shard2 加入到分片集中(连接任意一台 mongos):
从输出可以看到,shard1 的 2 个 chunk,已经分配到了 shard2 上面了,这是 MongoDB 的自动均衡机制起作用了。
看看每个 Shard 的文档数量有多少?
从两个分片中的文档数量来看,数据存放基本是均衡的。
删除分片:
查看移动的状态:
移动 DB 到其它分片:
总结
分片具有很大的灵活性。
不过,我们在执行某些操作时还存在一些限制。
我们将在以下列表中突出显示最重要的内容:
01group() 命令不起作用。我们应该使用 aggregate() 和聚合框架,或者 mapreduce()。
02db.eval() 命令不起作用,出于安全原因,在大多数情况下应将其禁用。
03更新操作时的 $isolated 选项不起作用。这是分片环境中缺少的功能。update() 的 $isolated 选项提供了保证,如果我们一次更新多个文档,其他读者和作者将看不到一些更新了新值的文档,而其他文档仍然具有旧值。这是在 unsharded 中实现的方式环境是通过持有全局写锁和/或将操作序列化到单个线程来确保对受 update() 影响的文档的每个请求都不会被其他线程/操作访问。此实现意味着它不是高性能的并且不支持任何并发,这禁止在分片环境中使用 $isolated 运算符。
04不支持查询的 $snapshot 运算符。find() 游标中的 $snapshot 运算符可防止文档由于在更新后被移动到磁盘上的不同位置,在结果中出现不止一次。$snapshot 运算符的操作成本很高,通常不是硬性要求。替代它的方法是对我们查询的字段使用索引,该字段的键在查询期间不会更改。
05如果我们的查询不包含分片键,索引将无法覆盖我们的查询。分片环境中的结果将来自磁盘,而不仅仅是来自索引。唯一的例外是如果我们只在内置的 _id 字段上查询并且只返回 _id 字段,在这种情况下,MongoDB 仍然可以使用内置索引覆盖查询。
06update()和remove()操作的工作方式不同。分片环境中的所有update()和remove()操作必须包括要受影响的文档的_id 或分片键;否则,mongos 路由器将不得不对所有集合、数据库和分片进行全表扫描,这在操作上会非常耗时。
07跨分片的唯一索引需要包含分片键作为索引的前缀。换句话说,要实现跨分片文档的唯一性,我们需要遵循 MongoDB 对分片遵循的数据分布。
08分片键的大小不得超过 512 字节。分片键索引必须在被分片的键字段和可选的其他字段上按升序排列,或者在其上的哈希索引。
相关文章
- Pandas 人口密度案例分析
- Pandas练习
- Pandas分析泰坦尼克号生还比例
- Pandas处理股票数据
- Pandas resample数据重采样
- Pandas分组聚合
- Pandas数据合并
- DataFrame基础
- Series基础
- 顺序表
- SQL技巧:查询某个表关联的所有存储过程
- 数据采集之登录那些事
- 压缩Sqlite数据文件大小,解决数据删除后占用空间不变的问题
- 网站添加数据出错,原来是MS SQL Server2008日志文件占据空间过大导致的
- 如何有效改进回顾会议(下)?
- PostgreSQL(02): PostgreSQL常用命令
- AIR32F103(六) ADC,I2S,DMA和ADPCM实现的录音播放功能
- DS18B20数字温度计 (二) 测温, ROM和CRC算法
- 商业智能中的决策, 数据和数据处理方法
- 数据类产品设计和实现思路