分布式实时搜索和分析引擎——Elasticsearch
liuian 2025-07-08 20:08 3 浏览
一、概述
Elasticsearch是一个基于Lucene的搜索引擎。它提供了具有HTTP Web界面和无架构JSON文档的分布式,多租户能力的全文搜索引擎。Elasticsearch是用Java开发的,根据Apache许可条款作为开源发布。
二、节点类型&作用
1)master节点(主节点)
配置
node.master:true
node.data:false(这里也可以配置成node.data:true)
【注意】node.master和node.data默认都是true, 但还是建议显式配置
作用
- 索引的创建或删除
- 跟踪哪些节点是集群的一部分
- 决定哪些分片分配给相关的节点
2)data节点(数据节点)
配置
node.master:false(这里也可以配置成node.master:true)
node.data:true
作用
- 存储索引数据
- 对文档进行增删改查,聚合操作
3)Coordinating节点(协调节点/Client节点)
每一个节点都隐式的是一个协调节点,Coordinating节点是负责接收任何 Client 的请求,包括 REST Client 等。该节点将请求分发到合适的节点,最终把结果汇集到一起。一般来说,每个节点默认起到了 Coordinating节点 的职责。
配置
node.master:false
node.data:false
作用
- 处理路由请求
- 处理搜索
- 分发索引
4)Ingest节点(预处理节点)
在索引数据之前可以先对数据做预处理操作,所有节点其实默认都是支持 Ingest 操作的,也可以专门将某个节点配置为 Ingest 节点。
配置
node.ingest:true
作用
- Ingest节点和集群中的其他节点一样,但是它能够创建多个处理器管道,用以修改传入文档。类似 最常用的Logstash过滤器已被实现为处理器。
- Ingest节点 可用于执行常见的数据转换和丰富。 处理器配置为形成管道。 在写入时,Ingest Node有20个内置处理器,例如grok,date,gsub,小写/大写,删除和重命名
- 在批量请求或索引操作之前,Ingest节点拦截请求,并对文档进行处理。
三、Elasticsearch 是如何实现 master 选举的
前提条件
- 只有候选主节点(master:true)的节点才能成为主节点。
- 最小主节点数(min_master_nodes)的目的是防止脑裂。
实现步骤
- 第一步:确认候选主节点数达标,elasticsearch.yml 设置的值discovery.zen.minimum_master_nodes;
- 第二步:对所有候选主节点根据nodeId字典排序,每次选举每个节点都把自己所知道节点排一次序,然后选出第一个(第0位)节点,暂且认为它是master节点。
- 第三步:如果对某个节点的投票数达到一定的值(候选主节点数n/2+1)并且该节点自己也选举自己,那这个节点就是master。否则重新选举一直到满足上述条件。
【补充】master 节点的职责主要包括集群、节点和索引的管理,不负责文档级别的管理;data 节点可以关闭 http 功能。
四、如何解决ES集群的脑裂问题
【原因】
所谓集群脑裂,是指 Elasticsearch 集群中的节点(比如共 20 个),其中的 10 个选了一个 master,另外 10 个选了另一个 master 的情况。
【解决】
当集群 master 候选数量不小于 3 个时,可以通过设置最少投票通过数量(discovery.zen.minimum_master_nodes)超过所有候选节点一半以上来解决脑裂问题;
五、调优
1)部署时,对 Linux 的设置优化方法
- 关闭缓存 swap;
- 堆内存设置为:Min(节.点内存/2,理想是 32GB);
- 设置最大文件句柄数;
- 线程池+队列大小根据业务需要做调整;
- 磁盘存储 raid 方式——存储有条件使用 RAID10,增加单节点性能以及避免单节点存储故障。
2)写入调优
- 写入前副本数设置为 0;
- 写入前关闭 refresh_interval 设置为-1,禁用刷新机制;
- 写入过程中:采取 bulk 批量写入;
- 写入后恢复副本数和刷新间隔;
- 尽量使用自动生成的 id。
3)查询调优
- 禁用 wildcard(wildcard 检索可以定义为:支持通配符的模糊检索。类似于mysql的like);
- 禁用批量 terms(成百上千的场景);
- 充分利用倒排索引机制,能 keyword 类型尽量 keyword;
- 据量大时候,可以先基于时间敲定索引再检索;
- 设置合理的路由机制。
六、Elasticsearch 索引文档的过程
这里的索引文档应该理解为文档写入 ES,创建索引的过程。
文档写入包含:单文档写入和批量 bulk 写入,这里只解释一下:单文档写入流程。
- 第一步:客户写集群某节点写入数据,发送请求。(如果没有指定路由/协调节点,请求的节点扮演路由节点的角色。)
- 第二步:节点 1 接受到请求后,使用文档_id 来确定文档属于分片 0。请求会被转到另外的节点,假定节点 3。因此分片 0 的主分片分配到节点 3 上。
- 第三步:节点 3 在主分片上执行写操作,如果成功,则将请求并行转发到节点 1和节点 2 的副本分片上,等待结果返回。所有的副本分片都报告成功,节点 3 将向协调节点(节点 1)报告成功,节点 1 向请求客户端报告写入成功。
七、索引模板
索引模板,简而言之,是一种复用机制,就像一些项目的开发框架如 Laravel 一样,省去了大量的重复,体力劳动。当新建一个 Elasticsearch 索引时,自动匹配模板,完成索引的基础部分搭建。
典型的如下所示:
{
"order": 0,
"template": "sample_info*",
"settings": {
"index": {
"number_of_shards": "64",
"number_of_replicas": "1"
}
},
"mappings": {
"info": {
"dynamic_templates": [
{
"string_fields": {
"mapping": {
"analyzer": "only_words_analyzer",
"index": "analyzed",
"type": "string",
"fields": {
"raw": {
"ignore_above": 512,
"index": "not_analyzed",
"type": "string"
}
}
},
"match_mapping_type": "string",
"match": "*"
}
}
],
"properties": {
"user_province": {
"analyzer": "lowercase_analyzer",
"index": "analyzed",
"type": "string",
"fields": {
"raw": {
"ignore_above": 512,
"index": "not_analyzed",
"type": "string"
}
}
}
}
}
},
"aliases": {}
}
上述模板定义,看似复杂,拆分来看,主要为如下几个部分:
{
"order": 0, // 模板优先级
"template": "sample_info*", // 模板匹配的名称方式
"settings": {...}, // 索引设置
"mappings": {...}, // 索引中各字段的映射定义
"aliases": {...} // 索引的别名
}
1)模板优先级
一个模板可能绝大部分符合新建索引的需求,但是局部需要微调,此时,如果复制旧的模板,修改该模板后,成为一个新的索引模板即可达到我们的需求,但是这操作略显重复。此时,可以采用模板叠加与覆盖来操作。模板的优先级是通过模板中的 order 字段定义的,数字越大,优先级越高。
如下为定义所有以 te 开头的索引的模板:
{
"order": 0
"template" : "te*",
"settings" : {
"number_of_shards" : 1
},
"mappings" : {
"type1" : {
"_source" : { "enabled" : false }
}
}
}
索引模板是有序合并的。如何想单独修改某一小类索引的一两处单独设置,可以在累加一层模板:
{
"order" : 1,
"template" : "tete*",
"settings" : {
"number_of_shards" : 2
},
"mappings" : {
"type1" : {
"_all" : { "enabled" : false }
}
}
}
上述第一个模板的 order 为0,第二个模板的 order 为1,优先级高于第一个模板,其会覆盖第一个模板中的相同项。所以对于所有以 tete 开头的索引模板效果如下:
{
"settings" : {
"number_of_shards" : 2
},
"mappings" : {
"type1" : {
"_source" : { "enabled" : false },
"_all" : { "enabled" : false }
}
}
}
两个模板叠加了,项目的字段,优先级高的覆盖了优先级低的,如分片数。
2)索引模板的匹配
索引模板中的 "template" 字段定义的是该索引模板所应用的索引情况。如 "template": "tete*" 所表示的含义是,当新建索引时,所有以 tete 开头的索引都会自动匹配到该索引模板。利用该模板进行相应的设置和字段添加等。
3)setting 部分
索引模板中的 setting 部分一般定义的是索引的主分片、拷贝分片、刷新时间、自定义分析器等。常见的 setting 部分结构如下:
"settings": {
"index": {
"analysis": {...}, // 自定义的分析器
"number_of_shards": "32", // 主分片的个数
"number_of_replicas": "1", // 主分片的拷贝分片个数
"refresh_interval": "5s" // 刷新时间
}
}
八、冷热数据分离
ES集群的索引写入及查询速度主要依赖于磁盘的IO速度,冷热数据分离的关键为使用SSD磁盘存储数据。若全部使用SSD,成本过高,且存放冷数据较为浪费,因而使用普通SATA磁盘与SSD磁盘混搭,可做到资源充分利用,性能大幅提升的目标。为了解决控制成本的前提下读写性能问题,Elasticsearch冷热分离架构应运而生。
- 冷数据索引:查询频率低,基本无写入,一般为当天或最近2天以前的数据索引
- 热数据索引:查询频率高,写入压力大,一般为当天数据索引
1)实现原理
- Hot节点设置:索引节点(写节点),同时保持近期频繁使用的索引。 属于IO和CPU密集型操作,建议使用SSD的磁盘类型,保持良好的写性能;节点的数量设置一般是大于等于3个。将节点设置为hot类型:
node.attr.box_type: hot
- Warm节点设置: 用于不经常访问的read-only索引。由于不经常访问,一般使用普通的磁盘即可。内存、CPU的配置跟Hot节点保持一致即可;节点数量一般也是大于等于3个。将节点设置为warm类型:
node.attr.box_type: warm
es1:master节点
# elasticsearch.yml
node.name: "master"
cluster.name: "test-cluster"
network.host: 0.0.0.0
node.master: true
node.data: false
es2、es3、es4 热数据节点
# elasticsearch.yml
node.name: "hot-datanode-00x" # 提示:自行修改其他节点的名称
cluster.name: "test-cluster"
network.host: 0.0.0.0
node.master: false
node.data: true
discovery.zen.ping.unicast.hosts: ["master"]
node.attr.box_type: "hot" # 标识为热数据节点
es5、es6 冷/温数据节点
# elasticsearch.yml
node.name: "cold-datanode-00x" # 提示:自行修改其他节点的名称cluster.name: "docker-cluster" network.host: 0.0.0.0 node.master: false node.data: true discovery.zen.ping.unicast.hosts: ["master"] node.attr.box_type: "warm" # 标识为温数据节点
九、分片不均衡原因&解决方案
原因
可能存在的部分原因有以下几种:
- Shard设置不合理。
说明:大多数负载不均问题是由于shard设置不合理导致,建议优先排查。
- Segment大小不均。
- 存在典型的冷热数据需求场景。
说明:例如查询中添加了routing或查询频率较高的热点数据,则必然导致数据出现负载不均。
- 没有释放长连接,导致流量不均。
说明:该问题时常暴露于采用负载均衡及多可用区架构部署时。
解决方案
1)方案一:手动移动分片
例如移动node-1的分片0到node-4
curl -XPOST 'http://localhost:9200/_cluster/reroute' -d '{
"commands":[{
"move":{
"index":"indexName",
"shard":0,
"from_node":"node-1",
"to_node":"node-4"
}}]}'
- 优点:操作简单,恢复时间短;不必修改master node的配置,master node长期负载后高
- 缺点:索引大,移动时有很高的IO,索引容易损坏,需要做备份,不能解决master node既是数据节点又是负载均衡转发器的问题
【注意】分片和副本无法移动到同一个节点
2)方案二:重建索引,从另外一个集群导入
删除原来的索引,重新建立索引,;利用elasticsearch dump等工具从另一个集群中把数据导入到新的索引中
- 优点:可以重新配置master node和data node,主从负载均匀
- 缺点:费时间,容易数据丢失,需要验证数据的一致性
3)方案三:配置平衡参数
使用下面的命令恢复平衡
PUT_cluster/settings
{
"persistent": {
"cluster.routing.rebalance.enable": "all"
}
}
十、解决Elasticsearch分片未分配的问题
原因整体概述:
- 出现这个问题的原因是原有分片未正常关闭和清理,所以当分片要重新分配回出问题节点的时候没有办法获得分片锁。
- 这不会造成分片数据丢失,只需要重新触发一下分配。
unassigned 分片问题可能的原因如下:
- INDEX_CREATED: 由于创建索引的API导致未分配。
- CLUSTER_RECOVERED: 由于完全集群恢复导致未分配。
- INDEX_REOPENED: 由于打开open或关闭close一个索引导致未分配。
- DANGLING_INDEX_IMPORTED: 由于导入dangling索引的结果导致未分配。
- NEW_INDEX_RESTORED: 由于恢复到新索引导致未分配。
- EXISTING_INDEX_RESTORED: 由于恢复到已关闭的索引导致未分配。
- REPLICA_ADDED: 由于显式添加副本分片导致未分配。
- ALLOCATION_FAILED: 由于分片分配失败导致未分配。
- NODE_LEFT: 由于承载该分片的节点离开集群导致未分配。
- REINITIALIZED: 由于当分片从开始移动到初始化时导致未分配(例如,使用影子shadow副本分片)。
- REROUTE_CANCELLED: 作为显式取消重新路由命令的结果取消分配。
- REALLOCATED_REPLICA: 确定更好的副本位置被标定使用,导致现有的副本分配被取消,出现未分配。
解决方案如下:
执行修复命令
POST /_cluster/reroute?retry_failed
十一、ES读写数据过程
1)ES写入数据的过程
- 客户端发送任何一个请求到任意一个node,这个节点就成为协调节点(coordinate node)
- 协调节点对document(可以手动设置doc id,也可以由系统分配)进行hash路由,将请求转发给对应的node
- node上的primary shard处理请求,然后将数据同步到replica node
- 协调节点如果发现primary shard所在的node和所有的replica shard所对应的node都搞定之后,就会将请求返回给客户端
2)ES读数据过程
可以通过doc id来查询,根据doc id进行hash,判断当时写这个document时是分配到哪个shard上去了,然后就去那个shard上查询。
- 客户端发送任何一个请求到任意一个node,这个节点就成为协调节点(coordinate node)
- 协调节点对doc id进行hash路由,将请求转发到对应的node,此时会使用round-robin随机轮询算法,在primary shard以及所有的replica shard中随机选择一个,让读请求负载均衡
- 接受请求的node,返回document给协调节点
- 协调节点再将数据返回给客户端
十二、在海量数据中提高效率的几个手段
- filesystem cache:ES的搜索引擎严重依赖底层的filesystem cache,如果给filesystem cache更多的内存,尽量让内存可以容纳所有的index segment file索引数据文件
- 数据预热:对于那些你觉得比较热的数据,即经常会有人访问的数据,最好做一个专门的缓存预热子系统,对于热数据,每隔一段时间,系统本身就提前访问一下,让数据进入filesystem cache里面去,这样下次访问的时候,性能会更好一些。
- 冷热分离:冷数据索引:查询频率低,基本无写入,一般为当天或最近2天以前的数据索引,这种数据可以存储在机械硬盘HDD中热数据索引:查询频率高,写入压力大,一般为当天的数据索引,这种数据可以存储在SSD中
- document的模型设计:不要在搜索的时候去执行各种复杂的操作,尽量在document模型设计和数据写入的时候就将复杂操作处理掉
- 分页性能优化:翻页的时候,翻得越深,每个shard返回的数据越多,而且协调节点处理的时间越长,此时,要用scroll,scroll会一次性的生成所有数据的快照,然后每次翻页都是通过移动游标来完成
相关推荐
- Python tkinter学习笔记(七):Notebook和Treeview
-
‘Pythontkinter’是Python自带的GUI工具包,非常适合开发小型的GUI应用。最近使用‘tkinter’开发了一些自己日常使用的小工具,效果不错,于是把开发过程中学习到的一些tkin...
- 如何用 Python实现简单的表格界面
-
Excel有表格编辑功能,为什么我还要弄一个,不是多此一举么。道理是对的,但是很多会员功能才更加强大,不是吗?我们学语言,一来可以练习编码熟练的,巩固知识点,更重要的是你熟悉开发,以后如果你想实现一...
- 土地增值税清算中的施工合同进行判断是否有重复施工的情况
-
对土地增值税清算中的施工合同进行判断是否有重复施工的情况,使用Python中的Pandas库对施工合同的相关数据进行处理,基于文本相似度进行判断。1.读取施工内容数据:将施工内容数据存储在一个...
- 大模型时代必备技能:Embedding与向量数据库开发完全指南
-
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在官网-聚客AI学院大模型应用开发微调项目实践课程学习平台一.Embeddings与向量数据库1.1Embeddings的...
- 分布式实时搜索和分析引擎——Elasticsearch
-
一、概述Elasticsearch是一个基于Lucene的搜索引擎。它提供了具有HTTPWeb界面和无架构JSON文档的分布式,多租户能力的全文搜索引擎。Elasticsearch是用Java开发的...
- elasticsearch v9.0.0重磅发布!解锁最新核心特性与性能飞跃!
-
时隔3年,Elasticsearch迎来重大版本更新!基于Lucene10.1.0构建,9.0.0版本在AI搜索、安全分析、向量计算、集群管理等多个领域实现突破性升级版本亮点o新...
- Java中间件-Elasticsearch(java中间件技术及其应用开发)
-
Elasticsearch是一个非常强大的搜索引擎。它目前被广泛地使用于各个IT公司。Elasticsearch是由Elastic公司创建。它的代码位于GitHub-elastic/...
- 知名互联网公司和程序员都看好的数据库是什么?
-
2017年数据库领域的最大趋势是什么?什么是最热的数据处理技术?学什么数据库最有前途?程序员们普遍不喜欢的数据库是什么?本文都会一一揭秘。大数据时代,数据库的选择备受关注,此前本号就曾揭秘国内知名互联...
- 快速了解Elasticsearch(快速了解词语浑话的读音、释义等知识点)
-
Elasticsearch是一款基于Lucene的开源分布式全文搜索引擎,它支持实时搜索,具有优秀的可扩展性和可靠性。作为一款搜索引擎,Elasticsearch提供了丰富的API,使得开发人员可以通...
- 面试官:Kafka和ES选主有什么区别?
-
Kafka和ES都是用来处理大数据的中间件,一个是消息中间件的代表(Kafka),另一个是大数据搜索引擎的代表(ES)。它们在Java领域的使用非常广泛,在大数据方面就更不用说了,但它们的选...
- ElasticSearch 23 种映射参数详解
-
ElasticSearch系列教程我们前面已经连着发了四篇了,今天第五篇,我们来聊一聊Es中的23种常见的映射参数。针对这23种常见的映射参数,松哥专门录制了一个视频教程:视频链接:...
- 还不会Elasticsearch?看这些知识入门刚刚好
-
作者:MacroZheng链接:https://juejin.im/post/5e8c7d65518825736512d097记得刚接触Elasticsearch的时候,没找啥资料,直接看了遍Ela...
- Elasticsearch学习,请先看这一篇!
-
题记:Elasticsearch研究有一段时间了,现特将Elasticsearch相关核心知识、原理从初学者认知、学习的角度,从以下9个方面进行详细梳理。欢迎讨论……0.带着问题上路——ES是如何产...
- Elasticsearch企业级应用全景图:原理/场景/优化/避坑四重奏
-
一、核心概念与架构原理1.基本定义Elasticsearch是基于ApacheLucene构建的分布式实时搜索与分析引擎,具有以下核心特性:分布式架构:支持PB级数据水平扩展近实时(NRT):数据...
- ELK Stack系列之基础篇(八) - Elasticsearch原理总结(图示)
-
前言通过前面的知识,我们已经了解到了ELk到底是什么、以及他们的工作原理、ES集群架构、专有名词的一些解释。在进入下一阶段ES实操学习环节前,那么今天我将以图解的方式将ELK重点以及ES的相关逻辑进行...
- 一周热门
-
-
Python实现人事自动打卡,再也不会被批评
-
【验证码逆向专栏】vaptcha 手势验证码逆向分析
-
Psutil + Flask + Pyecharts + Bootstrap 开发动态可视化系统监控
-
一个解决支持HTML/CSS/JS网页转PDF(高质量)的终极解决方案
-
再见Swagger UI 国人开源了一款超好用的 API 文档生成框架,真香
-
网页转成pdf文件的经验分享 网页转成pdf文件的经验分享怎么弄
-
C++ std::vector 简介
-
系统C盘清理:微信PC端文件清理,扩大C盘可用空间步骤
-
10款高性能NAS丨双十一必看,轻松搞定虚拟机、Docker、软路由
-
python使用fitz模块提取pdf中的图片
-
- 最近发表
-
- Python tkinter学习笔记(七):Notebook和Treeview
- 如何用 Python实现简单的表格界面
- 土地增值税清算中的施工合同进行判断是否有重复施工的情况
- 大模型时代必备技能:Embedding与向量数据库开发完全指南
- 分布式实时搜索和分析引擎——Elasticsearch
- elasticsearch v9.0.0重磅发布!解锁最新核心特性与性能飞跃!
- Java中间件-Elasticsearch(java中间件技术及其应用开发)
- 知名互联网公司和程序员都看好的数据库是什么?
- 快速了解Elasticsearch(快速了解词语浑话的读音、释义等知识点)
- 面试官:Kafka和ES选主有什么区别?
- 标签列表
-
- python判断字典是否为空 (50)
- crontab每周一执行 (48)
- aes和des区别 (43)
- bash脚本和shell脚本的区别 (35)
- canvas库 (33)
- dataframe筛选满足条件的行 (35)
- gitlab日志 (33)
- lua xpcall (36)
- blob转json (33)
- python判断是否在列表中 (34)
- python html转pdf (36)
- 安装指定版本npm (37)
- idea搜索jar包内容 (33)
- css鼠标悬停出现隐藏的文字 (34)
- linux nacos启动命令 (33)
- gitlab 日志 (36)
- adb pull (37)
- table.render (33)
- python判断元素在不在列表里 (34)
- python 字典删除元素 (34)
- vscode切换git分支 (35)
- python bytes转16进制 (35)
- grep前后几行 (34)
- hashmap转list (35)
- c++ 字符串查找 (35)