API 文档

分片集群问题

最近更新时间:2022-03-22 17:15:13

MongoDB 是否支持分片(sharding)?

支持,详情参见 创建分片集群

什么是 MongoDB 分片集群?

云数据库 MongoDB 目前已经支持分片功能。

  • 分片集群将数据按照片键分布存储在多台物理机上,平滑的扩展能力,非常适用于 TB 或 PB 级的数据存储场景。
  • 分片集群支持实例级别的备份和回档来保证数据高可靠。每个分片内采用多节点自动容灾的机制,保证服务高可用。
  • 可以使用腾讯云 MongoDB 分片功能便捷高效的搭建海量分布式存储系统。

如何创建 MongoDB 分片集群?

登录 MongoDB 购买页 ,在实例类型选择分片集群,按需选择分片的片数,片内节点数,以及节点规格。
每个分片都是多节点的副本集,片内多节点自动容灾,保证服务高可用。

如何查询 MongoDB 分片集群的信息?

控制台 中可以查看分片集群实例的详细信息,如分片的构成,片节点的规格和已使用容量,同时也可以在控制台上进行实例的 续费管理 以及 扩容 等操作。

MongoDB 分片集群扩容方式有哪些?

目前只支持将所有节点进行统一扩容,暂不支持通过添加节点的方式进行扩容。
控制台 实例列表页单击配置调整,选择需要扩到的容量规格。

MongoDB 如何实现分片集群实例监控?

云数据库 MongoDB 分片集群实例提供三个维度的监控指标,来进行整个集群的数据监控。

  • 实例维度
  • 片维度
  • 节点维度

提供操作请求,容量使用,负载等多项指标的监控数据,可在实例的系统监控页查看。

MongoDB 的分片策略是什么?

  • 支持 hash key 的分片机制。
  • 支持联合字段的 shard key。
  • 分片实例下所有数据集合必须使用分片,建议把不分片的数据放到单独的副本集实例下。

MongoDB 分片认证机制是什么?

MongoDB 完全兼容支持 SCRAM-SHA-1 和 MONGODB-CR 两种机制。

MongoDB 分片集群命令支持情况?

详细请参见 分片集群命令支持情况

分片集群选择分片方式应遵循什么原则?

分片集群需要提前对数据集合启用分片,片键对分片集群的读写性能起着至关重要的作用,低版本 MongoDB 一旦设置就不能修改。最优片键选择一般遵循如下原则 :

  • 保证写入的数据能均衡散列到多个分片。
  • 尽可能保证高频查询能在一个分片获取到数据,避免从多个分片获取数据后 mongos 做聚合。
  • 如果是高频类的范围查询,建议采用范围分片。
  • 如果是高频类的指定查询,建议采用 hash 分片。

分片集群如何进行提前预分片?

对于分片集群来说,提前预分片,可以最大化保证数据均衡写入到多个分片,同时避免高峰期不同分片 chunks 不均衡而触发 moveChunk 操作引起的业务抖动。MongoDB 支持两种分片策略进行数据预分片。

Hash 预分片
hash 预分片,该功能默认支持,可通过以下命令实现,其中 n 为分片数。

sh.shardCollection("db.collection", {bookId:"hashed"}, false, { numInitialChunks: 8192*n} )

范围预分片
MongoDB 官方默认不支持范围预分片,因为无法知道用户的数据分布情况,您可以通过 splitAt 提前预分片,将数据分为指定范围的两部分。具体示例,请参见 MongoDB 官方网站

Balance 窗口设置
如果分片 chunk 不均衡会触发 moveChunk 来完成 balance 操作,moveChunk 过程会涉及到数据搬迁,会增加系统负载,业务高峰期会收到一定影响,因此建议在业务低峰期进行数据均衡操作,设置 balance 窗口。示例如下:

use config
db.settings.update({"_id":"balancer"},{"$set":{"activeWindow":{"start":"02:00","stop":"05:00"}}},true)

如何优化分片集群查询请求不带片键,导致数据库性能变差的问题?

问题现象
查询请求如果带上片键,可以保证数据落在对应的 shard,这样可以实现读性能的最大化。但是,实际业务场景中,一个业务访问同一个表,有些查询请求带有片键字段,而有些查询请求并不携带片键字段,这部分不带片键的查询请求便需要广播到多个 shard,之后经 mongos 聚合后再返回客户端,这类不带片键的查询效率较差。

解决方法
如果集群分片数比较多,不带片键的查询请求频率也很高,您可以通过建立辅助索引表来规避解决该问题。
例如,某 feed 信息流业务,每条 feed 信息对应一条详情数据,存放到 feed_info 详情表中。每条 feed 详情对应一条数据,如下:

{
"_id" : ObjectId("614498889f97fd4692d22991")
“feedId”: “223”
“userId”: 3445
“feedInfo”: “xxxxxxx”
}
由于该 feed_info 详情表会频繁按照 userId 进行查询,因此选择 userId 作为分片片键。但是业务除了根据 userId 查询外,也会根据 feedId 进行查询,并且 feedId 查询频率也很高,由于根据 feedId 查询不带片建,因此该类查询会广播到所有分片,在多分片场景性能会很差。

这时候就可以引入 FeedId_userId_relationship 辅助表采用 feedId 作为片键,该表和 feed_info 详情表的隐射关系如下图所示。

如上图,通过某个 feedId 查询具体 feed 信息,首先根据 feedId 从辅助索引表中查找该 feedId 对应的 userId,然后根据查询到的 userId+feedId 的组合获取对应的详情信息。整个查询过程需要查两个表,查询语句如下:

1.    //FeedId_userId_relationship 表分片片建为 feedId,提前 hashed 预分片  
2.    db.FeedId_userId_relationship.find({“FeedId”: “223”},  {userId: 1}) //假设返回的 userId 为“3445”  
3.    //feedInfo 表分片片键为 userId,提前 hashed 预分片  
4.    db.FeedInfo.find({“userId”: “3445”}) 
总之,通过引入辅助索引表,最终解决跨分片广播问题。但是引入辅助表会增加一定的存储成本,同时会增加一次辅助查询,建议只有在分片 shard 比较多,并且不带片键且查询比较频繁的情况使用。

目录