elasticsearch干什么的,elasticsearch适合做什么

首页 > 经验 > 作者:YD1662022-11-04 04:20:30

Text 用于索引全文值的字段,例如电子邮件正文或产品说明。这些字段是被分词的,它们通过分词器传递 ,以在被索引之前将字符串转换为单个术语的列表。

分析过程允许 Elasticsearch 搜索单个单词中每个完整的文本字段。文本字段不用于排序,很少用于聚合。

Keyword 用于索引结构化内容的字段,例如电子邮件地址,主机名,状态代码,邮政编码或标签。它们通常用于过滤,排序,和聚合。Keyword 字段只能按其确切值进行搜索。

通过对字段类型的了解我们知道有些字段需要明确定义的,例如某个字段是 Text 类型还是 Keyword 类型差别是很大的,时间字段也许我们需要指定它的时间格式,还有一些字段我们需要指定特定的分词器等等。

如果采用动态映射是不能精确做到这些的,自动识别常常会与我们期望的有些差异。

所以创建索引的时候一个完整的格式应该是指定分片和副本数以及 Mapping 的定义,如下:

PUT my_index
{
"settings" : {
"number_of_shards" : 5,
"number_of_replicas" : 1
}
"mappings": {
"_doc": {
"properties": {
"title": { "type": "text" },
"name": { "type": "text" },
"age": { "type": "integer" },
"created": {
"type": "date",
"format": "strict_date_optional_time||epoch_millis"
}
}
}
}
}
ES 的基本使用

在决定使用 Elasticsearch 的时候首先要考虑的是版本问题,Elasticsearch (排除 0.x 和 1.x)目前有如下常用的稳定的主版本:2.x,5.x,6.x,7.x(current)。

你可能会发现没有 3.x 和 4.x,ES 从 2.4.6 直接跳到了 5.0.0。其实是为了 ELK(ElasticSearch,Logstash,Kibana)技术栈的版本统一,免的给用户带来混乱。

在 Elasticsearch 是 2.x (2.x 的最后一版 2.4.6 的发布时间是 July 25, 2017) 的情况下,Kibana 已经是 4.x(Kibana 4.6.5 的发布时间是 July 25, 2017)。

那么在 Kibana 的下一主版本肯定是 5.x 了,所以 Elasticsearch 直接将自己的主版本发布为 5.0.0 了。

统一之后,我们选版本就不会犹豫困惑了,我们选定 Elasticsearch 的版本后再选择相同版本的 Kibana 就行了,不用担忧版本不兼容的问题。

Elasticsearch 是使用 Java 构建,所以除了注意 ELK 技术的版本统一,我们在选择 Elasticsearch 的版本的时候还需要注意 JDK 的版本。

因为每个大版本所依赖的 JDK 版本也不同,目前 7.2 版本已经可以支持 JDK11。

安装使用

elasticsearch干什么的,elasticsearch适合做什么(5)

①下载和解压 Elasticsearch,无需安装解压后即可用,解压后目录如上图:

②安装目录下运行 bin/elasticsearch来启动 ES。

③默认在 9200 端口运行,请求 curl http://localhost:9200/ 或者浏览器输入 http://localhost:9200,得到一个 JSON 对象,其中包含当前节点、集群、版本等信息。

{
"name" : "U7fp3O9",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "-Rj8jGQvRIelGd9ckicUOA",
"version" : {
"number" : "6.8.1",
"build_flavor" : "default",
"build_type" : "zip",
"build_hash" : "1fad4e1",
"build_date" : "2019-06-18T13:16:52.517138Z",
"build_snapshot" : false,
"lucene_version" : "7.7.0",
"minimum_wire_compatibility_version" : "5.6.0",
"minimum_index_compatibility_version" : "5.0.0"
},
"tagline" : "You Know, for Search"
}

集群健康状态

要检查群集运行状况,我们可以在 Kibana 控制台中运行以下命令 GET /_cluster/health,得到如下信息:

{
"cluster_name" : "wujiajian",
"status" : "yellow",
"timed_out" : false,
"number_of_nodes" : 1,
"number_of_data_nodes" : 1,
"active_primary_shards" : 9,
"active_shards" : 9,
"relocating_shards" : 0,
"initializing_shards" : 0,
"unassigned_shards" : 5,
"delayed_unassigned_shards" : 0,
"number_of_pending_tasks" : 0,
"number_of_in_flight_fetch" : 0,
"task_max_waiting_in_queue_millis" : 0,
"active_shards_percent_as_number" : 64.28571428571429
}

集群状态通过 绿,黄,红 来标识:

当集群状态为红色时,它将会继续从可用的分片提供搜索请求服务,但是你需要尽快修复那些未分配的分片。

ES 机制原理

ES 的基本概念和基本操作介绍完了之后,我们可能还有很多疑惑:

带着这些疑问我们进入接下来的内容。

写索引原理

下图描述了 3 个节点的集群,共拥有 12 个分片,其中有 4 个主分片(S0、S1、S2、S3)和 8 个副本分片(R0、R1、R2、R3),每个主分片对应两个副本分片,节点 1 是主节点(Master 节点)负责整个集群的状态。

elasticsearch干什么的,elasticsearch适合做什么(6)

写索引是只能写在主分片上,然后同步到副本分片。这里有四个主分片,一条数据 ES 是根据什么规则写到特定分片上的呢?

这条索引数据为什么被写到 S0 上而不写到 S1 或 S2 上?那条数据为什么又被写到 S3 上而不写到 S0 上了?

首先这肯定不会是随机的,否则将来要获取文档的时候我们就不知道从何处寻找了。

实际上,这个过程是根据下面这个公式决定的:

shard = hash(routing) % number_of_primary_shards

Routing 是一个可变值,默认是文档的 _id,也可以设置成一个自定义的值。

Routing 通过 Hash 函数生成一个数字,然后这个数字再除以 number_of_primary_shards(主分片的数量)后得到余数。

这个在 0 到 number_of_primary_shards-1之间的余数,就是我们所寻求的文档所在分片的位置。

这就解释了为什么我们要在创建索引的时候就确定好主分片的数量并且永远不会改变这个数量:因为如果数量变化了,那么所有之前路由的值都会无效,文档也再也找不到了。

由于在 ES 集群中每个节点通过上面的计算公式都知道集群中的文档的存放位置,所以每个节点都有处理读写请求的能力。

在一个写请求被发送到某个节点后,该节点即为前面说过的协调节点,协调节点会根据路由公式计算出需要写到哪个分片上,再将请求转发到该分片的主分片节点上。

elasticsearch干什么的,elasticsearch适合做什么(7)

假如此时数据通过路由计算公式取余后得到的值是 shard=hash(routing)%4=0

则具体流程如下:

存储原理

上面介绍了在 ES 内部索引的写处理流程,这个流程是在 ES 的内存中执行的,数据被分配到特定的分片和副本上之后,最终是存储到磁盘上的,这样在断电的时候就不会丢失数据。

具体的存储路径可在配置文件 ../config/elasticsearch.yml 中进行设置,默认存储在安装目录的 Data 文件夹下。

建议不要使用默认值,因为若 ES 进行了升级,则有可能导致数据全部丢失:

path.data: /path/to/data //索引数据
path.logs: /path/to/logs //日志记录

①分段存储

索引文档以段的形式存储在磁盘上,何为段?索引文件被拆分为多个子文件,则每个子文件叫作段,每一个段本身都是一个倒排索引,并且段具有不变性,一旦索引的数据被写入硬盘,就不可再修改。

在底层采用了分段的存储模式,使它在读写时几乎完全避免了锁的出现,大大提升了读写性能。

段被写入到磁盘后会生成一个提交点,提交点是一个用来记录所有提交后段信息的文件。

一个段一旦拥有了提交点,就说明这个段只有读的权限,失去了写的权限。相反,当段在内存中时,就只有写的权限,而不具备读数据的权限,意味着不能被检索。

段的概念提出主要是因为:在早期全文检索中为整个文档集合建立了一个很大的倒排索引,并将其写入磁盘中。

如果索引有更新,就需要重新全量创建一个索引来替换原来的索引。这种方式在数据量很大时效率很低,并且由于创建一次索引的成本很高,所以对数据的更新不能过于频繁,也就不能保证时效性。

索引文件分段存储并且不可修改,那么新增、更新和删除如何处理呢?

段被设定为不可修改具有一定的优势也有一定的缺点,优势主要表现在:

段的不变性的缺点如下:

②延迟写策略

介绍完了存储的形式,那么索引写入到磁盘的过程是怎样的?是否是直接调 Fsync 物理性地写入磁盘?

答案是显而易见的,如果是直接写入到磁盘上,磁盘的 I/O 消耗上会严重影响性能。

那么当写数据量大的时候会造成 ES 停顿卡死,查询也无法做到快速响应。如果真是这样 ES 也就不会称之为近实时全文搜索引擎了。

为了提升写的性能,ES 并没有每新增一条数据就增加一个段到磁盘上,而是采用延迟写的策略。

每当有新增的数据时,就将其先写入到内存中,在内存和磁盘之间是文件系统缓存。

当达到默认的时间(1 秒钟)或者内存的数据达到一定量时,会触发一次刷新(Refresh),将内存中的数据生成到一个新的段上并缓存到文件缓存系统 上,稍后再被刷新到磁盘中并生成提交点。

这里的内存使用的是 ES 的 JVM 内存,而文件缓存系统使用的是操作系统的内存。

新的数据会继续的被写入内存,但内存中的数据并不是以段的形式存储的,因此不能提供检索功能。

由内存刷新到文件缓存系统的时候会生成新的段,并将段打开以供搜索使用,而不需要等到被刷新到磁盘。

在 Elasticsearch 中,写入和打开一个新段的轻量的过程叫做 Refresh (即内存刷新到文件缓存系统)。

默认情况下每个分片会每秒自动刷新一次。这就是为什么我们说 Elasticsearch 是近实时搜索,因为文档的变化并不是立即对搜索可见,但会在一秒之内变为可见。

我们也可以手动触发 Refresh,POST /_refresh刷新所有索引,POST /nba/_refresh刷新指定的索引。

Tips:尽管刷新是比提交轻量很多的操作,它还是会有性能开销。当写测试的时候, 手动刷新很有用,但是不要在生产>环境下每次索引一个文档都去手动刷新。而且并不是所有的情况都需要每秒刷新。

可能你正在使用 Elasticsearch 索引大量的日志文件, 你可能想优化索引速度而不是>近实时搜索。

这时可以在创建索引时在 Settings 中通过调大 refresh_interval = "30s" 的值 , 降低每个索引的刷新频率,设值时需要注意后面带上时间单位,否则默认是毫秒。当refresh_interval=-1时表示关闭索引的自动刷新。

虽然通过延时写的策略可以减少数据往磁盘上写的次数提升了整体的写入能力,但是我们知道文件缓存系统也是内存空间,属于操作系统的内存,只要是内存都存在断电或异常情况下丢失数据的危险。

为了避免丢失数据,Elasticsearch 添加了事务日志(Translog),事务日志记录了所有还没有持久化到磁盘的数据。

elasticsearch干什么的,elasticsearch适合做什么(8)

上一页123下一页

栏目热文

文档排行

本站推荐

Copyright © 2018 - 2021 www.yd166.com., All Rights Reserved.