Elasticsearch集群架构设计
Elasticsearch是基于Lucene构建的分布式搜索引擎,支持全文检索、结构化查询、聚合分析和地理位置搜索。在日志分析、全文检索和数据分析场景中,Elasticsearch凭借倒排索引结构和分布式分片机制提供毫秒级的查询响应。集群由多个节点组成,按角色分为Master节点(集群管理)、Data节点(数据存储和查询)、Coordinating节点(查询协调)和Ingest节点(数据预处理)。
数据按Index(索引)组织,每个Index可配置多个Shard(分片)实现水平拆分。分片分为主分片和副本分片:主分片承载原始数据,副本分片是主分片的拷贝,提供高可用和读负载均衡。当集群中某个Data节点故障时,该节点上的主分片由对应副本分片提升为主分片,副本分片数量不足时集群进入yellow状态告警。
分片数量的规划需要根据数据量和节点数确定。单个分片建议不超过50GB,分片数过多增加集群元数据管理开销,分片数过少限制水平扩展能力。对于预期增长的数据集,初始分片数按未来一年的数据量规划,避免频繁reindex操作。
Elasticsearch集群部署配置
三节点集群部署示例,每个节点承担Master和Data角色(生产环境建议Master和Data分离):
# elasticsearch.yml (node-1)
cluster.name: yunthe-es-cluster
node.name: node-1
node.roles: [master, data, ingest]
# 集群发现配置
discovery.seed_hosts: ["192.168.10.11", "192.168.10.12", "192.168.10.13"]
cluster.initial_master_nodes: ["node-1", "node-2", "node-3"]
# 网络配置
network.host: 0.0.0.0
http.port: 9200
transport.port: 9300
# 内存配置
bootstrap.memory_lock: true
# 路径配置
path.data: /data/elasticsearch
path.logs: /var/log/elasticsearch
# 跨域配置(供Kibana和DevTools使用)
http.cors.enabled: true
http.cors.allow-origin: "https://kibana.yunthe.com"
JVM堆内存配置对ES性能影响显著。config/jvm.options中设置-Xms和-Xmx相等避免堆动态调整开销,堆内存不超过物理内存的50%,剩余内存留给操作系统文件系统缓存(Page Cache)用于Lucene段文件缓存:
# jvm.options
-Xms16g
-Xmx16g
# 系统参数配置
# /etc/security/limits.conf
elasticsearch soft nofile 65536
elasticsearch hard nofile 65536
elasticsearch soft memlock unlimited
elasticsearch hard memlock unlimited
# /etc/sysctl.conf
vm.max_map_count=262144
# 生效: sysctl -p
bootstrap.memory_lock: true配合memlock unlimited锁定堆内存,防止被swap到磁盘导致性能急剧下降。vm.max_map_count设置进程最大映射内存区域数,Lucene需要大量mmap操作,默认值65530不够。
索引分片与副本配置
创建索引时指定分片数和副本数,配合Mapping定义字段类型和分词器:
PUT /articles_index
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1,
"refresh_interval": "30s",
"analysis": {
"analyzer": {
"ik_smart_analyzer": {
"type": "custom",
"tokenizer": "ik_smart"
},
"ik_max_word_analyzer": {
"type": "custom",
"tokenizer": "ik_max_word"
}
}
}
},
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "ik_max_word_analyzer",
"search_analyzer": "ik_smart_analyzer",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"content": {
"type": "text",
"analyzer": "ik_max_word_analyzer",
"search_analyzer": "ik_smart_analyzer"
},
"author": {
"type": "keyword"
},
"publish_date": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss"
},
"category": {
"type": "keyword"
},
"view_count": {
"type": "integer"
},
"tags": {
"type": "keyword"
}
}
}
}
索引级别配置说明:number_of_shards设置为3,按文档ID hash分配到3个主分片;number_of_replicas设置为1,每个主分片有1个副本,集群最少需要2个Data节点才能分配完整副本;refresh_interval设置为30秒(默认1秒),降低索引刷新频率提升写入吞吐量,代价是写入后30秒内不可被搜索。
Mapping设计要点:title和content字段使用text类型支持全文检索,同时配置ik_max_word作为索引分词器(最大粒度分词提高召回率),ik_smart作为搜索分词器(智能分词提高精确度)。title.keyword子字段用于精确匹配、排序和聚合。author、category、tags使用keyword类型,不分词、全值匹配。publish_date使用date类型支持范围查询。
IK中文分词器安装与配置
Elasticsearch默认的标准分词器对中文按单字切分,无法识别中文词语边界。IK Analyzer是Elasticsearch最常用的中文分词插件,支持细粒度分词(ik_max_word)和智能分词(ik_smart)两种模式。安装IK分词器需要在每个节点上执行:
# 在每个ES节点上安装IK分词器(版本需与ES版本匹配)
./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v8.11.0/elasticsearch-analysis-ik-8.11.0.zip
# 安装后重启节点
systemctl restart elasticsearch
# 验证分词效果
POST /_analyze
{
"analyzer": "ik_smart",
"text": "Elasticsearch集群部署与中文全文检索配置"
}
# 返回分词结果:
# ["Elasticsearch", "集群", "部署", "与", "中文", "全文", "检索", "配置"]
POST /_analyze
{
"analyzer": "ik_max_word",
"text": "Elasticsearch集群部署与中文全文检索配置"
}
# 返回分词结果:
# ["Elasticsearch", "集群", "部署", "与", "中文", "全文检索", "全文", "检索", "配置"]
ik_max_word做最细粒度切分,适合索引阶段使用,召回率高;ik_smart做粗粒度切分,适合搜索阶段使用,精确度高。对于专业领域词汇,IK支持自定义词典扩展。在config/analysis-ik/目录下创建custom.dic文件并配置到IKAnalyzer.cfg.xml:
IK Analyzer 扩展配置
custom.dic
https://config.yunthe.com/ik/dict.txt
stopword.dic
机器学习
深度学习
大语言模型
向量数据库
检索增强生成
微服务架构
的
了
和
是
在
remote_ext_dict支持远程词典热更新,修改远程词典文件后IK分词器定期拉取新词典,无需重启ES集群。热更新间隔由remote_ext_dict的Last-Modified或ETag响应头变化触发。
全文检索查询与高亮显示
Elasticsearch提供Query DSL进行复杂查询。以下实现多字段检索、结果高亮和聚合统计:
POST /articles_index/_search
{
"query": {
"bool": {
"must": [
{
"multi_match": {
"query": "Elasticsearch集群配置",
"fields": ["title^3", "content^1"],
"type": "best_fields",
"operator": "and"
}
}
],
"filter": [
{
"range": {
"publish_date": {
"gte": "2026-01-01",
"lte": "2026-12-31"
}
}
},
{
"term": {
"category": "数据库"
}
}
]
}
},
"highlight": {
"pre_tags": [""],
"post_tags": [""],
"fields": {
"title": { "number_of_fragments": 0 },
"content": {
"fragment_size": 150,
"number_of_fragments": 3,
"no_match_size": 150
}
}
},
"aggs": {
"category_stats": {
"terms": {
"field": "category",
"size": 10
},
"aggs": {
"avg_views": {
"avg": { "field": "view_count" }
}
}
}
},
"sort": [
{ "_score": { "order": "desc" } },
{ "publish_date": { "order": "desc" } }
],
"from": 0,
"size": 20
}
multi_match的best_fields类型在多字段中搜索同一查询词,取最高分字段的得分作为文档得分。title^3将标题匹配权重提升3倍,使标题包含关键词的文档排序靠前。filter子句不参与评分,用于精确过滤条件,结果会被缓存提升查询性能。highlight对匹配关键词的文本片段用pre_tags和post_tags包裹,前端渲染时显示高亮。aggs按category做聚合统计并计算各分类的平均浏览量,实现搜索结果页面的分类筛选功能。
索引文档时使用bulk API批量写入提升吞吐量,单次bulk请求建议5-15MB大小。写入完成后使用_force_merge合并段文件减少查询时的段扫描数量,但该操作消耗大量I/O,建议在低峰期执行。集群监控通过GET /_cluster/health查看集群状态,GET /_cat/indices?v查看各索引的文档数、大小和分片分布。当集群状态为red表示有主分片未分配,yellow表示有副本分片未分配,需要检查节点磁盘空间和JVM堆使用率。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/elasticsearch-ji-qun-bu-shu-yu-suo-yin-fen-pian-fu-ben-pei/