面试题答案
一键面试业务场景:物联网设备数据实时采集存储场景
假设我们有大量的物联网设备,每个设备按固定频率(如每秒)发送传感器数据,包括设备ID、时间戳、温度、湿度等信息。数据需要实时采集并存储,以便后续分析和监控。
基于MongoDB升序片键的数据分发方案
- 选择片键:考虑使用时间戳作为升序片键。物联网数据通常具有时间序列特性,按时间顺序存储便于查询特定时间段内的数据。例如,使用ISO 8601格式的时间戳作为片键字段。
- 数据分发逻辑:当数据写入MongoDB集群时,MongoDB根据时间戳片键值将数据分发到不同的分片。较新的数据(时间戳较大)会被分配到新的分片或者现有分片的末尾区域。
根据业务特点调整片键设置
- 粒度调整:如果数据量非常大且写入频率极高,可考虑在时间戳基础上增加设备ID作为复合片键。例如,
{timestamp: 1, deviceID: 1}
,这样可以进一步分散数据,避免单个设备的数据集中在一个分片上。 - 片键范围:根据数据采集的频率和预计的时间跨度,合理设置片键的范围。如果数据采集跨度长,可以按天、周等时间单位划分片键范围,以便更好地管理和迁移数据。
集群配置
- 分片数量:根据预估的数据量和读写负载确定分片数量。例如,如果预计每秒有1000个设备发送数据,每个数据记录大小为1KB,每天产生的数据量约为86400 * 1000 * 1KB ≈ 86GB。根据硬件资源和性能需求,可初步设置5 - 10个分片。
- 副本集:为每个分片设置副本集,以提供数据冗余和高可用性。建议设置3个副本成员,一个主节点和两个从节点。这样在主节点故障时,从节点可以自动提升为主节点,保证数据的持续写入和读取。
应对数据倾斜
- 可行性:使用时间戳作为升序片键在一定程度上可以缓解数据倾斜。因为新数据会均匀地分布到各个分片的末尾。但如果某些设备发送数据频率异常高,仍可能导致数据倾斜。
- 优化措施:
- 复合片键:如前文所述,使用复合片键(时间戳 + 设备ID)可以更均匀地分布数据。
- 动态分片调整:MongoDB支持动态调整分片,当发现某个分片数据量过大时,可以手动或自动进行数据迁移,将部分数据迁移到其他分片。
应对高并发读写
- 可行性:MongoDB的分布式架构在设计上支持高并发读写。通过合理的分片和副本集配置,可以分散读写负载。
- 优化措施:
- 读操作:利用副本集的从节点进行读操作,通过设置读偏好(read preference)为secondaryPreferred,将大部分读请求发送到从节点,减轻主节点压力。
- 写操作:使用批量写入(bulk write)操作,减少网络开销。同时,合理设置写入关注点(write concern),在保证数据一致性的前提下,提高写入性能。例如,对于实时性要求高但一致性要求相对较低的场景,可以使用
{w: 1}
的写入关注点,即只等待主节点确认写入成功。