前言
Elasticsearch is a highly scalable open-source full-text search and analytics engine. It allows you to store, search, and analyze big volumes of data quickly and in near real time. It is generally used as the underlying engine/technology that powers applications that have complex search features and requirements.
Elasticsearch是一个高度可扩展的开源全文搜索和分析引擎。它允许您快速,近实时地存储,搜索和分析大量数据。它通常用作底层引擎/技术,为具有复杂搜索功能和要求的应用程序提供支持。
Elastic Stack
Elastic Stack 是原 ELK Stack 在 5.0 版本加入 Beats 套件后的新称呼
- Logstash用于数据采集 (新增轻量级Beats)
- Kibana用于数据展示
使用场景
- 您运行在线网上商店,允许您的客户搜索您销售的产品。
- 您运行价格警报平台,允许精通价格的客户指定一条规则,例如“我有兴趣购买特定的电子产品,如果小工具的价格在下个月内从任何供应商降至X美元以下,我希望收到通知”
- 您希望收集日志或交易数据,并且希望分析和挖掘此数据以查找趋势,统计信息,摘要或异常。在这种情况下,您可以使用Logstash(Elasticsearch / Logstash / Kibana堆栈的一部分)来收集,聚合和解析数据,然后让Logstash将此数据提供给Elasticsearch。
- 您有分析/商业智能需求,并希望快速调查,分析,可视化并询问有关大量数据的特定问题。使用Elasticsearch存储数据,然后使用Kibana(Elasticsearch / Logstash / Kibana堆栈的一部分)构建自定义仪表板,以便可视化数据
版本特征
Shay Banon在2010年2月发布了Elasticsearch的第一个版本。
2.x (2015)
- doc_values 排序聚合支持,默认开启
- Mapping 变化 字段名不要包含 dot 、type 不长于255字符等
- Filtered Query deprecated
5.x ( 2016) ES官方在5.x时代统一了 ELK体系的版本号
支持Lucene6版本,其中最重要的特性就是 Dimensional Point Fields, “磁盘空间少一半;索引时间少一半;” ,Merge 时间和 JVM Heap 占用都会减少,索引本身的性能也提升。
“查询性能提升25%;IPV6也支持了
ProfileAPI、ShrinkAPI、RolloverAPI、ReindexAPI
Search After ,search 接口的一个新实现,使得你可以深度翻页。这个弥补了 scroll 和 search 的不足
String类型被text/keyword 两个类型取代,分别代表分词和部分词
索引级别设置不能再写到yml配置文件,需要为每个索引单独设置或写到模板中
TaskManager,重建索引等任务被管理,可以观察任务状态
6.x (2017)
- 每个索引支持一个_type
- 默认禁用_all字段
- 优化了doc_values,占用磁盘空间更少,读写速度更快
- 模板规则定义方式由template改为index_patterns
- 增加序列ID,加快索引恢复速度
7.x(2019)
- 查询相关性速度优化 Weak-AND算法在Term Query查询场景有3700%的性能提升。
- 引入新的集群协调子系统
- 默认分片数不再是5,而是1
- 安装包自带JDK环境
- 集群中默认节点名字不再随机提供,改为获取hostname
- mapping与query阶段不再支持多type操作
初识Elasticsearch
基于Elasticsearch 6.x
基本概念
-
Elasticsearch is a near real time search platform. What this means is there is a slight latency (normally one second) from the time you index a document until the time it becomes searchable.
Elasticsearch是一个近乎实时的搜索平台。这意味着从索引文档到可搜索文档的时间有一点延迟(通常是一秒)
-
A cluster is a collection of one or more nodes (servers) that together holds your entire data and provides federated indexing and search capabilities across all nodes.
集群是一个或多个节点(服务器)的集合,它们共同保存您的整个数据,并提供跨所有节点的联合索引和搜索功能
-
A node is a single server that is part of your cluster, stores your data, and participates in the cluster’s indexing and search capabilities.
节点是作为群集一部分的单个服务器,存储数据并参与群集的索引和搜索功能。
-
An index is a collection of documents that have somewhat similar characteristics
索引是具有某些类似特征的文档集合。
-
A type used to be a logical category/partition of your index to allow you to store different types of documents in the same index
一种类型,曾经是索引的逻辑类别/分区,允许您在同一索引中存储不同类型的文档. Deprecated in 6.0.0.
-
A document is a basic unit of information that can be indexed. This document is expressed in JSON (JavaScript Object Notation) which is a ubiquitous internet data interchange format.Within an index/type, you can store as many documents as you want. Note that although a document physically resides in an index, a document actually must be indexed/assigned to a type inside an index.
文档是可以编制索引的基本信息单元。该文档以JSON(JavaScript Object Notation)表示,JSON是一种普遍存在的互联网数据交换格式。
-
- Sharding is important for two primary reasons:
- It allows you to horizontally split/scale your content volume
- It allows you to distribute and parallelize operations across shards (potentially on multiple nodes) thus increasing performance/throughput
- Replication is important for two primary reasons:
- It provides high availability in case a shard/node fails. For this reason, it is important to note that a replica shard is never allocated on the same node as the original/primary shard that it was copied from.
- It allows you to scale out your search volume/throughput since searches can be executed on all replicas in parallel.
分片: 水平扩展、提高并发度
副本: 高可用(副本不会在同个节点上)、提高并发度
关系图
- Sharding is important for two primary reasons:
集群健康度
- Green - everything is good (cluster is fully functional)
- Yellow - all data is available but some replicas are not yet allocated (cluster is fully functional)
- Red - some data is not available for whatever reason (cluster is partially functional)
集群节点角色
主节点(Master node)
The master node is responsible for lightweight cluster-wide actions such as creating or deleting an index, tracking which nodes are part of the cluster, and deciding which shards to allocate to which nodes. It is important for cluster health to have a stable master node.
Indexing and searching your data is CPU-, memory-, and I/O-intensive work which can put pressure on a node’s resources. To ensure that your master node is stable and not under pressure, it is a good idea in a bigger cluster to split the roles between dedicated master-eligible nodes and dedicated data nodes.
To prevent data loss, it is vital to configure the
discovery.zen.minimum_master_nodes
setting (which defaults to1
) so that each master-eligible node knows the minimum number of master-eligible nodes that must be visible in order to form a cluster.This setting should be set to a quorum of master-eligible nodes:
(master_eligible_nodes / 2) + 1
负责集群层面的相关操作,管理集群变更.也可以作为数据节点,但尽可能做少量的工作,尽量分离主节点和数据节点,同时为了防止网络分区时多主的情况(脑裂),需要设置有资格成为主节点的数量.
数据节点(Data node)
Data nodes hold the shards that contain the documents you have indexed. Data nodes handle data related operations like CRUD, search, and aggregations. These operations are I/O-, memory-, and CPU-intensive. It is important to monitor these resources and to add more data nodes if they are overloaded.
负责保存数据、执行数据相关操作:CRUD、搜索、聚合等.
预处理节点(Ingest node)
Ingest nodes can execute pre-processing pipelines, composed of one or more ingest processors. Depending on the type of operations performed by the ingest processors and the required resources, it may make sense to have dedicated ingest nodes, that will only perform this specific task.
5.0引入.预处理操作允许在索引文档之前,即写入数据之前.通过事先定义好的一系列processors和pipeline,对数据进行某种转换、富化. 拦截bluk和index请求
协调节点(Coordinating node)
If you take away the ability to be able to handle master duties, to hold data, and pre-process documents, then you are left with a coordinating node that can only route requests, handle the search reduce phase, and distribute bulk indexing. Essentially, coordinating only nodes behave as smart load balancers.
协调节点将请求转发给保存数据的节点,每个数据节点在本地执行请求,并将结果返回协调节点.协调节点收集完数据后,将每个数据节点的结果合并为单个全局结果.对结果手机和排序的过程可能需要很多CPU和内存资源(协调节点过多也会成为负担,主节点必须等待各节点集群状态更新)
部落节点(Tribe node)
A tribe node, configured via the
tribe.*
settings, is a special type of coordinating only node that can connect to multiple clusters and perform search and other operations across all connected clusters.允许部落节点在多个集群间充当联合客户端
By default a node is a master-eligible node and a data node, plus it can pre-process documents through ingest pipelines. This is very convenient for small clusters but, as the cluster grows, it becomes important to consider separating dedicated master-eligible nodes from dedicated data nodes.
node.master: true
node.data: true
node.ingest: true
search.remote.connect: true
内部模块简介
Cluster
Cluster模块是主节点执行集群管理的封装实现,管理集群状态,维护集群层面的配置信息.
主要功能如下:
- 管理集群状态
- 调用allocation模块执行分片分配,决策哪些分片应该分配到哪个节点
- 在集群各节点中直接迁移分片,保持数据平衡
allocation
封装了分片分配相关的功能和策略,包括主分片的分配和副分配的分配,本模块由主节点调用.
创建新索引、集群完全重启都需要分片分配的过程.
Discovery
发现模块负责发现集群中的节点,以及选举主节点.当节点加入或退出集群时,主节点回采取相应的行动(类似Zookeeper)
gateway
负责对收到Master广播下看来对集群状态(cluster state)数据持久化存储,并在集群完全重启时恢复它们
indices
索引模块管理全局级的索引设置,不包含索引级的(索引设置分为全局级和每个索引级)
它还封装了索引数据恢复功能.集群启动阶段需要主分片恢复和副分片恢复就是在这个模块实现的.
HTTP
允许通过HTTP的方式访问ES的API,HTTP模块本质上是完全异步的,解决了C10K问题(10K量级的并发连接),部分场景可以考虑使用HTTP keepalive提升性能
Transport
传输模块用于集群内节点之间的内部通信.传输本质也是完全异步的,使用TCP通信,每个节点都与其他节点维持若干TCP长连接.
Engine
Engine模块封装了对Lucene的操作以及translog的调用,它是对一个分片读写操作的最终提供者
Es使用Guice框架(Google开发的轻量级依赖注入框架IoC)进行模块画管理
集群启动流程
选举主节点
选主是对Bully算法的改进,主要思路是对节点 ID 排序,取最大值做 master,每个节点都运行这个流程。
- 参数人数过半
- 得票数过半
- 探测节点离开时,判断当前节点过半
选举集群元信息
被选出的 Master 和集群元信息的新旧程度没有关系。因此他的第一个任务是选举元信息, 让各节点把其各自存储的元信息发过来,根据版本号确定最新的元信息,然后把这个信息广播下去,这样,集群的所有节点都有了最新的元信息。
元信息的选举包括两个级别的:集群级和索引级。
allocation 过程
选举 shard 级元信息,构建路由表,是在 allocation 模块完成的。初始阶段,所有的 shard 都处于UNASSIGNED状态。此时,首先要做的是分配主分片。
index recovery
主分片 recovery
对于主分片来说,这些未刷盘数据可以从 translog 恢复,每次刷盘完毕,translog 都会被清空,因此把 translog 中的数据全部重放,建立 lucene 索引,如此完成主分片的 recovery。
副分片 recovery
副分片需要恢复成与主分片一致,同时,恢复期间允许新的索引操作。因此在主分片所在节点,调用 lucene 接口把 shard 做快照。恢复进入:
- 第一阶段:把 shard 数据拷贝到副本节点。如果主副两 shard 有相同的 syncid 且 doc 数相同,则跳过这个阶段。在第一阶段完毕前,会向副分片阶段发送告知对方启动 engine,在第二阶段开始之前,副分片就可以正常处理写请求了。
- 第二阶段:对 translog 做快照,这个快照里包含从第一个节点开始的新增索引.
写流程
基本流程
新建、索引和删除 请求都是 写 操作, 必须在主分片上面完成之后才能被复制到相关的副本
详细流程
读流程
GET流程
整体分为五个阶段:准备集群信息,内容路由,协调请求,数据读取,回复客户端。
Search流程
索引和搜索
ES中的数据可以分成两类 : 精确值和全文(mapping中指定类型)
- 精确值 , 日期和用户id、IP地址等
- 全文 , 指文本内容,日志或邮件内容 (会经过分析器 , 字符过滤器、分词器Tokenizer、Tonken过滤器、语言处理, 生成词Term ,生成倒排和正排索引)
搜索流程
增删改查操作只对单个文档进行处理,通常由 _index, _type, 和 _id三元组来确定唯一文档。但搜索需要一种更复杂的模型,因为不知道查询会命中哪些文档。一个搜索请求必须询问指定索引的所有分片中的某个副本来进行匹配。假设一个索引有5个主分片,1个副本分片,共10个分片,一次搜索请求会由5个分片来共同完成,他们有可能是主分片,也可能是副分片。也就是说,一次搜索请求只会命中所有副本中的一个。
找到匹配文档仅仅完成了一半,多分片中的结果必须组合成单个排序列表。集群的任意节点都可以接受搜索请求,接收客户端请求的节点成为协调节点,在协调节点,搜索任务被执行成一个两阶段过程,称之为 query then fetch 。 真正执行搜索任务的节点暂且称为数据节点。
相关优化
官方: https://www.elastic.co/guide/en/elasticsearch/reference/current/how-to.html
写入速度优化
综合来说提升写入速度从以下几方面入手:
加大translog flush间隔 ,目的降低iops、writeblock
允许接受部分数据丢失,可以调整translog持久化策略的周期性和大小(Es2.x 开始,默认配置为每次请求都“flush”)
index.translog.durability : async Index.translog.sync_interval : 5s Index.translog.flush_threshod_size : 512mb
加大index refresh间隔,除了降低I/O,更重要的是降低了segment merge频率
每次索引refresh会产生一个新的Lucene段,这会导致频繁的segment merge(I/O和内存占用都比较高)行为
index.refresh_interval : 1s
调整bluk请求
- bulk线程池和队列(建立索引属于计算密集型)
- 并发执行bulk请求(瓶颈在CPU)
为避免给集群带来内存压力,每个请求最好避免超过几十兆字节
优化磁盘间的任务均匀情况,将shard尽量均匀分布在物理主机的各个磁盘
- 简单轮询 : 在系统初始化阶段,简单轮询的效果是最均匀的
- 基于可用空间的动态加权轮询 : 以可用空间作为权重,在磁盘之间加权轮询
优化节点间的任务分布,将任务尽量均匀地发到各节点
数据写入客户端应该把bulk请求轮询发送到各个节点
优化Lucene层建立索引过程,目的降低CPU占用率及I/O,例如禁用_all字段
- 自动生成doc ID
- 调整字段Mappings
- 减少字段数量
- 减少建立索引的字段
- 减少字段内容
- 使用不同分析器(analyzer)
- 调整_source字段
- 禁用_all字段
- 对Analyzed字段禁用Norms(评分)
- index_options设置
搜索速度优化
- 为文件系统cache预留足够的内存 (第一性能因子)
- 使用更快的硬件
- 搜索尽可能少的字段
- 预索引数据
- 预热 (全局预热、文件系统)
- 副本(ARS 一主二副)
- 冷热分离(通过索引区分冷、热数据)
- 模型设计(仅需要索引的字段放在es,完整数据放在Hbase)
- 分页优化(不允许深度分页,使用scroll api)
现在假设你有一个2分片索引和两个节点。在一种情况下,副本的数量是0,这意味着每个节点拥有一个分片。在第二种情况下,副本的数量是1,这意味着每个节点具有两个分片。哪种设置在搜索性能方面表现最佳?通常,每个节点总共具有较少分片的设置将表现得更好。原因是它为每个分片提供了更大的可用文件系统缓存份额,而文件系统缓存可能是Elasticsearch的第一性能因子。同时,请注意,在单节点发生故障的情况下,没有副本的设置会出现故障,因此在吞吐量和可用性之间需要进行权衡。
参考:
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 951488791@qq.com