文章目录
简述
全文检索是一种通过对文本内容进行全面索引和搜索的技术。它可以快速地在大量文本数据中查找包含特定关键词或短语的文档,并返回相关的搜索结果。全文检索广泛应用于各种信息管理系统和应用中,如搜索引擎、文档管理系统、电子邮件客户端、新闻聚合网站等。它可以帮助用户快速定位所需信息,提高检索效率和准确性。
什么是倒排索引
正排索引(Forward Index)和倒排索引(Inverted Index)是全文检索中常用的两种索引结构,它们在索引和搜索的过程中扮演不同的角色。
正排索引(正向索引)
正排索引是将文档按顺序排列并进行编号的索引结构。每个文档都包含了完整的文本内容,以及其他相关的属性或元数据,如标题、作者、发布日期等。在正排索引中,可以根据文档编号或其他属性快速定位和访问文档的内容。正排索引适合用于需要对文档进行整体检索和展示的场景,但对于包含大量文本内容的数据集来说,正排索引的存储和查询效率可能会受到限制。
在MySQL 中通过 ID 查找就是一种正排索引的应用。
倒排索引(反向索引)
倒排索引是根据单词或短语建立的索引结构。它将每个单词映射到包含该单词的文档列表中。倒排索引的建立过程是先对文档进行分词处理,然后记录每个单词在哪些文档中出现,以及出现的位置信息。通过倒排索引,可以根据关键词或短语快速找到包含这些词语的文档,并确定它们的相关性。倒排索引适用于在大规模文本数据中进行关键词搜索和相关性排序的场景,它能够快速定位文档,提高搜索效率。
技术选型
Elasticsearch | Solr | MongoDB | MySQL | |
---|---|---|---|---|
DB类型 | 搜索引擎 | 搜索引擎 | 文档数据库 | 关系型数据库 |
基于何种框架开发 | Lucene | Lucene | ||
基于何种开发语言 | Java | Java | C++ | C、C++ |
数据结构 | FST、Hash等 | B+ Trees | ||
数据格式 | Json | Json/XML/CSV | Json | Row |
分布式支持 | 原生支持 | 支持 | 原生支持 | 不支持 |
数据分区方案 | 分片 | 分片 | 分片 | 分库分表 |
业务系统类型 | OLAP | OLAP | OLTP | OLTP |
事务支持 | 不支持 | 不支持 | 多文档ACID事务 | 支持 |
数据量级 | PB级 | TB级~PB级 | PB级 | 单库3000万 |
一致性策略 | 最终一致性 | 最终一致性 | 最终一致性即时一致性 | 即时一致性 |
擅长领域 | 海量数据全文检索大数据聚合分析 | 大数据全文检索 | 海量数据CRUD | 强一致性ACID事务 |
劣势 | 不支持事务写入实时性低 | 海量数据的性能不如ES随着数据量的不断增大,稳定性低于ES | 弱事务支持不支持join查询 | 大数据全文搜索性能低 |
查询性能 | ★★★★★ | ★★★★ | ★★★★★ | ★★★ |
写入性能 | ★★ | ★★ | ★★★★ | ★★★ |
ElasticSearch核心概念
节点:Node
一个节点就是一个Elasticsearch的实例,可以理解为一个 ES 的进程。
注意:一个节点 ≠ 一台服务器
角色:Roles
ES的角色分类:
-
主节点(active master):一般指活跃的主节点,一个集群中只能有一个,主要作用是对集群的管理。
-
候选节点(master-eligible):当主节点发生故障时,参与选举,也就是主节点的替代节点。
-
数据节点(data node):数据节点保存包含已编入索引的文档的分片。数据节点处理数据相关操作,如 CRUD、搜索和聚合。这些操作是 I/O 密集型、内存密集型和 CPU 密集型的。监控这些资源并在它们过载时添加更多数据节点非常重要。
-
预处理节点(ingest node):预处理节点有点类似于logstash的消息管道,所以也叫ingest pipeline,常用于一些数据写入之前的预处理操作。
注意:如果 node.roles 为缺省配置,那么当前节点具备所有角色。
索引:Index
索引在 ES 中所表述的含义和 MySQL 中的索引完全不同,在 MySQL 中索引指的是加速数据查询的一种特殊的数据结构,如 normal index。
而在 ES 中,索引表述的含义等价于 MySQL 中的表(仅针对 ES 7.x 以后版本),注意这里只是类比去理解,索引并不等于表。
在 ES 中,索引在不同的特定条件下可以表示三种不同的意思:
-
表示源文件数据:当做数据的载体,即类比为数据表,通常称作 index 。例如:通常说 集群中有 product 索引,即表述当前 ES 的服务中存储了 product 这样一张“表”。
-
表示索引文件:以加速查询检索为目的而设计和创建的数据文件,通常承载于某些特定的数据结构,如哈希、FST 等。例如:通常所说的 正排索引 和 倒排索引(也叫正向索引和反向索引)。就是当前这个表述,索引文件和源数据是完全独立的,索引文件存在的目的仅仅是为了加快数据的检索,不会对源数据造成任何影响,
-
表示创建数据的动作:通常说创建或添加一条数据,在 ES 的表述为索引一条数据或索引一条文档,或者 index 一个 doc 进去。此时索引一条文档的含义为向索引中添加数据。
索引的组成部分:
-
alias:索引别名
-
settings:索引设置,常见设置如分片和副本的数量等。
-
mapping:映射,定义了索引中包含哪些字段,以及字段的类型、长度、分词器等。
类型:Type(ES 7.x 之后版本已删除此概念)
在较早的ES版本中,索引可以包含多个类型,每个类型代表了不同的文档结构。然而,从ES 7.x版本开始,类型已经被弃用,一个索引只能包含一个文档类型。
ES 7.x
-
不推荐在请求中指定类型。例如,索引文档不再需要文档type。新的索引 API 适用PUT {index}/_doc/{id}于显式 ID 和POST {index}/_doc 自动生成的 ID。请注意,在 7.0 中,_doc是路径的永久部分,表示端点名称而不是文档类型。
-
索引创建、索引模板和映射 API 中的include_type_name参数将默认为false. 完全设置参数将导致弃用警告。
-
_default_映射类型被删除 。
ES 8.x
-
不再支持在请求中指定类型。
-
该include_type_name参数被删除。
文档:Document
文档是ES中的最小数据单元。它是一个具有结构化JSON格式的记录。文档可以被索引并进行搜索、更新和删除操作。
文档元数据,所有字段均以下划线开头,为系统字段,用于标注文档的相关信息:
-
_index:文档所属的索引名
-
_type:文档所属的类型名
-
_id:文档唯一id
-
_source: 文档的原始Json数据
-
_version: 文档的版本号,修改删除操作_version都会自增1
-
_seq_no: 和_version一样,一旦数据发生更改,数据也一直是累计的。Shard级别严格递增,保证后写入的Doc的_seq_no大于先写入的Doc的_seq_no。
-
_primary_term: _primary_term主要是用来恢复数据时处理当多个文档的_seq_no一样时的冲突,避免Primary Shard上的写入被覆盖。每当Primary Shard发生重新分配时,比如重启,Primary选举等,_primary_term会递增1。
ES中提供了一种强大的检索数据方式,这种检索方式称之为Query DSL(Domain Specified Language 领域专用语言) , Query DSL是利用Rest API传递JSON格式的请求体(RequestBody)数据与ES进行交互,这种方式的丰富查询语法让ES检索变得更强大,更简洁。
查询
全文检索查询(Full Text Queries)和术语级别查询(Term-Level Queries)是 Elasticsearch 中搜索和检索数据的两种不同方法。
全文检索查询旨在基于相关性搜索和匹配文本数据。这些查询会对输入的文本进行分析,将其拆分为词项(单个单词),并执行诸如分词、词干处理和标准化等操作。Elasticsearch 中的一些全文检索查询示例包括 match、match_phrase 和 multi_match 查询。
布尔查询
布尔查询可以按照布尔逻辑条件组织多条查询语句,只有符合整个布尔条件的文档才会被搜索出来。
在布尔条件中,可以包含两种不同的上下文。
- 搜索上下文(query context):使用搜索上下文时,Elasticsearch需要计算每个文档与搜索条件的相关度得分,这个得分的计算需使用一套复杂的计算公式,有一定的性能开销,带文本分析的全文检索的查询语句很适合放在搜索上下文中。
- 过滤上下文(filter context):使用过滤上下文时,Elasticsearch只需要判断搜索条件跟文档数据是否匹配,例如使用Term query判断一个值是否跟搜索内容一致,使用Range query判断某数据是否位于某个区间等。过滤上下文的查询不需要进行相关度得分计算,还可以使用缓存加快响应速度,很多术语级查询语句都适合放在过滤上下文中。
布尔查询一共支持4种组合类型:
类型 | 说明 |
---|---|
must | 可包含多个查询条件,每个条件均满足的文档才能被搜索到,每次查询需要计算相关度得分,属于搜索上下文 |
should | 可包含多个查询条件,不存在must和filter条件时,至少要满足多个查询条件中的一个,文档才能被搜索到,否则需满足的条件数量不受限制,匹配到的查询越多相关度越高,也属于搜索上下文 |
filter | 可包含多个过滤条件,每个条件均满足的文档才能被搜索到,每个过滤条件不计算相关度得分,结果在一定条件下会被缓存, 属于过滤上下文 |
must_not | 可包含多个过滤条件,每个条件均不满足的文档才能被搜索到,每个过滤条件不计算相关度得分,结果在一定条件下会被缓存, 属于过滤上下文 |
深度分页
ES通过参数index.max_result_window用来限制单次查询满足查询条件的结果窗口的大小,其默认值为10000。
ES分页查询流程大致如下:
- 数据存储在各个分片中,协调节点将查询请求转发给各个节点,当各个节点执行搜索后,将排序后的前N条数据返回给协调节点。
- 协调节点汇总各个分片返回的数据,再次排序,最终返回前N条数据给客户端。
- 这个流程会导致一个深度分页的问题,也就是翻页越多,性能越差,甚至导致ES出现OOM。
滚动查询:Scroll Search
scroll滚动搜索是先搜索一批数据,然后下次再搜索下一批数据,以此类推,直到搜索出全部的数据来。
scroll搜索会在第一次搜索的时候,保存一个当时的视图快照,之后只会基于该视图快照搜索数据,如果在搜索期间数据发生了变更,用户是看不到变更的数据的。因此,滚动查询不适合实时性要求高的搜索场景。
官方已不推荐使用滚动查询进行深度分页查询,因为无法保存索引状态。
search_after
参考文档:https://www.elastic.co/guide/en/elasticsearch/reference/7.17/paginate-search-results.html#search-after
scroll API适用于高效的深度滚动,但滚动上下文成本高昂,不建议将其用于实时用户请求。而search_after参数通过提供一个活动光标来规避这个问题。这样可以使用上一页的结果来帮助检索下一页。
分页方式 | 性能 | 优点 | 缺点 | 适用场景 |
---|---|---|---|---|
from + size | 低 | 灵活性好,实现简单,支持随机翻页 | 受制于max_result_window设置,不能无限制翻页;存在深度翻页问题,越往后翻页越慢。 | 数据量比较小,能容忍深度分页问题 |
scroll | 中 | 解决了深度分页问题 | scroll查询的相应数据是非实时的,如果遍历过程中插入新的数据,是查询不到的;保留上下文需要足够的堆内存空间。 | 海量数据的导出,需要查询海量结果集的数据 |
search_after | 高 | 性能最好,不存在深度分页问题,能够反映数据的实时变更 | 实现复杂,需要有一个全局唯一的字段连续分页的实现会比较复杂,因为每一次查询都需要上次查询的结果,它不适用于大幅度跳页查询 | 海量数据的分页 |
分词
分词器官方称之为文本分析器,顾名思义,是对文本进行分析处理的一种手段,基本处理逻辑为按照预先制定的分词规则,把原始文档分割成若干更小粒度的词项,粒度大小取决于分词器规则。
分词器的处理过程发生在 Index Time 和 Search Time 两个时期。
- Index Time:文档写入并创建倒排索引时期,其分词逻辑取决于映射参数analyzer。
- Search Time:搜索发生时期,其分词仅对搜索词产生作用。
组成
- 切词器(Tokenizer):用于定义切词(分词)逻辑
- 词项过滤器(Token Filter):用于对分词之后的单个词项的处理逻辑
- 字符过滤器(Character Filter):用于处理单个字符
注意:
- 分词器不会对源数据造成任何影响,分词仅仅是对倒排索引或者搜索词的行为。
切词器:Tokenizer
tokenizer 是分词器的核心组成部分之一,其主要作用是分词,或称之为切词。主要用来对原始文本进行细粒度拆分。拆分之后的每一个部分称之为一个 Term,或称之为一个词项。可以把切词器理解为预定义的切词规则。官方内置了很多种切词器,默认的切词器位 standard。
词项过滤器:Token Filter
词项过滤器用来处理切词完成之后的词项,例如把大小写转换,删除停用词或同义词处理等。官方同样预置了很多词项过滤器,基本可以满足日常开发的需要。当然也是支持第三方也自行开发的。
字符过滤器:Character Filter
分词之前的预处理,过滤无用字符。
HTML 标签过滤器:HTML Strip Character Filter
字符过滤器会去除 HTML 标签和转义 HTML 元素,如 、&
字符映射过滤器:Mapping Character Filter
通过定义映替换为规则,把特定字符替换为指定字符
正则替换过滤器:Pattern Replace Character Filter
相关性算法
TF-IDF
TF-IDF(term frequency–inverse document frequency)是一种用于信息检索与数据挖掘的常用加权技术。
- TF-IDF被公认为是信息检索领域最重要的发明,除了在信息检索,在文献分类和其他相关领域有着非常广泛的应用。
- IDF的概念,最早是剑桥大学的“斯巴克.琼斯”提出
- 1972年——“关键词特殊性的统计解释和它在文献检索中的应用”,但是没有从理论上解释IDF应该是用log(全部文档数/检索词出现过的文档总数),而不是其他函数,也没有做进一步的研究
- 1970,1980年代萨尔顿和罗宾逊,进行了进一步的证明和研究,并用香农信息论做了证明http://www.staff.city.ac.uk/~sb317/papers/foundations_bm25_review.pdf
- 现代搜索引擎,对TF-IDF进行了大量细微的优化
Lucene中的TF-IDF评分公式:
- TF是词频(Term Frequency)
检索词在文档中出现的频率越高,相关性也越高。
- IDF是逆向文本频率(Inverse Document Frequency)
每个检索词在索引中出现的频率,频率越高,相关性越低。总文档中有些词比如“是”、“的” 、“在” 在所有文档中出现频率都很高,并不重要,可以减少多个文档中都频繁出现的词的权重。
- 字段长度归一值( field-length norm)
检索词出现在一个内容短的 title 要比同样的词出现在一个内容长的 content 字段权重更大。
以上三个因素——词频(term frequency)、逆向文本频率(inverse document frequency)和字段长度归一值(field-length norm)——是在索引时计算并存储的,最后将它们结合在一起计算单个词在特定文档中的权重。
BM25
BM25 就是对 TF-IDF 算法的改进,对于 TF-IDF 算法,TF(t) 部分的值越大,整个公式返回的值就会越大。BM25 就针对这点进行来优化,随着TF(t) 的逐步加大,该算法的返回值会趋于一个数值。
- 从ES 5开始,默认算法改为BM 25
- 和经典的TF-IDF相比,当TF无限增加时,BM 25算分会趋于一个数值
单字符串多字段查询
三种场景:
- 最佳字段(Best Fields)
当字段之间相互竞争,又相互关联。例如,对于博客的 title和 body这样的字段,评分来自最匹配字段
- 多数字段(Most Fields)
处理英文内容时的一种常见的手段是,在主字段( English Analyzer),抽取词干,加入同义词,以匹配更多的文档。相同的文本,加入子字段(Standard Analyzer),以提供更加精确的匹配。其他字段作为匹配文档提高相关度的信号,匹配字段越多则越好。
- 混合字段(Cross Fields)
对于某些实体,例如人名,地址,图书信息。需要在多个字段中确定信息,单个字段只能作为整体的一部分。希望在任何这些列出的字段中找到尽可能多的词。
最佳字段(Best Fields)搜索
best_fields策略获取最佳匹配字段的得分, final_score = max(其他匹配字段得分, 最佳匹配字段得分)
采用 best_fields 查询,并添加参数 tie_breaker=0.1,final_score = 其他匹配字段得分 * 0.1 + 最佳匹配字段得分
Best Fields是默认类型,可以不用指定,等价于dis_max查询方式
聚合
Metric Aggregation:—些数学运算,可以对文档字段进行统计分析,类比Mysql中的 min(), max(), sum() 操作。
Bucket Aggregation: 一些满足特定条件的文档的集合放置到一个桶里,每一个桶关联一个key,类比Mysql中的group by操作。
Pipeline Aggregation:对其他的聚合结果进行二次聚合
ES聚合分析的默认作用范围是query的查询结果集,同时ES还支持以下方式改变聚合的作用范围:
- Filter
- Post Filter
- Global
指定order,按照count和key进行排序:
- 默认情况,按照count降序排序
- 指定size,就能返回相应的桶
ElasticSearch在对海量数据进行聚合分析的时候会损失搜索的精准度来满足实时性的需求。
不精准的原因: 数据分散到多个分片,聚合是每个分片的取 Top X,导致结果不精准。ES 可以不每个分片Top X,而是全量聚合,但势必这会有很大的性能问题。
插入数据时对索引进行预排序
- Index sorting (索引排序)可用于在插入时对索引进行预排序,而不是在查询时再对索引进行排序,这将提高范围查询(range query)和排序操作的性能。
- 在 Elasticsearch 中创建新索引时,可以配置如何对每个分片内的段进行排序。
节点查询缓存(Node query cache)可用于有效缓存过滤器(filter)操作的结果。如果多次执行同一 filter 操作,这将很有效,但是即便更改过滤器中的某一个值,也将意味着需要计算新的过滤器结果。
ES集群
概念
集群
-
一个集群可以有一个或者多个节点
-
不同的集群通过不同的名字来区分,默认名字“elasticsearch“
-
通过配置文件修改,或者在命令行中 -E cluster.name=es-cluster进行设定
节点
- 节点是一个Elasticsearch的实例
- 本质上就是一个JAVA进程
- 一台机器上可以运行多个Elasticsearch进程,但是生产环境一般建议一台机器上只运行一个Elasticsearch实例
- 每一个节点都有名字,通过配置文件配置,或者启动时候 -E node.name=node1指定
- 每一个节点在启动之后,会分配一个UID,保存在data目录下
节点类型
- Master Node:主节点
- Master eligible nodes:可以参与选举的合格节点
- Data Node:数据节点
- Coordinating Node:协调节点
- 其他节点
集群状态(Cluster State) ,维护了一个集群中,必要的信息
- 所有的节点信息
- 所有的索引和其相关的Mapping与Setting信息
- 分片的路由信息
Master Node的职责
- 处理创建,删除索引等请求,负责索引的创建与删除
- 决定分片被分配到哪个节点
- 维护并且更新Cluster State
Master Node的最佳实践
- Master节点非常重要,在部署上需要考虑解决单点的问题
- 为一个集群设置多个Master节点,每个节点只承担Master 的单一角色
选主的过程
- 互相Ping对方,Node ld 低的会成为被选举的节点
- 其他节点会加入集群,但是不承担Master节点的角色。一旦发现被选中的主节点丢失,就会选举出新的Master节点
Data Node & Coordinating Node
Data Node
- 可以保存数据的节点,叫做Data Node,负责保存分片数据。在数据扩展上起到了至关重要的作用
- 节点启动后,默认就是数据节点。可以设置node.data: false 禁止
- 由Master Node决定如何把分片分发到数据节点上
- 通过增加数据节点可以解决数据水平扩展和解决数据单点问题
Coordinating Node
- 负责接受Client的请求, 将请求分发到合适的节点,最终把结果汇集到一起
- 每个节点默认都起到了Coordinating Node的职责
其他节点类型
Hot & Warm Node
- 不同硬件配置 的Data Node,用来实现Hot & Warm架构,降低集群部署的成本
Ingest Node
- 数据前置处理转换节点,支持pipeline管道设置,可以使用ingest对数据进行过滤、转换等操作
Machine Learning Node
- 负责跑机器学习的Job,用来做异常检测
Tribe Node
- Tribe Node连接到不同的Elasticsearch集群,并且支持将这些集群当成一个单独的集群处理
分片(Primary Shard & Replica Shard)
主分片(Primary Shard)
- 用以解决数据水平扩展的问题。通过主分片,可以将数据分布到集群内的所有节点之上
- 一个分片是一个运行的Lucene的实例
- 主分片数在索引创建时指定,后续不允许修改,除非Reindex
副本分片(Replica Shard)
- 用以解决数据高可用的问题。 副本分片是主分片的拷贝
- 副本分片数,可以动态调整
- 增加副本数,还可以在一定程度上提高服务的可用性(读取的吞吐)
全局流量管理(GTM)和负载均衡(SLB)的区别:
GTM 是通过DNS将域名解析到多个IP地址,不同用户访问不同的IP地址,来实现应用服务流量的分配。同时通过健康检查动态更新DNS解析IP列表,实现故障隔离以及故障切换。最终用户的访问直接连接服务的IP地址,并不通过GTM。而 SLB 是通过代理用户访问请求的形式将用户访问请求实时分发到不同的服务器,最终用户的访问流量必须要经过SLB。 一般来说,相同Region使用SLB进行负载均衡,不同region的多个SLB地址时,则可以使用GTM进行负载均衡。
高级
ES数据预处理
Ingest Node
Elasticsearch 5.0后,引入的一种新的节点类型。默认配置下,每个节点都是Ingest Node:
-
具有预处理数据的能力,可拦截lndex或 Bulk API的请求
-
对数据进行转换,并重新返回给Index或 Bulk APl
无需Logstash,就可以进行数据的预处理,例如:
-
为某个字段设置默认值;
-
重命名某个字段的字段名;
-
对字段值进行Split 操作
-
支持设置Painless脚本,对数据进行更加复杂的加工
Ingest Node VS Logstash
Logstash | Ingest Node | |
---|---|---|
数据输入与输出 | 支持从不同的数据源读取,并写入不同的数据源 | 支持从ES REST API获取数据,并且写入Elasticsearch |
数据缓冲 | 实现了简单的数据队列,支持重写 | 不支持缓冲 |
数据处理 | 支持大量的插件,也支持定制开发 | 内置的插件,可以开发Plugin进行扩展(Plugin更新需要重启) |
配置和使用 | 增加了一定的架构复杂度 | 无需额外部署 |
Ingest Pipeline
应用场景: 修复与增强写入数据
Painless Script
自Elasticsearch 5.x后引入,专门为Elasticsearch 设计,扩展了Java的语法。Painless支持所有Java 的数据类型及Java API子集。
建模
关系型数据库范式化(Normalize)设计的主要目标是减少不必要的更新,往往会带来一些副作用:
- 一个完全范式化设计的数据库会经常面临“查询缓慢”的问题。数据库越范式化,就需要Join越多的表;
- 范式化节省了存储空间,但是存储空间已经变得越来越便宜;
- 范式化简化了更新,但是数据读取操作可能更多。
反范式化(Denormalize)的设计不使用关联关系,而是在文档中保存冗余的数据拷贝。
- 优点: 无需处理Join操作,数据读取性能好。Elasticsearch可以通过压缩_source字段,减少磁盘空间的开销
- 缺点: 不适合在数据频繁修改的场景。 一条数据的改动,可能会引起很多数据的更新
关系型数据库,一般会考虑Normalize 数据;在Elasticsearch,往往考虑Denormalize 数据。
Elasticsearch并不擅长处理关联关系,一般会采用以下四种方法处理关联
- 对象类型
- 嵌套对象(Nested Object)
- 父子关联关系(Parent / Child )
- 应用端关联
嵌套对象(Nested Object)
什么是Nested Data Type
- Nested数据类型: 允许对象数组中的对象被独立索引
- 使用nested 和properties 关键字,将所有actors索引到多个分隔的文档
- 在内部, Nested文档会被保存在两个Lucene文档中,在查询时做Join处理
父子关联关系(Parent / Child )
- 对象和Nested对象的局限性: 每次更新,可能需要重新索引整个对象(包括根对象和嵌套对象)
- ES提供了类似关系型数据库中Join 的实现。使用Join数据类型实现,可以通过维护Parent/ Child的关系,从而分离两个对象
- 父文档和子文档是两个独立的文档
- 更新父文档无需重新索引子文档。子文档被添加,更新或者删除也不会影响到父文档和其他的子文档
嵌套文档 VS 父子文档
Nested Object | Parent / Child | |
---|---|---|
优点 | 文档存储在一起,读取性能高 | 父子文档可以独立更新 |
缺点 | 更新嵌套的子文档时,需要更新整个文档 | 需要额外的内存维护关系。读取性能相对差 |
适用场景 | 子文档偶尔更新,以查询为主 | 子文档更新频繁 |
调优
写数据底层原理
核心概念
segment file: 存储倒排索引的文件,每个segment本质上就是一个倒排索引,每秒都会生成一个segment文件,当文件过多时es会自动进行segment merge(合并文件),合并时会同时将已经标注删除的文档物理删除。
commit point: 记录当前所有可用的segment,每个commit point都会维护一个.del文件,即每个.del文件都有一个commit point文件(es删除数据本质是不属于物理删除),当es做删改操作时首先会在.del文件中声明某个document已经被删除,文件内记录了在某个segment内某个文档已经被删除,当查询请求过来时在segment中被删除的文件是能够查出来的,但是当返回结果时会根据commit point维护的那个.del文件把已经删除的文档过滤掉
translog日志文件: 为了保证可靠存储,防止elasticsearch宕机造成数据丢失,es会将每次写入数据同时写到translog日志中。
**os cache:**操作系统里面,磁盘文件其实都有一个东西,叫做os cache,操作系统缓存,就是说数据写入磁盘文件之前,会先进入os cache,先进入操作系统级别的一个内存缓存中去
ELK
ELK架构分为两种,一种是经典的ELK,另外一种是加上消息队列(Redis或Kafka或RabbitMQ)和Nginx结构。
经典的ELK主要是由Filebeat + Logstash + Elasticsearch + Kibana组成,(早期的ELK只有Logstash + Elasticsearch + Kibana)
此架构主要适用于数据量小的开发环境,存在数据丢失的危险。
Logstash核心概念
Pipeline
-
包含了input—filter—output三个阶段的处理流程
-
插件生命周期管理
-
队列管理
Logstash Event
-
数据在内部流转时的具体表现形式。数据在input 阶段被转换为Event,在 output被转化成目标格式数据
-
Event 其实是一个Java Object,在配置文件中,可以对Event 的属性进行增删改查
Codec (Code / Decode)
将原始数据decode成Event;将Event encode成目标数据
Beats
轻量型数据采集器,文档地址: https://www.elastic.co/guide/en/beats/libbeat/7.17/index.html
Beats 是一个免费且开放的平台,集合了多种单一用途的数据采集器。它们从成百上千或成千上万台机器和系统向 Logstash 或 Elasticsearch 发送数据。
FileBeat专门用于转发和收集日志数据的轻量级采集工具。它可以作为代理安装在服务器上,FileBeat监视指定路径的日志文件,收集日志数据,并将收集到的日志转发到Elasticsearch或者Logstash。
Grok插件
Grok是一种将非结构化日志解析为结构化的插件。这个工具非常适合用来解析系统日志、Web服务器日志、MySQL或者是任意其他的日志格式。
https://www.elastic.co/guide/en/logstash/7.17/plugins-filters-grok.html
Grok语法
Grok是通过模式匹配的方式来识别日志中的数据,可以把Grok插件简单理解为升级版本的正则表达式。它拥有更多的模式,默认Logstash拥有120个模式。如果这些模式不满足我们解析日志的需求,我们可以直接使用正则表达式来进行匹配。
背压机制
顾名思义,背压是分布式系统中的一种机制,指的是系统限制数据消耗或生成速率以防止自身或其下游组件过载的能力。对其调用方应用背压的系统并不总是显式的,例如以限制或负载卸除的形式,但有时也是隐式的,例如通过增加所处理请求的延迟来减慢自己的系统速度,而无需明确说明。隐式和显式背压都旨在减慢调用方的速度,当调用方行为不佳或服务本身运行状况不佳且需要时间恢复时。