面试题答案
一键面试底层存储结构设计
- 索引设计
- 字段映射:对不同类型的数据使用合适的数据类型进行映射。例如,对于日期类型使用
date
类型,避免使用字符串存储日期,以提高查询效率。对于不需要进行全文搜索的字段,设置index: false
,减少索引空间占用。 - 分片策略:根据数据量和预计的增长情况合理分配分片数量。对于读多写少的场景,可以适当增加副本数量以提高读性能;对于写多读少的场景,重点考虑如何优化写入性能,避免过多副本带来的写性能损耗。例如,如果数据量预计在未来一年内增长到 10TB,按照每个分片 30GB 的推荐大小,可以初始设置 350 个左右的分片。
- 索引模板:定义索引模板,确保新建的索引遵循统一的结构规范,包括字段映射、分片和副本设置等,便于管理和维护。
- 字段映射:对不同类型的数据使用合适的数据类型进行映射。例如,对于日期类型使用
- 存储优化
- 磁盘选择:使用高速固态硬盘(SSD),相比传统机械硬盘,SSD 具有更快的读写速度,能够显著提升 ElasticSearch 的 I/O 性能,尤其在高并发写入场景下效果明显。
- 存储布局:将不同索引的数据分布在多个磁盘上,避免单个磁盘 I/O 瓶颈。例如,可以按照业务模块或数据类型将索引分别存储在不同的磁盘分区。
网络拓扑优化
- 集群架构
- 节点类型分离:将 ElasticSearch 集群中的节点按照功能进行分离,分为 Master 节点、Data 节点和 Coordinating 节点。Master 节点专注于集群的管理和元数据的维护,Data 节点负责数据的存储和读写,Coordinating 节点处理客户端请求的分发和结果的合并。这样的分离可以避免单个节点承担过多功能导致性能瓶颈。
- 节点间网络配置:确保节点之间使用高速、低延迟的网络连接,如 10Gbps 或更高带宽的网络。优化网络拓扑,减少网络跳数,降低网络延迟。
- 负载均衡
- 内部负载均衡:在 ElasticSearch 集群内部,使用 ElasticSearch 自身的负载均衡机制,通过配置合适的路由算法,将请求均匀分配到各个节点。例如,使用基于哈希的路由算法,确保数据在各个分片之间均匀分布。
- 外部负载均衡:在客户端和 ElasticSearch 集群之间部署负载均衡器,如 Nginx 或 HAProxy。负载均衡器可以根据节点的负载情况动态分配请求,提高集群的整体可用性和性能。可以设置基于权重的负载均衡策略,根据节点的硬件配置和性能表现分配不同的权重。
上层应用的读写策略调整
- 写入策略
- 批量写入:尽量使用 Bulk API 进行批量写入操作,减少单个请求的数量,降低网络开销。根据网络带宽和节点性能,合理调整批量写入的数据量大小。例如,在网络带宽充足且节点性能较好的情况下,可以每次批量写入 1000 - 5000 条数据。
- 异步写入:在应用层采用异步写入方式,将写入操作放入队列中,由专门的线程或进程进行批量处理后再写入 ElasticSearch。这样可以避免写入操作阻塞应用的其他业务逻辑,提高应用的响应速度。
- 写入时机优化:避免在业务高峰期进行大量的写入操作,可以选择在业务低谷期或者系统负载较低的时候执行批量写入任务。
- 读取策略
- 缓存策略:在应用层设置缓存,对于频繁读取的数据,先从缓存中获取。可以使用 Redis 等分布式缓存,将热门数据缓存起来,减少对 ElasticSearch 的读取压力。例如,对于首页展示的热门数据,设置 5 分钟的缓存时间。
- 聚合查询优化:对于复杂的聚合查询,尽量提前计算并存储聚合结果。例如,对于每日的统计数据,可以在每天凌晨计算并存储,查询时直接返回预计算结果,而不是实时进行复杂的聚合操作。
- 分页查询优化:对于分页查询,避免使用
from + size
的方式进行深度分页,因为这种方式随着from
值的增大性能会急剧下降。可以使用scroll
API 进行滚动查询,适用于需要处理大量数据分页的场景;或者使用search_after
方式,基于上一次查询结果进行下一页的查询,提高分页查询性能。