一、如何用好分片集群

1、合理的架构

  • 是否需要分片
  • 需要多少分片
  • 数据的分布规则

2、正确的姿势

  • 选择需要分片的表
  • 选择正确的片键
  • 使用合适的均衡策略

3、足够的资源

  • CPU
  • RAM
  • 存储

二、分片的基本标准

  • 关于数据:数据量不超过 3TB,尽可能保持在 2TB一个片;
  • 关于索引:常用索引必须容纳进内存;
  • 按照以上标准初步确定分片后,还需要考虑业务压力,随着压力增大, CPU、 RAM、磁盘中的任何一项出现瓶颈时,都可以通过添加更多分片来解决。

三、如何粗略判断需要多少分片

  • A = 所需存储总量 / 单服务器可挂载容量
  • B = 工作集大小 / (单服务器内存容量 * 0.6)
  • C = 并发量总数 / (单服务器并发量 * 0.7)

分片数量 = max(A, B, C) =?

例子:

A = 8TB / 2TB = 4
B = 400GB / ( 256G \* 0.6) = 3 C = 30000 / (9000\*0.7) = 6 分片数量 = max(A, B, C) = 6

四、额外的考量

考虑分片的分布:

  • 是否需要跨机房分布分片?
  • 是否需要容灾?
  • 高可用的要求如何 ?

五、选择片键的正确姿势

  • 片键 shard key:文档中的一个字段 ,也就是我们要选择的分片键
  • 文档 doc :包含 shard key 的一行数据
  • 块 Chunk :是一个逻辑的概念,包含 n 个文档,通常是 64M, 从 6.0.3开始不以 chunk进行均衡,而是 以为数据量进行均衡
  • 分片 Shard:包含 n 个 chunk
  • 集群 Cluster: 包含 n 个分片

  • 正确的姿势 ——选择合适的片键 影响片键效率的主要因素:
  • 取值基数( Cardinality);
  • 取值分布;
  • 分散写,集中读;
  • 被尽可能多的业务场景用到;
  • 避免单调递增或递减的片键;

5.1 准则 1:选择基数大的片键

对于小基数的片键:

  • 因为备选值有限,那么块的总数量就有限;
  • 随着数据增多,块的大小会越来越大;
  • 水平扩展时移动块会非常困难;

例如:存储一个高中的师生数据,以年龄(假设年龄范围为 15~65岁)作为片键, 15<=年龄 <=65,且只为整数 ,所以最多只会有 51个 chunk

结论:取值基数要大!

5.2 准则 2:选择分布均匀的片键

对于分布不均匀的片键:

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

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

  • 15<=年龄 <=65,且只为整数
  • 大部分人的年龄范围为 15~18岁(学生)
  • 15、 16、 17、 18四个 chunk 的数据量、访问压力远大于其他 chunk **结论:取值分布应尽可能均匀。

5.3 准则 3:查询的时候定向性好

考虑:

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

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

5.4 通过一个例子来看片键选择

我们用一个 Email系统的例子来学习下片键,这是一个 email的文档,里面有 id, id就是自增的,无穷大

{
  "_id": ObjectId(),
  "user": 123,
  "time": Date(),
  "subject": "...",
  "recipients": [],
  "body": "...",
  "attachments": []
}

5.4.1 选择片键:

5.4.2 选择片键:

5.4.3 选择片键:

5.4.4 选择片键:

六、如何规划硬件

  • mongos 与 config 通常消耗很少的资源,可以选择低规格虚拟机;
  • 资源的重点在于 shard 服务器:
  • 需要足以容纳热数据索引的内存;
  • 正确创建索引后 CPU 通常不会成为瓶颈,除非涉及非常多的计算;
  • 磁盘尽量选用 SSD;

实际测试是最好的检验,来看你的资源配置是否完备。 另外,即使项目初期已经具备了足够的资源,仍然需要考虑在合适的时候扩展。建议监控 各项资源使用情况,无论哪一项达到 60%以上,则开始考虑扩展。因为:

  • 扩展需要新的资源,申请新资源需要时间;
  • 扩展后数据需要均衡,均衡需要时间。应保证新数据入库速度慢于均衡速度
  • 均衡需要资源,如果资源即将或已经耗尽,均衡也是会很低效的。