这篇文章主要介绍 ElasticSearch 的基本概念,学习文档、索引、集群、节点、分片等概念,同时会将 ElasticSearch 和关系型数据库作简单的类比,还会简单介绍 REST API 的使用用法。html
索引和文档是偏向于逻辑上的概念,节点和分片更偏向于物理上的概念。node
首先来讲下什么是文档:数据库
ElasticSearch(简称 ES) 是面向文档的,文档是全部可搜索数据的最小单位。api
给你们举几个例子,让你们更形象地理解什么是文档:数组
你们能够把文档理解为关系型数据库中的一条记录。服务器
在 ES 中文档会被序列化成 JSON 格式,保存在 ES 中,JSON 对象由字段组成,其中每一个字段都有对应的字段类型(字符串/数组/布尔/日期/二进制/范围类型)。数据结构
在 ES 中,每一个文档都有一个 Unique ID,能够本身指定 ID 或者经过 ES 自动生成。架构
在上一篇文章手把手教你搭建 ELK 实时日志分析平台中,咱们讲到了经过 Logstash 向 ES 中导入数据,其中部分测试数据集和对应的转换后的格式以下所示:app
movieId,title,genres 193585,Flint (2017),Drama 193587,Bungo Stray Dogs: Dead Apple (2018),Action|Animation 193609,Andrew Dice Clay: Dice Rules (1991),Comedy
咱们从测试数据集 csv 文件中读取一个个的 RowData 的电影数据,而后经过 Logstash 转换进行转化之后进入到 ES 中就是 JSON 格式。运维
JSON 每一个字段都有本身的数据类型,ES 能够帮助你自动作作一个数据类型的推算,而且在 ES 中数据还支持数组和嵌套。
每个文档都有对应的元数据,用于标注文档的相关信息,咱们来了解下元数据都有什么内容:
{ "_index" : "movies", "_type" : "_doc", "_id" : "2035", "_score" : 1.0, "_source" : { "title" : "Blackbeard's Ghost", "genre" : [ "Children", "Comedy" ], "id" : "2035", "@version" : "1", "year" : 1968 } }
其中,_index
表明文档所属的索引名;_type
表示文档所属的类型名;_id
为文档惟一 id;_source
为文档的原始 JSON 数据,当搜索文档的时候默认返回的就是 _source
字段;@version
为文档的版本信息,能够很好地来解决版本冲突的问题;_score
为相关性打分,是这个文档在此次查询中的算分。
介绍完文档后,让咱们来看下索引:
索引简单来讲就是类似结构文档的集合,好比能够有一个客户索引,商品分类索引,订单索引,索引有一个名称,一个索引能够包含不少文档,一个索引就表明了一类相似的或者相同的文档,好比说创建一个商品索引,里面可能就存放了全部的商品数据,也就是全部的商品文档。每个索引都是本身的 Mapping 定义文件,用来去描述去包含文档字段的类型,分片(Shard)体现的是物理空间的概念,索引中的数据分散在分片上。
在一个的索引当中,能够去为它设置 Mapping 和 Setting,Mapping 定义的是索引当中全部文档字段的类型结构,Setting 主要是指定要用多少的分片以及数据是怎么样进行分布的。
索引在不一样的上下文会有不一样的含义,好比,在 ES 当中,索引是一类文档的集合,这里就是名词;同时保存一个文档到 ES 的过程也叫索引(indexing),抛开 ES,提到索引,还有多是 B 树索引或者是倒排索引,倒排索引是 ES 中一个重要的数据结构,会在之后的文章进行讲解。
接下来对类型进行讲解:
在 7.0 以前,每个索引是能够设置多个 Types 的,每一个 Type 会拥有相同结构的文档,可是在 6.0 开始,Type 已经被废除,在 7.0 开始,一个索引只能建立一个 Type,也就是 _doc
。
每一个索引里均可以有一个或多个 Type,Type 是索引中的一个逻辑数据分类,一个 Type 下的文档,都有相同的字段(Field),好比博客系统,有一个索引,能够定义用户数据 Type,博客数据 Type,评论数据 Type 等。
到此为止,咱们学习了文档、索引以及类型的概念,接下来学习什么是集群?什么是节点?什么是分片?
首先来看下集群的概念。
ES 集群实际上是一个分布式系统,要知足高可用性,高可用就是当集群中有节点服务中止响应的时候,整个服务还能正常工做,也就是服务可用性;或者说整个集群中有部分节点丢失的状况下,不会有数据丢失,即数据可用性。
当用户的请求量愈来愈高,数据的增加愈来愈多的时候,系统须要把数据分散到其余节点上,最后来实现水平扩展。当集群中有节点出现问题的时候,整个集群的服务也不会受到影响。
ES 的分布架构当中,不一样的集群是经过不一样的名字来区分的,默认的名字为 elasticsearch
,能够在配置文件中进行修改,或者在命令行中使用 -E cluster.name=wupx
进行设定,一个集群中能够有一个或者多个节点。
一个 ES 集群有三种颜色来表示健康程度:
了解完集群,那么就来看下什么是节点。
节点其实就是一个 ES 实例,本质上是一个 Java 进程,一台机器上能够运行多个 ES 进程,可是生产环境通常建议一台机器上只运行一个 ES 实例。
每个节点都有本身的名字,节点名称很重要(在执行运维管理操做的时候),能够经过配置文件进行配置,或者启动的时候 -E node.name=node1
指定。每个节点在启动以后,会分配一个 UID,保存在 data 目录下。
默认节点会去加入一个名称为 elasticsearch
的集群,若是直接启动不少节点,那么它们会自动组成一个 elasticsearch
集群,固然一个节点也能够组成一个 elasticsearch
集群。
每个节点启动后,默认就是一个 Master-eligible 节点,能够经过在配置文件中设置 node.master: false
禁止,Master-eligible 节点能够参加选主流程,成为 Master 节点。当第一个节点启动时候,它会将本身选举成 Master 节点。
每一个节点上都保存了集群的状态,只有 Master 节点才能修改集群的状态信息,若是是任意节点都能修改信息就会致使数据的不一致性。
集群状态(Cluster State),维护一个集群中必要的信息,主要包括以下信息:
下面咱们来看下什么是 Data Node 和 Coordinating Node?
顾名思义,能够保存数据的节点叫做 Data Node,负责保存分片上存储的全部数据,当集群没法保存现有数据的时候,能够经过增长数据节点来解决存储上的问题,在数据扩展上有相当重要的做用。
Coordinating Node 负责接收 Client 的请求,将请求分发到合适的节点,最终把结果聚集到一块儿返回给客户端,每一个节点默认都起到了 Coordinating Node 的职责。
还有其余的节点类型,你们能够了解下:
每一个节点在启动的时候会经过读取 elasticsearch.yml
配置文件决定本身承担什么样的角色,那么让咱们看下配置节点类型吧!
开发环境中一个节点能够承担多种角色。
生产环境中,应该设置单一的角色的节点(dedicated node)。
讲完节点,让咱们来看下什么是分片?
因为单台机器没法存储大量数据,ES 能够将一个索引中的数据切分为多个分片(Shard),分布在多台服务器上存储。有了分片就能够横向扩展,存储更多数据,让搜索和分析等操做分布到多台服务器上去执行,提高吞吐量和性能。
索引与分片的关系如上图所示,一个 ES 索引包含不少分片,一个分片是一个 Lucene 的索引,它自己就是一个完整的搜索引擎,能够独立执行创建索引和搜索任务。Lucene 索引又由不少分段组成,每一个分段都是一个倒排索引。 ES 每次 refresh 都会生成一个新的分段,其中包含若干文档的数据。在每一个分段内部,文档的不一样字段被单独创建索引。每一个字段的值由若干词(Term)组成,Term 是原文本内容通过分词器处理和语言处理后的最终结果(例如,去除标点符号和转换为词根)。
分片分为两类,一类为主分片(Primary Shard),另外一类为副本分片(Replica Shard)。
主分片主要用以解决水平扩展的问题,经过主分片,就能够将数据分布到集群上的全部节点上,一个主分片就是一个运行的 Lucene 实例,当咱们在建立 ES 索引的时候,能够指定分片数,可是主分片数在索引建立时指定,后续不容许修改,除非使用 Reindex 进行修改。
副本分片用以解决数据高可用的问题,也就是说集群中有节点出现硬件故障的时候,经过副本的方式,也能够保证数据不会产生真正的丢失,由于副本分片是主分片的拷贝,在索引中副本分片数能够动态调整,经过增长副本数,能够在必定程度上提升服务查询的性能(读取的吞吐)。
下面经过一个例子来理解下主分片和副本分片是怎么样把数据分散在集群不一样的节点上的:
PUT /blogs { "settings" :{ "number_of_shards" : 3, "number_of_repicas" : 1 } }
上面是 blogs 索引的定义,其中 settings
中的 number_of_shards
表示主分片数为 3,number_of_repicas
表示副本只有 1 份。
上图为 wupx 的一个集群,里面总共有 3 个节点,经过上面对索引 blogs 的配置,当有数据进来的时候,ES 内部就会把主分片分散在三个节点上,同时把每一个分片的副本分散到其余节点上,当集群中有节点出现故障,ES 内部就会产生故障转移的机制,故障转移机制会在之后的文章进行讲解,在上图中能够看到三个主分片被分散到三个节点上,若在这个时候为集群增长一个节点,是否能够增长系统的可用性呢?
带着这个问题,咱们先看下分片的设定:
分片的设定在生产环境中是十分重要的,不少时候须要提早作好容量规划,由于主分片在索引建立的时候须要预先设定的,而且在过后没法修改,在前面的例子中,一个索引被分红了 3 个主分片,这个集群即使增长再多节点,索引也只能分散在 3 个节点上。
分片设置过大的时候,也会带来反作用,一方面来讲会影响搜索结果的打分,影响统计结果的准确性,另外,单个节点上过多的分片,也会致使资源浪费,同时也会影响性能。从 7.0 版本开始,ES 的默认主分片数设置从 5 改成了 1,从这个方面也能够解决 over-sharding 的问题。
在了解完 ES 的术语后,来和咱们熟悉的关系型数据库作个类比,以便于咱们理解。
我相信你们对关系型数据库(简称 RDBMS)应该比较了解,所以接下来拿关系型数据库和 ES 作一个类比,让你们更容易理解:
从表中,不难看出,关系型数据库和 ES 有以下对应关系:
当进行全文检索或者对搜索结果进行算分的时候,ES 比较合适,但若是对数据事务性要求比较高的时候,会把关系型数据库和 ES 结合使用。
为了方便其余语言的整合,ES 提供了 REST API 来给其余程序进行调用,当咱们的程序要和 ES 进行集成的时候,只须要发出 HTTP 的请求就会获得相应的结果,接下来对基本的 API 进行介绍:
打开 Kibana,咱们首先打开 Kibana 的管理菜单(Management),其中提供索引管理功能,能够看到索引管理中有 movies 索引,为上篇文章中导入的,点击索引,能够看到索引的 Setting 和 Mapping 信息,如何对其进行设置会在以后的文章会进行介绍。
言归正传,来给你们看 REST API:
接下来打开 Kibana 的开发工具(Dev Tools),movies 为索引,如今输入 GET movies
点击执行,就能够查看电影索引相关的信息,主要包含索引的 Mapping 和 Setting。
输入 GET movies/_count
点击执行,就能够看到索引的文档总数,运行结果以下:
{ "count" : 9743, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 } }
输入以下代码
POST movies/_search { }
点击执行,就能够查看前 10 条文档,了解文档格式。
还能够对索引的名字进行通配符查询,使用 GET /_cat/indices/mov*?v&s=index
,能够查看匹配的索引。
使用 GET /_cat/indices?v&s=docs.count:desc
,能够按照文档个数排序。
使用 GET /_cat/indices?v&health=green
,能够查看状态为 green 的索引。
使用 GET /_cat/indices?v&h=i,tm&s=tm:desc
,能够查看每一个索引占用的内存。
ES 还提供了 API 去查看集群的健康情况,使用 GET _cluster/health
能够集群的健康情况,返回结果以下:
{ "cluster_name" : "wupx", "status" : "green", "timed_out" : false, "number_of_nodes" : 2, "number_of_data_nodes" : 2, "active_primary_shards" : 10, "active_shards" : 10, "relocating_shards" : 0, "initializing_shards" : 0, "unassigned_shards" : 0, "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" : 100.0 }
能够看到集群名字叫 wupx,集群状态是 green,一共有 2 个节点,这两个节点都是承担 Data Node 角色,另外还有 10 个主分片。
REST API 就介绍到这里,其他的你们能够本身去摸索下。
细心的小伙伴会发现 Kibana 怎么变成中文界面了,其实 Kibana 在 7.0 版本以后,官方自带汉化资源文件(位于 Kibana 目录下的
node_modules/x-pack/plugins/translations/translations/
),你们能够在 config 目录下修改kibana.yml
文件,在文件中加上配置项i18n.locale: "zh-CN"
,而后从新启动 Kibana 就汉化完成了。
本文主要学习了文档、索引、集群、节点等概念,了解到每一个集群中每一个节点能够承担不一样的角色,还了解了什么是主分片和副本分片以及它们在分布式系统中起到的做用,还经过和关系型数据库作类比,让你们更易理解,另外还介绍了 REST API 使用,最后给你们一份本身总结的 ES 术语思惟导图,思惟导图源文件能够在公众号武培轩回复es获取。
参考文献
《Elasticsearch技术解析与实战》
《Elasticsearch源码解析与优化实战》
Elasticsearch核心技术与实战
Elasticsearch顶尖高手系列
https://www.elastic.co/guide/en/elasticsearch/reference/7.1/index.html