面试题答案
一键面试副本集配置
- 节点数量
- 三节点副本集:推荐使用三节点副本集,一个主节点(Primary)和两个从节点(Secondary)。主节点负责处理所有的写操作和大部分读操作(默认情况下)。从节点会复制主节点的数据,当主节点出现故障时,其中一个从节点会通过选举成为新的主节点,保证系统的可用性。三节点副本集能在保证高可用的同时,相对简单且成本较低。
- 多节点副本集:如果系统对读性能要求极高,可以考虑增加从节点数量。但从节点过多可能会导致复制延迟增加,因为主节点需要向多个从节点同步数据。一般建议从节点数量不超过5个,这样既可以分散读压力,又能较好地控制复制延迟。
- 节点角色分配
- 仲裁节点:在某些情况下,可以引入仲裁节点(Arbiter)。仲裁节点不存储数据,仅参与选举过程,用于决定哪个从节点晋升为主节点。例如,在一个双节点副本集(一个主节点和一个从节点)中添加一个仲裁节点,形成三节点结构,这样可以在主节点故障时确保快速选举出新的主节点,提升系统稳定性。仲裁节点可以部署在性能较低的机器上,以节省资源。
- 副本集同步机制优化
- 优先节点配置:可以根据节点的硬件性能和网络状况,将性能较好的从节点配置为优先节点(Priority > 1)。这样在选举时,优先节点更有可能成为新的主节点,保证系统在故障切换后的性能。例如,在一个包含高性能服务器和普通服务器的副本集中,将高性能服务器的从节点设置为优先节点。
- 延迟节点设置:对于一些对数据实时性要求不高,但希望保留历史数据副本的场景,可以设置延迟节点(Hidden 和 Delayed 节点)。延迟节点会落后主节点一定时间(如1小时或1天)复制数据,可用于数据恢复、灾难恢复等场景,同时不会对主从复制造成额外压力。
分片机制配置
- 分片键选择
- 避免热点分片键:
- 不要使用单调递增字段:例如时间戳或自增ID作为分片键,如果使用这类字段,新的数据会集中写入到一个分片,导致该分片成为热点。比如使用
created_at
字段作为分片键,新产生的数据都会落到同一个分片上。
- 不要使用单调递增字段:例如时间戳或自增ID作为分片键,如果使用这类字段,新的数据会集中写入到一个分片,导致该分片成为热点。比如使用
- 选择离散性好的字段:
- 哈希分片键:可以使用哈希函数对某个字段进行处理后作为分片键,如对用户ID进行哈希运算。这样数据会均匀分布在各个分片上,有效避免热点。例如,使用
hash(user_id)
作为分片键,不同用户的数据会被分散到不同分片。 - 复合分片键:当单一字段无法很好地分散数据时,可以使用复合分片键。例如,对于电商订单数据,可以使用
{user_id: 1, order_date: -1}
作为复合分片键,既考虑了用户维度的分散,又兼顾了时间维度的分布,使得数据在不同用户和不同时间段上都能均匀分布,减少热点分片的产生。
- 哈希分片键:可以使用哈希函数对某个字段进行处理后作为分片键,如对用户ID进行哈希运算。这样数据会均匀分布在各个分片上,有效避免热点。例如,使用
- 避免热点分片键:
- 分片数量
- 初始分片数量:根据数据量和预期的增长情况确定初始分片数量。如果数据量较小且增长缓慢,可以先设置较少的分片,如3到5个分片。随着数据量的增长,再动态增加分片。例如,预估未来一年内数据量会增长到100GB,根据每个分片可承载的数据量(如每个分片可承载20GB数据),初始设置5个分片。
- 动态调整分片:MongoDB支持动态添加和删除分片。当发现某个分片负载过高时,可以将其数据迁移到新的分片上,或者对现有分片进行拆分。例如,通过
sh.splitAt
命令对某个分片进行拆分,以进一步均衡负载。
- 分片集群架构
- mongos路由器:部署多个mongos路由器,以实现客户端请求的负载均衡。mongos不存储数据,它负责接收客户端请求,根据分片键将请求路由到对应的分片上。多个mongos可以避免单点故障,同时提高系统的并发处理能力。例如,可以在不同的服务器上部署3到5个mongos实例,并通过负载均衡器(如Nginx)将客户端请求均匀分配到各个mongos上。
- config服务器:配置服务器(config server)存储着分片集群的元数据,包括分片信息、块范围等。建议使用三节点的config服务器副本集,以保证元数据的高可用性。config服务器对性能要求相对较低,但可靠性至关重要,因为它的数据准确性直接影响到整个分片集群的正常运行。