为什么要使用分片集群?

  • 数据容量日益增大,访问性能日渐降低,怎么破?
  • 新品上线异常火爆,如何支撑更多的并发用户?
  • 单库已有10TB数据,恢复需要1一2天,如何加速?
  • 数据需要服务全球用户,如何让全球的用户全部快速,低延迟地访问数据?

分片集群

完整的分片集群包括以下几个部分:

  • 路由节点(mongos):为应用程序提供集群的单一入口,转发应用端请求,选择合适的数据节点进行读写,合并多个数据节点的返回.
    • 无状态
    • 建议至少2个,主要是做高可用,还可以做负载均衡.
  • 配置节点(config):配置节点是标准的MongoDB复制集,,这三个节点的数据相同,提供集群元数据存储,分片数据分布的映射.
  • 数据节点(mongod):以复制集为单位,横向扩展,最大1024分片,分片之间数据不重复,所有分片在一起才完整工作.

分片集群特点:

  • 应用全透明,无特殊处理:分片集群的应用程序和单复制集的应用程序相同,不需要进行代码修改.
  • 数据自动均衡:自动检测各节点数据分布情况,如果不平衡,MongoDB自动将一分片的数据搬到另一分片.
  • 动态扩容,无须下线:不用一开始就构建分片集群,可以是复制集.当需要的时候,可以动态在线上增加新的复制集.

数据分布方式

基于范围

选一个或几个组合字段,把字段的值的范围分成多个范围块,如chunk1,chunk2….将这些chunk分配到不同的分片中.

优点:

  • 片键范围查询性能好.相邻的数据保存在同一节点中.读性能提高

缺点:

  • 数据分布可能不均匀,容易有热点.比如以自增主键为片键,写操作总是最新的分片中.

基于哈希

如果不希望有热分片,热点写的话,可以使用哈希方式.

将某个字段直接求哈希,放到对应的分片中.写操作可以随机分布到各个分片中.

优点:

  • 数据分布均匀,写优化.

缺点:

  • 范围查询效率低.每次范围查询都需要跨大量分片.

基于哈希的分片方式适合日志,物联网等高并发写入场景.

自定义Zone

如果数据有天然的地域性,某个区域的数据只用于某个区域的用户.这时可以给数据进行地域标签化.可以根据这些地域进行分片.

小结

分片集群可以有效解决性能瓶颈及系统扩容问题. 分片额外消耗较多,管理复杂,尽量不要分片,最好是在复制集中进行优化,实在无法支持再进行分片.

分片集群设计

如何用好分片集群

需要多少分片

分片的基本标准:

  • 关于数据:数据量不超过3TB,尽可能保持在2TB一个片;
  • 关于索引:常用索引必须容纳进内存;

按照以上标准初步确定分片后,还需要考虑业务压力,随着压力增大,CPU、RAM、磁盘中的任何一项出现瓶颈时,都可以通过添加更多分片来解决。

下面有个公式可以简单计算分片的数量:

工作集包括热数据和索引所占的空间:

  • 索引通过index.stats可以得到
  • 热数据和应用场景有关.新闻的热数据是最近几天的新闻,电商的热数据是商品详情.

单服务器内存容量:MongoDB默认用来做缓存的内存是物理内存的60%.

分片概念

各种概念由小到大:

  • 片键shard key:文档中的一个字段或多个组合字段,是分片的准则.
  • 文档doc:包含shardkey的一行数据.MongoDB存储的基本单位.
  • 块Chunk :包含n个文档,通常为64MB.包含文档数量取决于文档的大小.分片集群的均衡以块为单位.
  • 分片Shard:包含n个chunk
  • 集群Cluster:包含n个分片

选择合适片键

影响片键效率的主要因素:

  • 取值基数(Cardinality)
  • 取值分布
  • 分散写,集中读
  • 被尽可能多的业务场景用到
  • 避免单调递增或递减的片键

选择基数大的片键

对于小基数的片键:

  • 因为备选值有限,那么块的总数量就有限;
  • 随着数据增多,块的大小会越来越大;
  • 太大的块,会导致水平扩展时移动块会非常困难。因为MongoDB以块为单位进行分片均衡.如果块过大,分片均衡困难.

例如:存储一个高中的师生数据,以年龄( 假设年龄范围为15~65岁)作为片键,那么

  • 15<=年龄<=65,且只为整数
  • 最多只会有51个chunk

结论:取值基数要大!

选择分布均匀的片键

对于分布不均匀的片键:

  • 造成某些块的数据量急剧增大
  • 这些块压力随之增大
  • 数据均衡以chunk为单位,所以系统无能为力

例如:存储一个学校的师生数据,以年龄(假设年龄范围为15~65岁)作为片键,那么:

  • 15<=年龄<=65,且只为整数
  • 大部分人的年龄范围为15~18岁(学生)
  • 15、16、17、18四个chunk的数据量、访问压力远大于其他chunk

结论:取值分布应尽可能均匀

定向性好

考虑:

4个分片的集群,你希望读某条特定的数据.如果你用片键作为条件查询,mongos可以直接定位到具体的分片如果你不用片键, mongos需要把查询发到4个分片等最后的一个分片响应,mongos才能响应应用端。

结论:对主要查询要具有定向能力

足够的资源

mongos与config通常消耗很少的资源,可以选择低规格虚拟机;

资源的重点在于shard服务器:

  • 需要足以容纳热数据索引的内存;
  • 正确创建索引后CPU通常不会成为瓶颈,除非涉及非常多的计算;
  • 磁盘尽量选用SSD。

最后,实际测试是最好的检验,来看你的资源配置是否完备。