云数据库 MongoDB

分片集群问题

最近更新时间:2024-10-15 10:43:21

我的收藏

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 比较多,并且不带片键且查询比较频繁的情况使用。

如何清理孤儿文档?

在 MongoDB 分片集群中,由于数据迁移或其他操作中的意外情况,导致某些文档完成了复制但没有完成删除。使得同一份文档将会存在于两个 Shard 中。Config Server 记录这条文档的所属 Shard 信息,另一个 Shard 上的文档会存在但不会被感知,后续的 update、delete 操作都不会作用于这个错误的 Shard 上的文档,那么这条文档被称为孤儿文档(Orphaned Document)。在使用产品时,需要特别留意并处理这种情况,以确保数据的完整性和准确性。
MongoDB 4.4 及之后的版本,清理孤儿文档,请参见 cleanupOrphaned
MongoDB 4.4 之前版本,清理孤儿文档,请参见 cleanupOrphaned