当前位置: 首页 > news >正文

ElasticSearch架构和写入、更新、删除、查询的底层逻辑

ES插入增产改查流程

简单说,ES 架构基于 “分布式集群 + 分片” 实现高可用与横向扩展,而读写删查的底层逻辑则围绕 “倒排索引、分片协作、版本控制” 展开,确保性能与数据一致性。


一、Elasticsearch 核心架构

ES 是分布式搜索引擎,核心架构设计的目标是 “分片存储、集群协作”,先明确关键组件及其作用:

1. 集群与节点(Cluster & Node)
  • 集群(Cluster):由多个节点组成的整体,对外提供统一服务,通过 cluster.name 标识(默认 elasticsearch)。
  • 节点(Node):单个 ES 进程,按功能分为 3 类核心节点:
    • 主节点(Master Node):管理集群元数据(如分片分配、节点加入 / 退出),默认每个节点都可参选,通过 node.master: true 配置。
    • 数据节点(Data Node):存储分片数据,负责读写删查操作,通过 node.data: true 配置(性能敏感,需足够 CPU / 内存 / 磁盘)。
    • 协调节点(Coordinating Node):接收客户端请求,转发到对应节点并汇总结果,默认所有节点都是协调节点(可通过 node.master: false 和 node.data: false 配置纯协调节点)。
2. 索引与分片(Index & Shard)
  • 索引(Index):类似关系型数据库的 “表”,是逻辑上的数据集(如 user_index 存储用户数据)。
  • 分片(Shard):索引的物理拆分,解决 “单节点存储海量数据” 的问题,分为两类:
    • 主分片(Primary Shard):数据写入的第一站,每个索引默认 1 个(可在创建时指定,创建后不可修改),负责数据的索引构建与存储。
    • 副本分片(Replica Shard):主分片的副本,用于 “高可用” 和 “分担查询压力”,数量可动态调整(默认 1 个),仅能从主分片同步数据,不直接接收写入。

例:若 user_index 配置 3 个主分片、2 个副本,则总分片数 = 3(主) + 3×2(副本)= 9 个,数据会均匀分布到 3 个主分片中。

二、写入(Index)底层逻辑

ES 写入数据的核心是 “先写主分片,再同步副本,最后构建倒排索引”,确保数据可靠与查询可用,步骤如下:

  1. 请求路由:客户端发送写入请求到协调节点,协调节点通过公式 shard = hash(routing) % 主分片数 计算数据应写入的主分片(routing 默认是文档 ID,可自定义)。
  2. 主分片写入:协调节点将请求转发到主分片所在的数据节点,该节点执行以下操作:
    • 验证请求(如字段类型、权限);
    • 将数据写入 内存缓冲区(In-Memory Buffer),同时记录 事务日志(Translog)(防止内存数据丢失);
    • 当内存缓冲区满(默认 100MB)或达到刷新间隔(默认 1 秒),触发 刷新(Refresh):将内存数据生成不可变的 段(Segment) 写入磁盘(但不刷盘,仍在操作系统缓存),此时数据可被查询;
  3. 副本同步:主分片写入成功后,将数据同步到所有副本分片所在节点,副本执行与主分片相同的写入逻辑(内存 + Translog+Segment)。
  4. 最终刷盘:当 Translog 满(默认 512MB)或达到刷盘间隔(默认 30 分钟),触发 ** flush**:将所有 Segment 刷到磁盘,清空 Translog,完成数据持久化。

三、更新(Update)底层逻辑

ES 没有 “原地更新”,本质是 “删除旧文档 + 写入新文档”,步骤如下:

  1. 查询旧文档:协调节点先根据文档 ID 找到主分片,查询旧文档的版本号(ES 用版本控制避免并发冲突)。
  2. 标记删除:将旧文档标记为 已删除(Tombstone),不直接物理删除(物理删除会在后续 “段合并” 时执行)。
  3. 写入新文档:按 “写入逻辑” 将更新后的新文档写入主分片,同时版本号 +1。
  4. 同步副本:主分片将 “删除旧文档 + 写入新文档” 的操作同步到副本,确保集群数据一致。

注意:若更新时未指定文档 ID(如 _update_by_query),会先查询符合条件的文档,再逐个执行 “删旧写新”,性能较低,建议尽量按 ID 更新。

四、删除(Delete)底层逻辑

ES 同样不支持 “物理删除”,而是 “标记删除 + 延迟清理”,步骤如下:

  1. 请求路由:协调节点根据文档 ID 找到主分片,发送删除请求。
  2. 标记删除:主分片将目标文档标记为 Tombstone(墓碑),此时文档不可被查询,但仍占用磁盘空间。
  3. 同步副本:主分片将删除标记同步到所有副本,确保副本也不可查询该文档。
  4. 物理清理:当 ES 后台执行 段合并(Segment Merge) 时(将多个小 Segment 合并为大 Segment),会过滤掉标记为 Tombstone 的文档,释放磁盘空间。

五、查询(Search)底层逻辑

ES 查询分为 “查询(Query)” 和 “取回(Fetch)” 两阶段,支持 “近实时查询”,步骤如下:

1. 查询阶段(Query Phase):找到匹配文档的 ID 和得分
  • 请求分发:协调节点将查询请求广播到索引的所有主分片和副本分片(默认随机选一个,分担压力)。
  • 分片查询:每个分片在本地的 Segment 中执行查询(基于倒排索引快速匹配),返回 “匹配的文档 ID + 相关性得分(Score)”,并按得分排序,取前 N 条(如分页查询的 size 数量)。
  • 结果汇总:协调节点收集所有分片返回的结果,再次按得分排序,筛选出最终的前 N 条文档 ID。
2. 取回阶段(Fetch Phase):获取完整文档数据
  • 请求文档:协调节点根据最终的文档 ID,向对应的分片(主或副本)发送 “获取文档” 请求,获取完整的文档字段(默认返回所有字段,可通过 _source 筛选)。
  • 返回结果:协调节点汇总所有完整文档,返回给客户端。

优化点:若查询仅需部分字段(如 nameage),可在查询时指定 _source: ["name", "age"],减少数据传输量,提升性能。

六、关键底层技术支撑

  1. 倒排索引(Inverted Index):查询的核心,将 “字段值” 映射到 “文档 ID”(如 “关键词:Elasticsearch” 对应文档 ID 1、3、5),实现快速全文检索。
  2. 段(Segment):ES 存储数据的最小单元,是不可变的 Lucene 索引文件,不可变特性保证了查询性能(无需锁竞争),但也导致更新 / 删除需 “标记 + 重建”。
  3. 版本控制:通过 _version 字段实现,更新 / 删除时需验证版本号,防止并发操作导致数据覆盖(默认乐观锁,也支持悲观锁)。

七、Elasticsearch 读写删查核心步骤对比表

该表汇总了写入(Index)、更新(Update)、删除(Delete)、查询(Search)四大操作的核心流程、关键技术点及核心目标,方便快速对比和记忆。

操作类型核心步骤(按执行顺序)关键技术 / 组件核心目标
写入(Index)1. 协调节点按 hash(routing)%主分片数 路由到主分片2. 主分片验证请求,写入内存缓冲区 + Translog3. 触发 Refresh:内存数据生成 Segment(可查询)4. 主分片同步数据到所有副本分片5. 触发 Flush:Segment 刷盘,清空 Translogrouting 路由、内存缓冲区、Translog、Segment、Refresh/Flush数据可靠存储(持久化)、近实时可查
更新(Update)1. 协调节点路由到主分片,查询旧文档并获取版本号2. 主分片标记旧文档为 Tombstone(逻辑删除)3. 按写入流程将更新后的数据写入主分片(版本号 + 1)4. 同步 “删旧写新” 操作到所有副本5. 旧文档待 Segment Merge 时物理删除版本控制、Tombstone、Segment Merge保证数据更新一致性,避免并发冲突
删除(Delete)1. 协调节点路由到主分片,验证文档存在性2. 主分片标记目标文档为 Tombstone3. 同步删除标记到所有副本分片(副本同步标记后,文档不可查)4. 待 Segment Merge 时,过滤 Tombstone 文档,释放磁盘空间routing 路由、Tombstone、Segment Merge快速标记删除(不阻塞操作),延迟清理释放空间
查询(Search)1. 查询阶段:- 协调节点广播请求到所有相关分片(主 / 副本)- 分片执行查询(基于倒排索引),返回 “文档 ID + 得分” 并排序- 协调节点汇总结果,再次排序筛选出前 N 个 ID2. 取回阶段:- 协调节点向对应分片请求完整文档数据- 汇总文档,返回给客户端倒排索引、协调节点汇总、相关性得分(Score)、_source 筛选快速匹配目标文档,返回准确且排序合理
的结果


Translog 刷盘机制 和 Segment Merge 触发条件 

拆解 Translog 刷盘机制 和 Segment Merge 触发条件 的核心细节,帮你搞懂 ES 数据持久化与空间优化的底层逻辑。

一、Translog 刷盘机制:确保写入不丢数据

Translog 是 ES 用于 “防止内存数据丢失” 的关键组件,本质是一个追加写入的日志文件,其刷盘机制直接决定数据的持久化可靠性,核心逻辑可从 “触发时机” 和 “刷盘流程” 两方面看。

1. 核心作用
  • 写入数据时,先写内存缓冲区(In-Memory Buffer),同时同步写 Translog(顺序写,性能高)。
  • 若节点突然宕机,内存缓冲区数据会丢失,但 Translog 已落盘,重启后可通过 Translog 恢复数据,避免丢失。
2. 刷盘触发时机(3 种核心场景)

Translog 并非实时刷盘,而是通过 “定时 + 定量” 机制平衡性能与可靠性,具体触发条件如下:

触发类型具体条件配置参数(默认值)核心目的
定量触发Translog 文件大小达到阈值index.translog.flush_threshold_size: 512MB避免 Translog 文件过大,导致恢复时耗时过长
定时触发距离上次刷盘时间达到间隔index.translog.flush_threshold_period: 30m即使数据量小,也能定期持久化,降低丢失风险
手动触发调用 API 强制刷盘执行 POST /索引名/_flush(或 _flushall 全局刷盘)运维场景(如节点重启前),确保所有数据落盘
3. 刷盘核心流程
  1. 触发刷盘后,ES 会先关闭当前 Translog 文件,新建一个新的 Translog 文件接收后续写入(避免刷盘阻塞新请求)。
  2. 将关闭的 Translog 文件强制刷到磁盘(调用操作系统 fsync 命令,确保数据真正写入磁盘,而非停留在操作系统缓存)。
  3. 刷盘成功后,清空内存缓冲区中已写入 Segment 的数据(未触发 Refresh 的数据仍在内存),完成一次刷盘周期。

二、Segment Merge 触发条件:优化查询性能 + 释放空间

Segment 是 ES 存储数据的最小单元(不可变),写入时会生成大量小 Segment,过多小 Segment 会导致 “查询时需遍历所有小 Segment,性能下降”,且删除 / 更新标记的文档无法释放空间。Segment Merge 就是将 “多个小 Segment 合并为大 Segment” 的后台任务,触发条件分为 “自动触发” 和 “手动触发”。

1. 核心作用
  • 提升查询性能:合并后 Segment 数量减少,查询时只需遍历少量大 Segment,减少 IO 开销。
  • 释放磁盘空间:合并过程中,会过滤掉标记为 Tombstone(删除 / 更新旧文档)的记录,真正释放磁盘空间。
  • 减少元数据开销:每个 Segment 都有独立的元数据,合并后元数据总量减少,降低内存占用。
2. 自动触发条件(4 种核心场景)

ES 会通过后台线程(MergeScheduler)自动检测并触发 Merge,核心判断逻辑基于 “Segment 数量 + 大小”:

触发场景具体条件配置参数(默认值)说明
Segment 数量超标同一分片下,大小小于 merge.policy.floor_segment 的小 Segment 数量超过阈值merge.policy.max_merge_at_once: 10(一次最多合并 10 个小 Segment)merge.policy.floor_segment: 2MB(小于 2MB 的视为 “小 Segment”)最常见的触发场景,避免小 Segment 堆积
Segment 大小比例超标当一个 Segment 的大小,是其相邻更大 Segment 大小的一定比例以上merge.policy.max_merged_segment: 5GB(合并后的大 Segment 最大不超过 5GB)merge.policy.segments_per_tier: 10(每层 Segment 数量不超过 10 个,超过则合并)防止出现 “大小差异过大的 Segment”,平衡查询效率
写入触发每次 Refresh 生成新 Segment 后,会检查当前 Segment 数量,若超标则触发 Merge无单独参数,依赖上述 “数量 / 大小” 阈值写入频繁时,小 Segment 生成快,Merge 也会更频繁
定时触发后台 Merge 线程会定期(默认 1 秒)检查是否需要合并indices.memory.index_buffer_size: 10%(间接影响,内存缓冲满触发 Refresh 后,进而可能触发 Merge)兜底机制,确保即使写入少,也能清理过期数据
3. 手动触发条件(运维场景)

当自动 Merge 不及时(如大量删除后需快速释放空间),可通过 API 手动触发 Merge:

  • 合并指定索引:POST /索引名/_forcemerge
  • 合并所有索引:POST /_forcemerge
  • 关键参数:max_num_segments=1(可选,强制将分片的 Segment 合并为 1 个大 Segment,适合只读索引场景,但会占用大量 IO,需避开业务高峰)
4. 注意事项
  • Merge 是 IO 密集型任务:合并大 Segment 时会占用大量磁盘 IO 和 CPU,可能影响查询性能。ES 默认会限制 Merge 的 IO 速率(通过 indices.store.throttle.max_bytes_per_sec 配置,默认 20MB/s),避免过度抢占资源。
  • 只读索引建议手动 Merge:对于日志等只读索引(写入后不再更新),可在写入完成后手动触发 _forcemerge max_num_segments=1,最大化查询性能。

Segment为什么分层

在 Elasticsearch 中,“每层 segment” 是指基于TieredMergePolicy(分层合并策略)下,按照段的大小划分的不同 “层级”。

Elasticsearch 使用 Lucene 作为底层索引引擎,Lucene 采用段化存储来管理索引,段是不可变的磁盘索引文件集合,包含倒排索引、正向索引等数据结构。随着数据不断写入,会不断生成新的段,而过多的小段会影响查询性能,因为每个搜索请求都需要访问多个段。为了优化查询性能和磁盘占用,Elasticsearch 会在后台定期执行合并操作,将多个小段合并成较大的段。

TieredMergePolicy会将索引中的段分成若干层,每个层次内的段符合某些大小范围。例如,较小的段可能处于较低的层次,随着不断合并,段的大小逐渐增大,会晋升到更高的层次。每个层次都有一个最大段数限制,由index.merge.policy.segments_per_tier参数控制,默认值为 10。当某个层次中的段数量超过这个阈值时,就会触发合并操作,将这些段合并为一个更大的段。

之所以引入 “层” 的概念,主要是为了更好地管理段的合并过程。通过分层,可以避免过度合并小段,同时确保合并后的段大小合理,能够有效地提升查询性能。如果没有分层的概念,可能会导致频繁地对所有段进行合并,消耗大量的系统资源,或者无法及时将小段合并成大段,影响查询性能。

http://www.dtcms.com/a/536246.html

相关文章:

  • 做市场调研的网站网站建设费可以计入管理费用吗
  • SQL 性能优化:出现 sql 比较慢怎么办?
  • Access-Control-Allow-Origin 详解
  • __金仓数据库平替MongoDB:银行存款系统国产化实践__
  • 14天极限复习软考day4-法律、设计模式
  • 深度剖析数字化转型的三驾马车:信息化、数字化、数智化
  • 晋中网站公司长沙找人做企业网站文案
  • Qt——界面优化
  • 基于python的化妆品销售分析系统
  • 永康网站建设的公司快速搭建网站demo
  • jcms网站建设想做app推广项目在哪找
  • 罗永浩做的网站我要用新浪云做网站
  • 异步编程深度解析
  • Redis GEO 地理位置搜索:实战示例 + 底层原理解析
  • Java的中间件
  • 邢台学校网站建设价格百度企业服务平台
  • 建网站要注意的细节物流网站首页图片
  • 牙根尖挺使用失误的常见原因分析及规避方法
  • 麒光AI-OCT大模型:心血管诊疗的智能革命与未来展望
  • AI 驱动的 ITSM:数字化转型时代的 IT 服务新范式
  • EasyGBS视频实时监控系助力实现换热站全景可视化管理
  • HarmonyOS安全加密与TEE开发实战
  • 门户网站建设 简报网络培训视频如何加速
  • uniapp引入uniim后聊天列表无法加载出来
  • AWS Auto Scaling:自动扩容,让服务器像呼吸一样灵活
  • 实战|AWS Snowcone边缘计算落地工业场景:从技术原理到代码实现
  • uni-app facebook登录
  • 【设计模式笔记07】:迪米特法则
  • SIP协议详解:从请求到挂断的全生命周期
  • 药材网网站技术建设手机网站微信链接怎么做