不做大哥好多年 不做大哥好多年
首页
  • MySQL
  • Redis
  • Elasticsearch
  • Kafka
  • Etcd
  • MongoDB
  • TiDB
  • RabbitMQ
  • 01.Python
  • 02.GO
  • 03.Java
  • 04.业务问题
  • 05.关键技术
  • 06.项目常识
  • 10.计算机基础
  • Docker
  • K8S
  • 容器原理
  • Istio
  • 01.GO基础
  • 02.面向对象
  • 03.并发编程
  • 04.常用库
  • 05.数据库操作
  • 06.Beego框架
  • 07.Beego商城
  • 08.GIN框架
  • 09.GIN论坛
  • 10.微服务
  • 01.Python基础
  • 02.Python模块
  • 03.Django
  • 04.Flask
  • 05.SYL
  • 06.Celery
  • 10.微服务
  • 01.Java基础
  • 02.面向对象
  • 03.Java进阶
  • 04.Web基础
  • 05.Spring框架
  • 100.微服务
  • 数据结构
  • 算法基础
  • 算法题分类
  • 前置知识
  • PyTorch
  • Langchain
  • Linux基础
  • Linux高级
  • Nginx
  • KeepAlive
  • ansible
  • zabbix
  • Shell
  • Linux内核

逍遥子

不做大哥好多年
首页
  • MySQL
  • Redis
  • Elasticsearch
  • Kafka
  • Etcd
  • MongoDB
  • TiDB
  • RabbitMQ
  • 01.Python
  • 02.GO
  • 03.Java
  • 04.业务问题
  • 05.关键技术
  • 06.项目常识
  • 10.计算机基础
  • Docker
  • K8S
  • 容器原理
  • Istio
  • 01.GO基础
  • 02.面向对象
  • 03.并发编程
  • 04.常用库
  • 05.数据库操作
  • 06.Beego框架
  • 07.Beego商城
  • 08.GIN框架
  • 09.GIN论坛
  • 10.微服务
  • 01.Python基础
  • 02.Python模块
  • 03.Django
  • 04.Flask
  • 05.SYL
  • 06.Celery
  • 10.微服务
  • 01.Java基础
  • 02.面向对象
  • 03.Java进阶
  • 04.Web基础
  • 05.Spring框架
  • 100.微服务
  • 数据结构
  • 算法基础
  • 算法题分类
  • 前置知识
  • PyTorch
  • Langchain
  • Linux基础
  • Linux高级
  • Nginx
  • KeepAlive
  • ansible
  • zabbix
  • Shell
  • Linux内核
  • MySQL

  • Redis

  • Elasticsearch

    • 01.ES安装
    • 02.ES介绍
    • 03.倒排索引 ✅
    • 04.ES原理 ✅
      • 01.ES 原理
        • 1、搜索引擎原理
        • 2、倒排索引
        • 3、ES 创建索引
        • 0)索引不变性
        • 1)动态更新索引
        • 2)ES写入流程
        • 3)ES名称解释
        • 4、文档更新与删除
        • 5、并发控制
        • 1)ES乐观锁
        • 2)ES悲观锁(无)
        • 6、批量操作
        • 7、ES数据类型
      • 02.ES新增Doc过程介绍
        • 1、ES增加Doc过程(新增一条数据)
        • 2、ES删除Doc过程(删除、合并、更新)
    • 05.ES集群原理 ✅
    • 06.ES集群部署
    • 07.ES优化
    • 21.ES基本使用
    • 22.中文分词检索
    • 23.python使用ES
    • 24.ES复杂类型
    • 100.制作一些数据
    • 101.ES同步
  • Kafka

  • Etcd

  • MongoDB

  • TiDB

  • RabbitMQ

  • 数据库
  • Elasticsearch
xiaonaiqiang
2024-03-19
目录

04.ES原理 ✅常识原理

Elasticsearch(ES)的核心原理包括搜索引擎的工作机制、倒排索引、索引的创建和更新、并发控制等

搜索引擎通过查询分析、分词、关键词匹配和搜索排序完成一次检索

倒排索引将关键词与文档建立映射关系,实现高效搜索

ES的索引具有不变性,通过创建新段(Segment)更新数据并发控制中,ES主要使用乐观锁机制确保一致性

ES写入流程包括写入内存、磁盘和提交操作,结合translog日志文件保障数据的持久性

# 01.ES 原理

# 1、搜索引擎原理

  • 一次完整的搜索从用户输入要查询的关键词开始
  • 比如想查找 Lucene 的相关学习资料,我们都会在 Google 或百度等搜索引擎中输入关键词
  • 比如输入“Lucene ,全文检索框架”,之后系统根据用户输入的关键词返回相关信息

一次检索大致可分为四步

  • 第一步:查询分析

    • 正常情况下用户输入正确的查询,比如搜索“里约奥运会”这个关键词
    • 用户输入正确完成一次搜索,但是搜索通常都是全开放的,任何的用户输入都是有可能的
    • 很大一部分还是非常口语化和个性化的,有时候还会存在拼写错误,用户不小心把“淘宝”打成“涛宝”
    • 这时候需要用自然语言处理技术来做拼写纠错等处理,以正确理解用户需求
  • 第二步:分词技术

    • 这一步利用自然语言处理技术将用户输入的查询语句进行分词
    • 如标准分词会把“lucene全文检索框架”分成 lucene | 全 | 文|检|索|框|架|
    • IK分词会分成: lucene|全文|检索|框架|,还有简单分词等多种分词方法
  • 第三步:关键词检索

    • 提交关键词后在倒排索引库中进行匹配,倒排索引就是关键词和文档之间的对应关系,就像给文档贴上标签
    • 比如在文档集中含有 "lucene" 关键词的有文档1 、文档 6、文档9
    • 含有 "全文检索" 关键词的有文档1 、文档6 那么做与运算
    • 同时含有 "lucene" 和 "全文检索" 的文档就是文档1和文档6,在实际的搜索中会有更复杂的文档匹配模型
  • 第四步:搜索排序

    • 对多个相关文档进行相关度计算、排序,返回给用户检索结果

# 2、倒排索引

  • 在构建索引时,首先会对文档进行分词处理,得到一系列的词项
  • 然后将这些词项添加到词项字典中,并更新相关的Posting List
  • 在此过程中,还会更新Term Index,以保证可以快速定位到词项字典中的词项
  • 在进行搜索时,首先会在Term Index中查找词项
  • 然后通过Term Dictionary找到对应的Posting List,从而找到包含该词项的所有文档

# 3、ES 创建索引

# 0)索引不变性

  • 索引的不变性

    • 倒排索引一旦写入磁盘后,不会再修改,这避免了多进程的并发修改问题
  • 不变性有重要的价值

    • 无需锁:由于数据不变,不需要额外的锁机制来保证一致性
    • 缓存优化:索引读入内存缓存后,只要有足够空间,后续读请求直接来自内存,不会触发磁盘访问
    • 持久缓存:例如过滤缓存,在索引生命周期内无需重建

# 1)动态更新索引

  • 更新索引原理

    • 通过增加新的索引段(Segment)来反映更新,而非修改已有的倒排索引
  • Lucene 段(Segment)

    • 索引以 段(Segment) 为单位管理,每个段包含部分文档的倒排索引

    • 新文档会创建新段,且一旦创建,段内容不可修改

    • 段会定期合并,未读取的段会删除

  • ES段搜索

    • Elasticsearch继承Lucene设计,查询时并行对多个段进行搜索,合并结果,提高搜索效率
    • 举例
      • 假设我们有一个包含1亿篇文档的大型索引,这个索引被分成了10个段,每个段包含1000万篇文档
      • 当我们进行搜索时,Elasticsearch会启动10个线程,对这10个段分别进行搜索
      • 当所有线程都搜索完成后,Elasticsearch会将这10个结果按照一定的规则合并,得到最终的搜索结果
  • Lucene 提交点(Commit Point)

    • 提交点在Lucene中起到了版本控制和索引状态管理的作用

    • 当索引发生变化时,例如添加、删除或更新了文档,Lucene会写入新的文件来反映这些变化

      • 在Lucene中,索引数据是存储在多个不同的文件中的
      • 假设你在初始状态下有三个索引文件:file1, file2, file3
      • 然后你添加了一些文档,Lucene生成了新的文件file4
      • commit后,Lucene生成新的提交点,这个提交点文件列表就是[file1, file2, file3, file4]
      • 如果此后你再删除了一些文档,Lucene可能会生成新的文件file5
      • 然后你又执行了commit操作,新的提交点的文件列表就可能是[file1, file2, file3, file4, file5]
    • 提交点也被用来支持索引的版本控制

      • Lucene可以保存多个提交点,每个提交点代表了索引在不同时间点的状态
      • 这样,就可以回滚到旧的提交点,也就是说,可以恢复到旧的索引状态

# 2)ES写入流程

  • 1)写入内存

    • 数据先写入内存buffer,并同时写入translog(事务日志)

      数据写入内存buffer后不可搜索,直到刷新到磁盘

  • 2)写入磁盘

    • refresh(写入到os cache)
      • 当buffer满或定时,数据刷新到OS缓存,变为可搜索
    • 写入磁盘
      • 定时将数据写入新的segment文件,数据刷新至磁盘
      • 并且数据在translog日志文件里面持久化到磁盘了一份
      • 此时就可以让这个segment file的数据对外提供搜索了
  • 3)commit操作

    • 重复1~2步骤

    • 新的数据不断进入buffer和translog,不断将buffer数据写入一个又一个新的segment file中去

    • 每次refresh完,buffer就会被清空,同时translog保留一份日志数据

    • 随着这个过程推进,translog文件会不断变大

    • 当translog文件达到一定程度时,就会执行commit操作

    • commit操作发生第一步,就是将buffer中现有数据refresh到os cache中去,清空buffer

  • 4)commit完成

    • 将一个commit point 写入磁盘文件,里面标识着这个 commit point 对应的所有 segment file

    • 同时强行将os cache 中目前所有的数据都 fsync 到磁盘文件中去

    • 将现有的translog清空,然后再次重启启用一个translog,此时commit操作完成

  • translog日志文件的作用是什么?

    • 在你执行commit操作之前,数据要么是停留在buffer中,要么是停留在os cache中

    • 无论是buffer还是os cache都是内存,一旦这台机器死了,内存中的数据就全丢了

    • 因此需要将数据对应的操作写入一个专门的日志文件,也就是translog日志文件

    • 一旦此时机器宕机,再次重启的时候,es会自动读取translog日志文件中的数据,恢复到内存buffer和os cache中去

  • 综上可以看出

    • es是准实时的,因此数据写入1秒后才可以搜索到
    • 如果translog是异步写入的话,es可能会丢失数据

# 3)ES名称解释

  • translog

    • 写入ES的数据首先会被写入translog文件,该文件持久化到磁盘

    • 保证服务器宕机的时候数据不会丢失,由于顺序写磁盘,速度也会很快

    • 同步写入

      • 每次写入请求执行的时候,translog在fsync到磁盘之后,才会给客户端返回成功
    • 异步写入

      • 写入请求缓存在内存中,每经过固定时间之后才会fsync到磁盘,写入量很大
      • 对于数据的完整性要求又不是非常严格的情况下,可以开启异步写入
  • refresh

    • 经过固定的时间,或者手动触发之后,将内存中的数据构建索引生成segment,写入文件系统缓冲区
  • commit/flush

    • 定期触发,将内存数据刷新到磁盘,清理translog,生成新的提交点
  • merge

    • 合并多个小segment成一个大segment,优化存储并减少查询延迟

    • merge的过程大致描述如下

    • 磁盘上两个小segment:A和B,内存中又生成了一个小segment:C

    • A,B被读取到内存中,与内存中的C进行merge,生成了新的更大的segment:D

    • 触发commit操作,D被fsync到磁盘

    • 创建新的提交点,删除A和B,新增D

# 4、文档更新与删除

  • 删除

    • 段是不可改变的,所以既不能从把文档从旧的段中移除,也不能修改旧的段来进行反映文档的更新

    • 磁盘上的每个segment都有一个.del文件与它相关联

    • 当发送删除请求时,该文档未被真正删除,而是在.del文件中标记为已删除

    • 此文档可能仍然能被搜索到,但会从结果中过滤掉

    • 当segment合并时,在.del文件中标记为已删除的文档不会被包括在新的segment中

    • 也就是说merge的时候会真正删除被删除的文档

  • 更新

    • 创建新文档时,Elasticsearch将为该文档分配一个版本号
    • 对文档的每次更改都会产生一个新的版本号
    • 当执行更新时,旧版本在.del文件中被标记为已删除,并且新版本在新的segment中写入索引
    • 旧版本可能仍然与搜索查询匹配,但是从结果中将其过滤掉

# 5、并发控制

# 1)ES乐观锁

  • Elasticsearch主要使用乐观并发控制,每个文档都有一个版本号,当文档被修改时,版本号会自动递增
  • 我们可以在更新文档时指定版本号,如果指定的版本号和服务器上的版本号不匹配,那么更新操作就会失败
  • 这种机制相当于实现了乐观锁,假设冲突不会经常发生,只在发生冲突时才处理

# 2)ES悲观锁(无)

  • Elasticsearch的设计是无锁的,它并不支持传统意义上的悲观锁
  • 也就是说,它不会在数据被访问时就加锁
  • 但是,通过使用特定的API和字段(如_seq_no和_primary_term)
  • 可以实现类似悲观锁的效果,这需要在应用层面进行处理

# 6、批量操作

  • bulk API 允许在单个步骤中进行多次 create 、 index 、 update 或 delete 请求

  • 如果你需要索引一个数据流比如日志事件,它可以排队和索引数百或数千批次

  • bulk 请求不是原子的: 不能用它来实现事务控制

  • 每个请求是单独处理的,因此一个请求的成功或失败不会影响其他的请求

  • 整个批量请求都需要由接收到请求的节点加载到内存中,因此该请求越大,其他请求所能获得的内存就越少

  • 批量请求的大小有一个最佳值,大于这个值,性能将不再提升,甚至会下降

  • 但是最佳值不是一个固定的值

  • 它完全取决于硬件、文档的大小和复杂度、索引和搜索的负载的整体情况

# 7、ES数据类型

  • Elasticsearch 支持如下简单域类型

    • 字符串: string

    • 整数 : byte, short, integer, long

    • 浮点数: float, double

    • 布尔型: boolean

    • 日期: date

  • 映射

    • 为了能够将时间域视为时间,数字域视为数字,字符串域视为全文或精确值字符串

    • Elasticsearch 需要知道每个域中数据的类型,这个信息包含在映射中

    • 索引中每个文档都有 类型 ,每种类型都有它自己的 映射 ,或者 模式定义

    • 映射定义了类型中的域,每个域的数据类型,以及Elasticsearch如何处理这些域

    • 映射也用于配置与类型有关的元数据

    • 当你索引一个包含新域的文档(之前未曾出现),Elasticsearch 会使用 动态映射

    • 通过JSON中基本数据类型,尝试猜测域类型

  • 使用如下规则

# 02.ES新增Doc过程介绍

# 1、ES增加Doc过程(新增一条数据)

  1. 插入数据 → 存入内存 buffer,记录到 translog,尚不可搜索
  2. 刷新(refresh) → 数据从 buffer 刷新到文件系统缓存(OS cache),数据可搜索,但尚未持久化到磁盘
  3. 持久化(flush) → 刷新到磁盘,生成新的段并创建新的提交点
  4. translog 作用 → 保证在系统宕机时,数据不丢失,可以从 translog 中恢复
  • 1)插入数据到内存

    • 首先,文档(Doc)会被写入到 内存中的 buffer(通常是一个内存缓存

    • 同时,这个写入操作会记录到 translog(事务日志),用于确保数据的持久性,即便系统宕机,数据也不会丢失

  • 2)刷新至系统缓存

    • 刷新操作(refresh)

      • 当 buffer 达到一定的大小或在经过一定的时间间隔(通常是 1 秒)后,Elasticsearch 会触发 刷新 操作
      • 这时,数据从内存 buffer 被 刷新到文件系统缓存(OS cache) 中,但尚未持久化到磁盘
      • 此时,数据已经可搜索,但并没有完全写入磁盘
    • 新段(Segment)

      • 刷新操作会创建新的 段(Segment),这个段会存储刷新后的数据并被放入文件系统缓存中
      • 数据在文件系统缓存中的存在使得它能够被搜索到,尽管它尚未写入磁盘
    • 搜索可见性(实时搜索)

      • 由于数据已经刷新到文件系统缓存中(即 OS cache),在 Elasticsearch 中,这些数据就变得 可搜索 了

      • 即使数据尚未持久化到磁盘,只要它在系统缓存中,就可以被查询到。

      • 这是 Elasticsearch 被称为 近实时搜索的关键原因,意味着插入的数据在几乎实时的情况下即可被搜索

  • 3)数据持久化到磁盘(flush)

    • Flush 操作:

      • 当数据刷新到系统缓存后,Elasticsearch 会在后台周期性地执行 flush 操作,将 文件系统缓存 中的 段(Segment) 持久化到磁盘
      • 此时,数据被完全写入磁盘
    • commit 操作:

      • 在 flush 时,会创建一个新的 提交点(commit point),该提交点记录了当前所有段的状态
      • 此时,文件系统中的段成为正式的、持久化的索引数据
  • 4)事务日志(translog)与数据持久性

    • translog 用于记录所有未刷新到磁盘的数据修改,确保在系统崩溃时可以恢复数据

    • 默认情况下,translog 是 异步写入 的:Elasticsearch 在内存中缓存 translog 数据,周期性地将其刷写到磁盘

    • 在某些配置下,translog 可以进行 同步写入,即每次操作都会等到 translog 被 fsync 到磁盘后才返回成功

  • 避免数据丢失

    • 为了防止在两次 flush操作之间出现数据丢失,Elasticsearch 会保证

    • 每个操作(增、删、改)会被记录到 translog 中。

    • translog 会在每次 refresh 后被 fsync 到磁盘,以确保即便系统宕机,数据仍能恢复。

# 2、ES删除Doc过程(删除、合并、更新)

  • 1)ES Doc删除

    • 删除一个ES文档不会立即从磁盘中删除,它只是被标记成已删除
    • 因为段是不可变的,所以文档既不能从久文档中移除,旧的段也不能更新以反映文档的版本
  • 2)ES Doc的合并

    • 通过每秒自动刷新创建新的段,很快的数量就越来越多,每个段消费大量资源
    • 每次搜索请求都需要依次检查每个段,段越多查询越慢
    • ES利用段合并在后台选择一些小的段合并成大的段
    • 合并后新的段可以被搜索,就的段被删除
  • 3)ES Doc的更新

    • 当一个文档被更新,旧版的文档被标记为删除,新版本的文档在新的段中索引
    • 该文档的不同版本都会匹配一个查询,但是较旧的版本会从结果中删除
上次更新: 2025/4/29 17:38:19
03.倒排索引 ✅
05.ES集群原理 ✅

← 03.倒排索引 ✅ 05.ES集群原理 ✅→

最近更新
01
05.快递Agent智能体
06-04
02
200.AI Agent核心概念
06-04
03
105.Agent智能体梳理
06-04
更多文章>
Theme by Vdoing | Copyright © 2019-2025 逍遥子 技术博客 京ICP备2021005373号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式