# ElasticSearch基本概念 结合官网资料,做了更详细的实际使用总结。 从单机版安装到集群高可用生产环境搭建、基本概念(索引,分片,节点,倒排索引…)、DSL语法实践、分词器(内置+中文)、SpringBoot整合实战。 ## 1.简介 Elasticsearch是一个基于Lucene的搜索服务器。提供了一个分布式多用户能力的全文搜索引擎 * 基于Restful web接口。 * Java语言开发的 Elasticsearch的功能 * 分布式的文档存储引擎 * 分布式的搜索引擎和分析引擎 * 分布式,支持PB级数据 * 全文检索,结构化检索,数据分析 * 对海量数据进行近实时的处理 相关网站: * 官网:[传送门](https://www.elastic.co/) * 官网文档:[传送门](https://www.elastic.co/guide/index.html) * 中文手册:[传送门](https://www.elastic.co/guide/cn/elasticsearch/guide/current/index.html) * 中文社区:[传送门](https://elasticsearch.cn/) * Jave-Client :[传送门](https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.x/java-rest-high-create-index.html) ## 2.索引(Index) 索引是文档(Document)的容器,可以理解为是文档的集合。 * 索引相当于SQL中的一个数据库(Database) * 必须为全小写字符 * 一个索引可以有多个文档(Document) 下图是包含大写报错提示 ![](https://img.kancloud.cn/a8/c8/a8c89b71e4fc48f1370017e0c5b27824_1166x304.png) ## 3.类型(Type) * 类似为关系数据库中Table * 每个索引下可以建立多个类型,文档存储时需要指定index和type。 * 从6.0.0开始单个索引中只能有一个类型,7.0.0以后将将不建议使用,8.0.0 以后完全不支持。 下图示例在7.x版本中创建一个有type ![](https://img.kancloud.cn/5b/e2/5be2173673a5ecc03ddf6849fd93f1a0_2608x692.png) 返回的错误提示大概含义是: 弃用:\[删除类型\]不建议在文档索引请求中指定类型,请改用无类型端点 (/ {index} / \_ doc / {id},/ {index} / \_ doc或/ {index} / \_ create / {id} )。 查询的时候也会给提示 ![](https://img.kancloud.cn/74/db/74db86929f12f4eebb439747b1865caa_2668x748.png) ##### 弃用type原因: 一般把Index比作 SQL 的 Database,Type比作SQL的Table。 但这并不准确,因为如果在SQL中,Table 之前相互独立,同名的字段在两个表中毫无关系。 在ES中,同一个Index 下不同的 Type 如果有同名的字段,会被 Luecence 当作同一个字段 ,并且他们的定义必须相同。所以我觉得Index现在更像一个表,而Type字段并没有多少意义。 目前Type已经被Deprecated,在7.0开始,一个索引只能建一个Type为`_doc` ## 4.文档(Document) 索引Index里面单条的记录称为Document,等同于关系型数据库表中的行。 ![](https://img.kancloud.cn/e5/db/e5dbe1b3490146fecca49e951ce96eed_1634x596.png) *参数说明* | **参数** | **含义** | | --- | --- | | \_index | 文档所属索引名称 | | \_type | 文档所属类型名 | | \_id | 主键ID,可指定该值,若不指定则自动生成一个唯一的UUID | | \_version | 文档的版本信息,通过使用version来保证对文档的变更能以正确的顺序执行,避免乱序造成的数据丢失。 | | \_seq\_no | 严格递增的顺序号,每个文档一个Shard级别严格递增,保证后写入的Doc的\_seq\_no大于先写入的Doc的\_seq\_no。可以理解为数据版本,可以用来控制并发修改 | | \_primary\_term | 与\_seq\_no一样是一个整数,每当Primary Shard发生重新分配时,比如重启,Primary选举等,\_primary\_term会递增1 | | found | 查到数据则为true, 查不到则为false | | \_source | 文档的原始JSON数据,存入的数据JSON化 | ## 5.分片(shard) **为了解决什么?** * 单台机器即使存储再大,达到一定程度后也会遇到瓶颈。分片(shard)是为了解决节点容量上限问题。 * 让搜索和分析等操作分布到多台服务器上执行,提升吞吐量和性能。 **如何解决?** * ElasticSearch可以将一个索引中的数据切分为多个分片(shard),分布到多台服务器上。 * 通过将index分为多个分片(默认是一个,也就是不分片)。 * 一个或多个node共同存储该index的所有数据实现水平拓展(类似于关系型数据库中的分表) * 它们共同持有该索引的所有数据,默认通过hash(文档id)决定数据的归属 索引分片(Sharding)是自动完成的,而且所有分片索引(Shard)是作为一个整体呈现给用户的。 需要注意的是,尽管索引分片这个过程是自动的,但是在应用中需要事先调整好参数。因为集群中分片的数量需要在索引创建前配置好,而且服务器启动后是无法修改的。 ## 6.分片副本(replicas) **存在的目的** * **服务高可用** * 若数据只有一份,若正好node节点挂了,那存在上面的数据就丢了。有了副本只要不是都挂了数据就不会丢 * 分片副本-不会与主分片在同一个节点上 * **提高吞吐量** * 通过在多个replicas上并行搜索提高搜索性能,replicas上的数据都是近实时的(near realtime),因此所有replicas都能提供搜索功能,通过设置合理的replicas数量可以极高的提高搜索吞吐量 注:如果设置了replicas=2,那么一条数据共有三份,一份primary shard主分片,另外两份replicas shard幅分片。这三个统一称为副本组。 索引副本(Replica)机制的的思路很简单: * 为索引分片创建一份新的拷贝,支持像原来的主分片一样处理用户搜索请求。多节点备份也防止了数据的丢失, * 索引副本可以随时添加或者删除,所以用户也可以在需要的时候动态调整其数量,尽量提前预设好。防止扩充数据量越大的时候引起CPU负载过高。 ## 7.分片设定 **前置设定很重要** * 对于生产环境中分片的设定,需要提前做好容量规划, * 主分片数是在索引创建时预先设定的,后续无法修改。 **分片数设置过小问题** * 导致后续无法增加节点进行水平扩展。 * 导致分片的数据量太大,数据在重新分配时耗时; **分片数设置过大问题** * 影响搜索结果的相关性打分,影响统计结果的准确性; * 单个节点上过多的分片,会导致资源浪费,同时也会影响性能; 最大节点数建议公式 ~~~bash Max number of nodes = Number of shards * (number of replicas +1) ~~~ 例如:如果你计划用10个分片和2个分片副本,那么最大的节点数是30。 ## 8.倒排索引 **ElasticSearch**的搜索功能是基于[lucene](https://so.csdn.net/so/search?q=lucene&spm=1001.2101.3001.7020)。 lucene搜索的基本原理就是倒叙索引,倒序排序的结果跟分词的类型有关。 在**ElasticSearch**中,每个文档都有一个对应的文档 ID,文档内容被表示为一系列关键词的集合。 **例如:** 某文档经过分词,提取了 n 个关键词,每个关键词都会记录它在文档中出现的次数和出现位置。 **倒排索引:** 就是关键词到文档 ID 的映射,每个关键词都对应着一系列的文件,这些文件中都出现了关键词。 **案例:** 有如下3个文档 | **文档ID** | **文档内容** | | --- | --- | | 1 | 我是张三 | | 2 | 张三的成绩单 | | 3 | 张三的午餐 | 对文档进行分词后,得到倒排索引 注意:以下示例未严格按照字典顺序排列,不同的分词器,可能分的结果不一致,仅做示例参考 | **单词ID** | **单词内容(拆分的词语)** | **文档ID集** | | --- | --- | --- | | 1 | 我 | 1 | | 2 | 是 | 1 | | 3 | 张 | 1,2,3 | | 4 | 三 | 1,2,3 | | 5 | 的 | 2,3 | | 6 | 成绩单 | 2 | | 8 | 午餐 | 3 | 实际ES的倒排索引还可以记录更多的信息,比如 * 文档频率信息 * 在文档集合中有多少个文档包含某个单词 有了倒排索引,搜索引擎可以很方便地响应用户的查询。 **例如:一次简单的搜索流程,假设我们搜索"张三",搜索流程会是这样** * 分词,分词插件将句子分为2个term “张”,“三” * 将这2个term拿到倒叙索引中去查找,如果匹配到了就拿对应的文档id,获得文档内容,这些文档就是提供给用户的搜索结果。 **注:** * 倒排索引中的所有词项对应一个或多个文档 * 倒排索引中的词项根据字典顺序升序排列 ## 9.服务集群 **ElasticSearch集群的特性** * 高可用性 * 在服务上允许有节点停止服务; * 在数据上部分节点丢失,不会丢失数据; * 可扩展性 * 随着请求量的不断提升,数据量的不断增长,系统可以将数据分布到其他节点,实现水平扩展; **ElasticSearch集群健康值** * `绿色-green`:所有主分片和副本分片都可用 * `黄色-yellow`:所有主分片可用,部分副本分片都可用 * `红色-red`:部分主分片可用 注:当集群状态为 red,仍然可正常提供服务,会在现有存活分片中执行请求。需尽快修复故障分片,防止数据丢失 ## 10.服务节点(Node) * 节点是一个ElasticSearch的实例,其本质就是一个Java进程; * 一台机器上可以运行多个ElasticSearch实例,但是建议在生产环境中一台机器上只运行一个ElasticSearch实 * Node 是组成集群的一个单独的服务器,用于存储数据并提供集群的搜索和索引功能。与集群一样。