面试题答案
一键面试动态映射控制
- 策略:考虑到高并发读写及数据量增长,关闭不必要的动态映射。如果预先知道数据结构,手动定义映射。例如,在日志记录场景中,日志字段相对固定,如时间戳、日志级别、消息等。可提前定义:
{
"mappings": {
"properties": {
"timestamp": {
"type": "date"
},
"log_level": {
"type": "keyword"
},
"message": {
"type": "text"
}
}
}
}
这样做可以避免Elasticsearch在运行时频繁动态创建映射,减少资源开销。动态映射在高并发下可能导致性能问题,因为每次新字段出现都需要重新计算和更新映射结构。
字段数据存储方式
- 针对数字、日期等字段:
- 策略:对于数值型(如商品价格)和日期型(如订单时间)字段,如果需要进行排序、聚合操作,使用
doc_values
。例如:
- 策略:对于数值型(如商品价格)和日期型(如订单时间)字段,如果需要进行排序、聚合操作,使用
{
"mappings": {
"properties": {
"price": {
"type": "double",
"doc_values": true
},
"order_date": {
"type": "date",
"doc_values": true
}
}
}
}
- **依据**:`doc_values`在文档写入时构建,存储在磁盘上,能高效支持排序和聚合操作。在高并发读写场景下,可快速响应这些操作,提升系统整体吞吐量。
- 针对文本字段:
- 策略:如果文本字段仅用于搜索,不用于排序或聚合,可禁用
fielddata
。例如,对于文章内容字段:
- 策略:如果文本字段仅用于搜索,不用于排序或聚合,可禁用
{
"mappings": {
"properties": {
"article_content": {
"type": "text",
"fielddata": false
}
}
}
}
- **依据**:`fielddata`加载到内存中,在高并发场景下可能导致内存不足问题,禁用它可避免此风险,保证系统稳定性。
副本策略
- 策略:根据读写比例和集群资源来调整副本数量。例如,读操作远多于写操作的场景,可适当增加副本数量。假设集群有3个节点,可设置每个主分片有2个副本:
PUT /your_index/_settings
{
"number_of_replicas": 2
}
- 依据:增加副本可以将读请求分散到多个副本分片上,提高读性能。但副本过多会增加写操作的负担,因为每次写操作都需要同步到所有副本。所以要在读写性能之间找到平衡,同时考虑集群的硬件资源,避免因副本过多导致节点负载过高。
其他性能调优策略
- 索引设置:适当调整
refresh_interval
,在高并发写场景下,可适当增大此值,如从默认的1秒改为5秒:
PUT /your_index/_settings
{
"refresh_interval": "5s"
}
这样可以减少刷新频率,提高写性能。但会增加数据可见延迟,需根据业务场景权衡。
- 路由策略:如果数据有特定的分布特点,如按地域或用户ID分布,可利用自定义路由将相关数据写入同一分片,减少跨分片操作,提高读写性能。例如,按用户ID路由:
// Java客户端示例
IndexRequest indexRequest = new IndexRequest("your_index")
.source(jsonBuilder)
.routing(userId);