一 MongoDB 分片介绍
1.1 分片
MongoDB 另一种集群, 就是分片技术, 可以满足 MongoDB 数据量大量增长的需求.
当 MongoDB 存储海量的数据时, 一台机器可能不足以存储数据, 也可能不足以提供可接受的读写吞吐量. 这时, 可通过在多台机器上分割数据, 使得数据库系统能存储和处理更多的数据. 即通过分片进行水平扩展.
延伸:
复制与分片的区别: 复制时让多台服务器都拥有同样的数据副本, 每一台服务器都是其他服务器的镜像, 而每一个分片都和其他分片拥有不同的数据子集.
1.2 为什么使用分片
复制所有的写入操作到主节点
延迟的敏感数据会在主节点查询
单个副本集限制在 12 个节点
当请求量巨大时会出现内存不足.
本地磁盘不足
垂直扩展价格昂贵
1.3 分片的优势
分片为应对高吞吐量与大数据量提够了方法:
使用分片减少了每个分片需要处理的请求数: 通过水平扩展, 群集可以提高自己的存储容量. 比如, 当插入一条数据时, 应用只需要访问存储这条数据的分片.
使用分片减少了每个分片存储的数据: 分片的优势在于提供类似线性增长的架构, 提高数据可用性, 提高大型数据库查询服务器的性能. 当 MongoDB 单点数据库服务器存储成为瓶颈, 单点数据库服务器的性能成为瓶颈或需要部署大型应用以充分利用内存时, 可以使用分片技术.
二 MongoDB 分片架构
2.1 主要组件
Shard: 用于存储实际的数据块, 实际生产环境中一个 shard server 角色可由几台机器组个一个 replica set 承担, 防止主机单点故障.
Config Server:mongod 实例, 存储了整个 ClusterMetadata, 其中包括 chunk 信息.
Query Routers: 前端路由, 客户端由此接入, 且让整个集群看上去像单一数据库, 前端应用可以透明使用.
数据划分
MongoDB 的数据划分, 是以集合级别为标准. 分片通过 shard key 来划分集合数据.
2.2 shard key
在集合中分发文档, MongoDB 使用 shard key 对进行进行分片. shard key 既可以是集合的每个文档的索引字段也可以是集合中每个文档都有的组合索引字段.
MongoDB 将 shard keys 值按照块 (chunks) 划分, 并且均匀的将这些 chunks 分配到各个分片上. MongoDB 使用基于范围划分或基于散列划分来划分 chunks 的.
注意: 确定 shard key 时需要谨慎, 以确保集群性能和效率. 分片后不能更改 shard key, 也不能取消分片.
2.3 分片集和非分片集
数据库可以混合使用分片和非分片集合. 分片集合在集群中的分片上进行分区和分布, 非分片集合存储在主分片上, 每个数据库都有自己的主分片.
2.4 分片集连接
可以使用与连接到单个 mongos 相同的方式连接分片集 mongod, 如通过 mongoshell 或 MongoDB 驱动程序. 但必须连接到 mongos 路由器, 才能与分片集群中的任何集合进行交互. 这包括分片和非分片集合, 客户端永远不应连接到单个分片以执行读取或写入操作.
三 分片策略
3.1 基于范围划分
MongoDB 通过 shard key 值将数据集划分到不同的范围就称为基于范围划分.
对于数值型的 shard key: 可以虚构一条从负无穷到正无穷的直线(理解为 x 轴), 每个 shard key 值都落在这条直线的某个点上, 然后 MongoDB 把这条线划分为许多更小的没有重复的范围成为块(chunks), 一个 chunk 就是某些最小值到最大值的范围.
3.2 基于散列划分
MongoDB 计算每个字段的 hash 值, 然后用这些 hash 值建立 chunks. 基于散列值的数据分布有助于更均匀的数据分布, 尤其是在 shard key 单调变化的数据集中.
但是, 散列分布意味着对 shard key 的基于范围的查询不太可能以单个分片为目标, 从而导致更多群集范围的广播操作.
基于范围和基于散列划分的性能比较:
基于范围划分对于范围查询比较高效. 假设在 shard key 上进行范围查询, 查询路由很容易能够知道哪些块与这个范围重叠, 然后把相关查询按照这个路线发送到仅仅包含这些 chunks 的分片.
但是基于范围划分很容易导致数据不均匀分布, 这样会削弱分片集群的功能. 例如当 shard key 是个成直线上升的字段, 如时间. 那么, 所有在给定时间范围内的请求都会映射到相同的 chunk, 也就是相同的分片上. 这种情况下, 小部分的分片将会承受大多数的请求, 那么系统整体扩展并不理想.
相反的, 基于散列划分是以牺牲高效范围查询为代价, 它能够均匀的分布数据, 散列值能够保证数据随机分布到各个分片上.
3.3 自定义标签划分
MongoDB 支持通过自定义标签标记分片的方式直接平衡数据分布策略, 可以创建标签并且将它们与 shard key 值的范围进行关联, 然后分配这些标签到各个分片上, 最终平衡器转移带有标签标记的数据到对应的分片上, 确保集群总是按标签描述的那样进行数据分布. 标签是控制平衡器行为及集群中块分布的主要方法.
四 数据均衡
新加入的数据及服务器都会导致集群数据分布不平衡, MongoDB 采用两种方式确保数据分布的平衡:
4.1 拆分
拆分是一个后台进程, 防止块变得太大. 当一个块增长到指定块大小的时候, 拆分进程就会块一分为二, 整个拆分过程是高效的. 不会涉及到数据的迁移等操作.
4.2 平衡
平衡器是一个后台进程, 管理块的迁移. 平衡器能够运行在集群任何的 mongd 实例上. 当集群中数据分布不均匀时, 平衡器就会将某个分片中比较多的块迁移到拥有块较少的分片中, 直到数据分片平衡为止.
举个例子: 如果集合 users 有 100 个块在分片 1 里, 50 个块在分片 2 中, 那么平衡器就会将分片 1 中的块迁移到分片 2 中, 直到维持平衡.
分片采用后台操作的方式管理着源分片和目标分片之间块的迁移. 在迁移的过程中, 源分片中的块会将所有文档发送到目标分片中, 然后目标分片会获取并应用这些变化. 最后, 更新配置服务器上关于块位置元数据.
4.3 从集群中增加和删除分片
添加新分片到集群中会产生数据不平衡, 因为新分片中没有块, 当 MongoDB 开始迁移数据到新分片中时, 等到数据分片平衡需要一定时间.
当删除一个分片时, 平衡器将会把分片中所有块迁移到另一个分片中, 在完成这些迁移并更新元数据后, 才可安全的删除分片了.
更多分片参考官方: https://docs.mongodb.com/manual/sharding/#sharding-strategy
相关参考:
- https://blog.51cto.com/13643643/2148825
- https://www.cnblogs.com/Jtianlin/p/5128977.html
- https://www.jianshu.com/p/cb55bb333e2d
来源: https://www.cnblogs.com/itzgr/p/11019870.html