面试题答案
一键面试索引结构设计
- 字段类型选择:
- 对于商品名称字段,使用
text
类型。例如,在映射定义中:
{ "mappings": { "properties": { "product_name": { "type": "text", "analyzer": "my_custom_analyzer" } } } }
- 对于商品名称字段,使用
- 自定义分析器:
- 处理拼写错误:使用
edgengram
分词器来创建前缀和后缀的子词。例如:
{ "settings": { "analysis": { "analyzer": { "my_custom_analyzer": { "tokenizer": "my_custom_tokenizer", "filter": ["lowercase"] } }, "tokenizer": { "my_custom_tokenizer": { "type": "edge_ngram", "min_gram": 2, "max_gram": 10 } } } } }
- 处理同义词:创建同义词文件(如
synonyms.txt
),内容格式为手机,移动电话
,并在分析器中添加同义词过滤器:
{ "settings": { "analysis": { "analyzer": { "my_custom_analyzer": { "tokenizer": "my_custom_tokenizer", "filter": ["lowercase", "my_synonym_filter"] } }, "tokenizer": { "my_custom_tokenizer": { "type": "edge_ngram", "min_gram": 2, "max_gram": 10 } }, "filter": { "my_synonym_filter": { "type": "synonym", "synonyms_path": "synonyms.txt" } } } } }
- 处理多语言:可以使用
icu_analyzer
,它对多种语言有较好的支持。例如:
{ "settings": { "analysis": { "analyzer": { "my_custom_analyzer": { "type": "icu_analyzer", "filter": ["my_synonym_filter"] } }, "filter": { "my_synonym_filter": { "type": "synonym", "synonyms_path": "synonyms.txt" } } } } }
- 处理拼写错误:使用
查询流程
- 用户输入处理:接收用户输入的商品名称,传递给ElasticSearch查询接口。
- 查询构建:
- 使用
match
查询,并设置fuzziness
参数来处理拼写错误。例如,在Java代码中:
SearchRequest searchRequest = new SearchRequest("products_index"); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("product_name", userInput) .fuzziness(Fuzziness.AUTO); searchSourceBuilder.query(matchQueryBuilder); searchRequest.source(searchSourceBuilder);
- 由于分析器在索引和查询时都会应用同义词,所以同义词处理是自动的。对于多语言,由于
icu_analyzer
的使用,也能较好地处理混合搜索情况。
- 使用
- 结果返回:ElasticSearch执行查询后,将匹配的商品信息返回给应用层展示给用户。
配置和代码实现
- 配置:
- 在ElasticSearch的
config/elasticsearch.yml
文件中,可以设置集群相关配置,如节点数量、分片和副本数等,以适应高并发。例如:
cluster.name: my_ecommerce_cluster node.name: node - 1 network.host: 0.0.0.0 http.port: 9200 discovery.seed_hosts: ["node - 1", "node - 2"] cluster.initial_master_nodes: ["node - 1", "node - 2"] index.number_of_shards: 3 index.number_of_replicas: 2
- 在ElasticSearch的
- 代码实现:以Java为例,使用Elasticsearch Java High - Level REST Client。
- 引入依赖:
<dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch - rest - high - level - client</artifactId> <version>7.10.2</version> </dependency>
- 构建客户端并执行查询:
RestHighLevelClient client = new RestHighLevelClient( RestClient.builder( new HttpHost("localhost", 9200, "http"))); // 构建查询如上述查询构建部分 SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); client.close();
高并发扩展性和稳定性保障
- 扩展性:
- 水平扩展:通过增加ElasticSearch节点来提高集群的处理能力。可以根据业务增长情况,逐步添加节点到集群中,ElasticSearch会自动重新分配分片,平衡负载。例如,在云环境中,可以轻松地启动新的EC2实例作为ElasticSearch节点。
- 索引分片:合理设置索引的分片数,在高并发情况下,每个分片可以并行处理查询请求,提高整体查询性能。如上述配置中设置
index.number_of_shards: 3
,可以根据数据量和并发量调整该值。
- 稳定性:
- 副本机制:设置索引的副本数,如
index.number_of_replicas: 2
,当某个节点出现故障时,副本分片可以接替故障节点的工作,保证数据的可用性和查询的正常执行。 - 监控和预警:使用Elasticsearch的监控工具(如Elasticsearch Monitoring),实时监控集群的健康状态、节点负载、索引性能等指标。设置预警规则,当指标超出阈值时及时通知运维人员进行处理,避免出现严重故障影响业务。
- 负载均衡:在应用层和ElasticSearch集群之间部署负载均衡器(如Nginx),将高并发的查询请求均匀分配到各个ElasticSearch节点上,防止单个节点过载。
- 副本机制:设置索引的副本数,如