ElasticSearch 7.8.x技术整理4 – 高级篇( 续 )

0、前言

变更原由:昨晚更新博客之后,第一次出现有人看得到,有人又看不到,我也不知道我设置了什么地方,所以我把原博客删了,重新发布

另外:
其中一些理论与前面的知识点相关,所以我没有读过:我建议您看看其他三篇知识文章。

[En]

Some of these theories are linked to the previous knowledge points, so I haven’t read them: I suggest you take a look at the other three knowledge articles.

基础篇:https://www.cnblogs.com/xiegongzi/p/15684307.html
java操作篇:https://www.cnblogs.com/xiegongzi/p/15690534.html
高级篇1:https://www.cnblogs.com/xiegongzi/p/15757337.html

4.12、文档搜索

4.12.1、不可变的倒排索引

在以前的全文检索中,整个文档集合被创建为倒排索引,然后存储在磁盘上。当要创建新索引时,只要新索引准备就绪,旧索引就会被替换,以便可以检索最新的文档数据更改。

[En]

In the previous full-text retrieval, the entire document collection was made into an inverted index and then stored on disk. When a new index is to be created, as long as the new index is ready, the old index will be replaced, so that the most recent document data changes can be retrieved.

一旦将索引保存到磁盘,它就是不可变的(它永远不能被修改),这有以下好处:

[En]

Once the index is saved to disk, it is immutable (it can never be modified), and this has the following benefits:

  • 1、只要索引被读入到内存中了,由于其不变性,所以就会一直留在内存中( 只要空间足够 ),从而当我们做”读操作”时,请求就会进入内存中去,而不会去磁盘中,这样就减小开销,提高效率了
  • 2、索引放到内存中之后,是可以进行压缩的,这样做之后,也就可以节约空间了
  • 3、放到内存中后,是不需要锁的,如果自己的索引是长期不用更新的,那么就不用怕多进程同时修改它的情况了

当然:这种不变的倒排索引有其优点,但也必然有缺点。

[En]

Of course: this immutable inverted index has advantages, but it must have disadvantages.

  • 一成不变、不可修改,这是最大的劣势如果要重置可检索的索引,则需要重新构建整个索引。这会导致索引中的数据量很大(数据量有限),同时索引也会更新,所以频率会降低(是什么?关系表,大型表检索和更新数据是否有效?肯定不高,所以扩展了:变量指数)
    [En]

    immutable and unmodifiable, this is the biggest disadvantage. When you want to reset an index that can be retrieved, you need to reconstruct the entire index. This will result in a large amount of data in the index (the size of the data is limited), and the index will be updated at the same time, so the frequency will be reduced ( * what is it? Relational tables, is it efficient for a large table to retrieve and update data? It’s definitely not high, so it extends: variable index)

4.12.2、可变的倒排索引

又想保留不可变性,又想能够实现倒排索引的更新,咋办?

  • 就搞出了 补充索引所谓的补充索引:有点类似于日志这个玩意儿,当然和MySQL中INNODB下的ACID的A原子性的实现方式undo log日志更像,只是做的事情不一样。而ES中的补充索引就是重建一个索引,然后用来记录最近指定一段时间内的索引中文档数据的更新。这样更新的索引数据就记录在补充索引中了,然后检索数据时,直接找补充索引即可,这样检索时不再重写整个倒排索引了,这有点类似于关系型中的拆表,大表拆小表嘛, *但是啊:每一份补充索引都是一份单独的索引啊,这又和分片很像,可是:查询时是对这些补充索引进行轮询,然后再对结果进行合并,从而得到最终的结果,这和前面说过的读流程中说明的协调节点挂上钩了

这里还需要了解一个配套的 按段搜索 ,玩过 Lucene 的可能听过。按段,每段也就可以理解为:补充索引,它的流程其实也很简单:

  • 1、新文档被收集到内存索引缓存
  • 2、不时地提交缓存
  • 2.1、一个新的段,一个追加的倒排索引,被写入磁盘
  • 2.2、一个新的包含新段名字的提交点被写入磁盘
  • 2.3、磁盘进行同步,所有在文件系统缓存中等待的写入都刷新到磁盘,以确保它们被写入物理文件
  • 3、新的段被开启,让它包含的文档可见,以被搜索
  • 4、内存缓存被清空,等待接收新的文档

同样,在查询时也轮询段落,然后将查询结果合并得到最终结果。

[En]

Similarly, the paragraph is also polled when querying, and then the query results are merged to get the final result.

另外就是涉及到删除的事情, 段本身也是不可变的, 既不能把文档从旧的段中移除,也不能修改旧的段来进行文档的更新,而删除是因为:是段在每个提交点时有一个.del文件,这个文件就是一个删除的标志文件,要删除哪些数据,就对该数据做了一个标记,从而下一次查询的时候就过滤掉被标记的这些段,从而就无法查到了,这叫逻辑删除( 当然:这就会导致倒排索引越积越多,再查询时。轮询来查数据也会影响效率 ),所以也有物理删除,它是把段进行合并,这样就舍弃掉被删除标记的段了,从而最后刷新到磁盘中去的就是最新的数据( 就是去掉删除之后的 ,别忘了前面整的段的流程啊,不是白写的 )

4.13、近实时搜索、文档刷新、文档刷写、文档合并

ES的最大好处就是实时数据全文检索,但是:ES这个玩意儿并不是真的实时的,而是近实时 / 准实时,原因就是:ES的数据搜索是分段搜索,最新的数据在最新的段中( 每一个段又是一个倒排索引 ),只有最新的段刷新到磁盘中之后,ES才可以进行数据检索,这样的话,磁盘的IO性能就会极大的影响ES的查询效率,而ES的目的就是为了:快速的、准确的获取到我们想要的数据,因此:降低数据查询处理的延迟就very 重要了,而ES对这方面做了什么操作?

  • *就是搞的一主多副的方式( 一个主分片,多个副本分片 ),这虽然就是一句话概括了,但是:里面的门道却不是那么简单的

首先来看一下主副操作

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

但是:这种去找寻节点的过程想都想得到会造成延时,而延时 = 主分片延时 + 主分片拷贝数据给副本的延时
而且并不是这样就算完了,前面提到了N多次的分段、刷新到磁盘还没上堂呢,所以接着看

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

但是:在flush到磁盘中的时候,万一断电了呢?或者其他原因导致出问题了,那最后数据不就没有flush到磁盘吗。因此:其实还有一步操作,把数据保存到另外一个文件中去
ps:对照MySQL的A原子性原理来理解,不懂的可以去翻我的MySQL数据库,里面有说到MySQL在INNODB下的ACID原则实现方式:链接**

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

数据放到磁盘中之后,translog中的数据就会清空
同时更新到磁盘后,用户可以搜索数据。

[En]

After updating to disk at the same time, users can search for data.

注意:这里要区分一下,MySQL数据库中是先更新到log中,然后再更新到内存中,而ES是反着的,是先更新到Segment( 可以直接认为是内存,因它本身就在内存中 ),再更新到log中

可是啊,还是有问题,flush刷写到磁盘是很耗性能的,假如:不断进行更新呢?这样不断进行IO操作,性能好吗?也不行,因此:继续改造( 在Java的JDBC中我说过的 ———— 没有什么是加一层解决不了的,一层不够,那就再来一层 )

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

加入了缓存之后,这缓存里面的数据是可以直接用来搜索的,这样就不用等到flush到磁盘之后,才可以搜索了,这大大的提高了性能,而flush到磁盘,只要时间到了,让它自个儿慢慢flush就可以了( 操作系统缓存中的数据只要ES服务没宕掉就不会丢失啊 ), 上面这个流程也叫:持久化 / 持久化变更

写入和打开一个新段的轻量的过程叫做refresh。默认情况下每个分片会每秒自动刷新一次。这就是为什么我们说 ES是近实时搜索:文档的变化并不是立即对搜索可见,但会在一秒之内变为可见

刷新是1s以内完成的,这是有时间间隙的,因此会造成:搜索一个文档时,可能并没有搜索到,因此:解决办法就是使用refresh API刷新一下即可

但是这样也伴随一个问题:虽然这种从内存刷新到缓存中看起来不错,但是还是有性能开销的。并不是所有的情况都需要refresh的,假如:是在索引日志文件呢?去refresh干嘛,浪费性能而已,所以此时:你要的是查询速度,而不是近实时搜索,因此:可以通过一个配置来进行改动,从而降低每个索引的刷新频率

  http://ip:port/index_name/_settings   # 请求方式:put

  # 请求体内容
  {
    "settings": {
      "refresh_interval": "60s"
    }
  }

refresh_interval可以在既存索引上进行动态更新。在生产环境中,当你正在建立一个大的新索引时,可以先关闭自动刷新,待开始使用该索引时,再把它们调回来( 虽然有点麻烦,但是按照ES这个玩意儿来说,确实需要这么做比较好 )

  # 关闭自动刷新
  http://ip:port/users/_settings    # 请求方式:put

  # 请求体内容
  {
    "refresh_interval": -1
  }

  # 每一秒刷新
  http://ip:port/users/_settings    # 请求方式:put
  # 请求体内容
  {
    "refresh_interval": "1s"
  }

此外:不断更新会导致大量的分段(内存被写入磁盘的地方,会产生大量的磁盘文件),所以:哪里使用了文件合并功能(即分段合并文档的能力,从而将写入磁盘的文件变成一个文件)。

[En]

In addition: constant updates will lead to a lot of segments (where the memory is written to the disk, it will result in a lot of disk files), so: where the document merging function is used (that is, the ability of segments to merge documents, thus turning the document written to disk into one).

经过上面的思路了解之后,要是面试官问你数据库的优化可以怎么弄?除了常见的,这个分段的思想、分片的思想就可以套上去了,当然再结合Redis的优化方式来回答,更beautiful,顺带还可以扯到Redis和ES来( 面试造飞机,上班拧螺丝嘛,或者就是一部署完就在办公室坐着抠脚 ),这就变成你牵着面试官的鼻子走,而不是他问什么,你去跟着它的思路回答,主动权在自己手上不香吗,面试官面试一个人是有时间限制的,当然:要是不想扯到ES中来,直接根据情况大表拆小表也行

4.14、文档分析

试想一下:我们在浏览器里输入一条信息,比如:搜索“博客花园紫爱”。你为什么要搜索“博客花园”呢?这不是我想要的“

[En]

Just imagine: we enter a piece of information in the browser, such as: search for “blog Garden Purple Love”. Why did you even search for “blog Garden”? that’s not what I want. “

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

这就是全文检索,就是ES干的事情( 过滤数据、检索嘛 ),但是:它做了哪些操作呢?

在ES中有一个文档分析的过程,文档分析的过程也很简单:

  • 将文本拆成适合于倒排索引的独立的词条,然后把这些词条统一变为一个标准格式,从而使文本具有”可搜索性”
  • 而这个文档分析的过程在ES是由一个叫做”分析器 analyzer”的东西来做的,这个分析器里面做了三个步骤
  • 1、字符过滤器:就是用来处理一些字符的嘛,像什么将 & 变为 and 啊、去掉HTML元素啊之类的。它是文本字符串在经过分词之前的一个步骤,文本字符串是按文本顺序经过每个字符串过滤器从而处理字符串的
  • 2、分词器:见名知意,就是用来分词的,也就是将字符串拆分成词条( 字 / 词组 ),这一步和Java中String的split()一样的,通过指定的要求,把内容进行拆分,如:空格、标点符号
  • *3、Token过滤器:这个玩意儿的作用就是 词条经过每个Token过滤器,从而对数据再次进行筛选,如:字母大写变小写、去掉一些不重要的词条内容、添加一些词条( 如:同义词 )

上述的内容不理解没事,待会儿会用IK中文分词器来演示,从而能够更直观的看到效果

在ES中,有提供好的内置分析器、我们也可以自定义、当然还有就是前面说的IK分词器也可以做到( 而重点需要了解的就是IK中文分词器 ,写到这里了,就突然想到一个事儿,牢骚一下:

  • 就是有人私聊,说我博客废话太多了,有些不需要的东西写出来干什么?他只想快速上手,其他不相关的滤过比较好,所以我在想:不把事情的前因后果了解到,就直接开干好吗?反正现在的我不把东西整明白,学东西都总感觉缺点什么,从而导致学的东西不是我想要的,这样让我学起来很不爽,虽然理论确实整起来烦得很,我曾经开始接触Java的时候也是这么想的,就想着步子迈大一点,只管技术怎么用就行,理论哪些废话我不想听,可是后来步子迈大了,扯到了胯,后面研究另外一些深一点的东西时,我总觉得少了一些东西,边研究边百度,但是知识点是散的,那不是我想要的知识体系,这种更不爽( 我个人偏向于:自己脑海有知识体系才好,但那时候学是散的,自己一边整一边摸索的 )。你敢相信我当初才用ES时,快速上手到什么地步?就了解了一些基础理论、在linux中用docker-conpose.yml编写了ES和kibana的安装方式、还有就是Java API各种常用的方法,然后就没了,结果后面自己吃了大亏,后面我是把Java重学了一遍(这就是地基没打牢),所以别相信什么所谓的”键盘不稀烂、代码不停干”,只撸代码,会处理人际关系那有个鸟用,理论是筑起高楼的地基,好了言归正传吧!!!

在演示之前,先玩kibana吧,原本打算放在后面的,但是越早熟悉越好嘛,所以先把kibana说明了

4.14.1、kibana

准备工作:去Elastic官网下载kibana,官网地址如下:

下载好了kibana之后,解压到自己想要的目录
注:解压会有点久,因为是用Vue写的,里面有模块module 要是解压快的话,可能还下错了,然后点击bin/kibana.bat即可启动kibana

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

启动之后就是上图中的样子,然后访问图中的地址即可, 第一次进去会有一个选择页面,try / explore,选择explore就可以了,进去之后就是如下界面

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

这是英文版,要是没玩过大数据的话,那么里面的一些专业名词根据英文来看根本不知道,所以: 汉化吧,kibana本身就提供得有汉化的功能,只需要改动一个配置即可 —— 就是一个i18n配置而已

  • *进入config/kibana.yml,滑到最底部

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

加上上面的信息,然后重启kibana就可以了
但是:个人建议:首先是汉语一段时间,等待熟悉哪些名词,然后再翻译成英语,简而言之,最后的建议是使用英语,一是增加英语词汇量,二是熟悉英语专业词汇。不管怎么说,现在用英语编程比用中文编程更有优势,因为很多东西都是外国人的。

[En]

But: personal suggestion: first Chinese for a period of time, wait for familiar with which nouns, and then turn into English, in short, the final suggestion is to use English, one is to increase English vocabulary, the other is to be familiar with English professional words. Anyway, at present, programming anything in English has an advantage over using Chinese, because a lot of things belong to foreigners.

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

汉化成功

kibana遵循的是rest风格( get、put、delete、post….. ),具体用法接下来玩分析器和后面都会慢慢熟悉

4.14.2、内置分析器

4.14.2.1、标准分析器 standard

这是根据Unicode定义的单词边界来划分文本,将字母转成小写,去掉大部分的标点符号,从而得到的各种语言的最常用文本选择,另外:这是ES的默认分析器,接下来演示一下

启动kibana和ES( 这是用的单机,即重新解压启动的那种,另外方式也可以玩,但没演示 ),打开控制台

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

编写指令

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )
  GET _analyze
  {
    "analyzer": "standard", # analyzer 分析器  standard 标准分析器
    "text": "my name is ZiXieQing" # text 文本标识   my name is ZiXieQing 自定义的文本内容
  }

   # 响应内容
  {
    "tokens" : [
    {
      "token" : "my",   # 分词之后的词条
      "start_offset" : 0,
      "end_offset" : 2,   # start和end叫偏移量
      "type" : "",
      "position" : 0  # 当前词条在整个文本中所处的位置
    },
    {
      "token" : "name",
      "start_offset" : 3,
      "end_offset" : 7,
      "type" : "",
      "position" : 1
    },
    {
      "token" : "is",
      "start_offset" : 8,
      "end_offset" : 10,
      "type" : "",
      "position" : 2
    },
    {
      "token" : "zixieqing",
      "start_offset" : 11,
      "end_offset" : 20,
      "type" : "",
      "position" : 3
    }
    ]
  }

从上图可以看出:所谓的标准分析器通过标点符号(空格、逗号)将文本分成单词。您可以使用这些标点符号测试来观察右分词的结果),同时将大写转换为小写。

[En]

As can be seen from the above picture: the so-called standard analyzer divides the text into words by punctuation (spaces, commas. You can use these punctuation tests to observe the results of the right participle), and convert uppercase to lowercase at the same time.

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )
4.14.2.2、简单分析器 simple

简单分析器是”按非字母的字符分词,例如:数字、标点符号、特殊字符等,会去掉非字母的词,大写字母统一转换成小写”

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

4.14.2.3、空格分析器 whitespace

是简单按照空格进行分词,相当于按照空格split了一下,大写字母不会转换成小写

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

4.14.2.4、去词分析器 stop

会去掉无意义的词( 此无意义是指语气助词等修饰性词,补语文:语气词是疑问语气、祈使语气、感叹语气、肯定语气和停顿语气 ),例如:the、a、an 、this等,大写字母统一转换成小写

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

4.14.2.5、不拆分分析器 keyword

就是将整个文本当作一个词

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

4.14.3、IK中文分词器

来个实验

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

它把我的名字进行拆分了,这不是我想要的,我想要的”紫邪情”应该是一个完整的词,同样道理: 想要特定的词汇,如:ID号、用户名….,这些不应该拆分,而ES内置分析器并不能做到,所以需要IK中文分词器( 专门用来处理中文的 )

1、下载IK分词器

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

2、把IK解压到ES/plugins中去,如我的:

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

3、重启ES即可( kibana开着的话,也要关了重启 ),注意观察:重启时会有一个IK加载过程

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

经过如上的操作之后,IK中文分词器就配置成功了,接下来就来体验一下( 启动ES和kibana ),主要是为了了解IK中的另外两种分词方式: ik_max_word和ik_smart

  • ik_max_word是细粒度的分词,就是:穷尽词汇的各种组成
    ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )
  • ik_smart是粗粒度的分词
    ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

回到前面的问题,”紫邪情”是名字,我不想让它分词,怎么做?上面哪些分词都是在一个”词典”中,所以我们自己搞一个词典即可

1. 创建一个.dic文件 dic就是dictionary词典的简写

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

2. 在创建的dic文件中添加不分词的词组,保存

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

3. 把自定义的词典放到ik中去,保存

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

4. 重启ES和kibana
5. 测试

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

可见,现在就把”紫邪情”组成词组不拆分了,前面玩的kibana汉化是怎么做的?和这个的原理差不多

4.14.4、自定义分析器

这里还有一个自定义分析器的知识点,不管你是否不了解这一点,感兴趣的百度百科全书来了解一下吧。

[En]

Here is also a custom analyzer knowledge point, whether you do not understand this, interested Baidu encyclopedia to learn about it.

4.14.5、多玩几次kibana

在第一篇高级篇中我便说过:kibana重要,只是经过前面这些介绍了使用之后,并不算熟悉,因此:多玩几次吧

另外:就是前面说的kibana遵循rest风格,在ES中是怎么玩的?总结下来其实就下面这些,要上手简单得很,但理论却是一直弄到现在

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

现在用kibana来演示几个,其他的内容在在postman中怎么弄,换一下即可( 其实不建议用postman测试,但是:前面用的一直是postman,专业的人做专业的事,kibana才是我们后端玩的 )

1. 创建索引

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

2, 查看索引

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

3. 删除索引

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

4. 创建文档( 自定义id )

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

5. 查看文档( 通过id查询 )

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

6. 修改文档( 局部修改 )

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

验证一下:

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

7. 建字段类型

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

其他的也是差不多的玩法,在基础篇中怎么玩,稍微变一下就是kibana的玩法了

4.15、文档控制( 了解即可 )

所谓的文档控制就是:不断更新的情况,试想:多进程不断去更新文档,会造成什么情况?会把其他人更新过的文档进行覆盖更新了,而ES是怎么解决这个问题的?

就是弄了一个锁来实现的,和Redis一样,也是用的乐观锁来实现的,这个其实没什么好说的,只需要看一下就知道了

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

上图中的三个字段就和锁挂钩的,version,版本号嘛,每次更新都会有一个版本号,这样就解决了多进程修改从而造成的文档冲突了( 必须等到一个进程更新完了,另一个进程才可以更新,才可以拿到版本号嘛 )

当然:需要注意旧版本的ES在请求中加上version即可,但是新版本的ES需要使用 “if_seq_no=value” & “if_primary_term” =value来达到version的效果( 这两个字段一样的放在请求路径中即可 )

4.16、ES的优化

ES的所有索引和文档数据都是存储在本地的磁盘中的,所以:磁盘能处理的吞吐量越大,节点就越稳定

要修改的话,是在config/elasticsearch.yml中改动

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

4.16.1、硬件方面

1. 选用固态硬盘( 即:SSD ),它比机械硬盘好是因为:机械硬盘是通过旋转马达的驱动来进行的,所以这就会造成发热、磨损,就会影响ES的效率,而SSD是使用芯片式的闪存来存储数据的,性能比机械硬盘好得多

2. 使用RAID 0 ( 独立磁盘冗余阵列 ),它是把连续的数据分散到多个磁盘上存取,这样,系统有数据请求就可以被多个磁盘并行的执行,每个磁盘执行属于它自己的那部分数据请求。这种数据上的并行操作可以充分利用总线的带宽,显著提高磁盘整体存取性( 不了解总线和带宽的,真的有必要去学一下:计算机组成原理,这个知识在计算机组成原理的数据总线那里有 , 当然:面向百度简单了解一下也行 )

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

3. 由上面的RAID 0可以联想到另外一个解决方式:使用多块硬盘,也就可以达到同样的效果了( 有钱就行 ),是通过path data目录配置把数据条分配到这些磁盘上面

4. 不要把ES挂载到远程上去存储

4.16.2、分片策略

碎片和副本不是随机分发的!分片也可以位于不同的节点(假设节点中存储的数据较多),这类似于关系拆分表,确实可以视为优化,但:如果一个节点有多个分片,则会导致分片之间的资源竞争,从而导致性能下降。

[En]

Fragments and copies are not randomly distributed! Sharding can also be located in different nodes (provided that there is more data stored in the node), which is similar to a relational split table, which can indeed be regarded as optimization, but: if there are multiple shards in a node, then it will cause resource competition between shards, which will lead to performance degradation.

所以分片和副本遵循下面的原则就可以了
1. 每个分片占用的磁盘容量不得超过ES的JVM的堆空间设置( 一般最大为32G ),假如:索引容量为1024G,那么节点数量为:1024 / 32 = 32左右

2. 分片数不超过节点数的3倍,就是为了预防一个节点上有多个分片的情况,万一当前节点死了,那么就算做了副本,也很容易导致集群丢失数据

3. 节点数

4. 推迟分片分配

  • *有可能一个节点宕掉了,但是后面它又恢复了,而这个节点原有数据是还在的,所以:推迟分片分配,从而减少ES的开销,具体做法如下:
  PUT /_all/_settings
  {
    "settings": {
      "index.unassigned.node_left.delayed_timeout": "5m"
    }
  }

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

可以全局修改,也可以在索引时修改

[En]

Can be modified globally or when indexing

4.16.3、带路由查询

前面说过:路由计算公式 shard = hash( routing ) % number_of_primary_shards

而routing默认值就是文档id,所以查询时把文档id带上,如:前面玩kibana做的操作

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

如果没有路由,则会签出分片和副本,然后进行轮询。效率会稍微慢一点。

[En]

If there is no routing, the shards and copies will be checked out, and then polling will be carried out. The efficiency will be a little slower.

4.16.4、内存优化

修改es的config/jvm.options

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

把上面的数字改了, Xms 表示堆的初始大小, Xmx 表示可分配的最大内存,ES默认是1G,这个数字在现实中是远远不够了,改它的目的是:为了能够在 Java 垃圾回收机制清理完堆内存后不需要重新分隔计算堆内存的大小而浪费资源,可以减轻伸缩堆大小带来的压力,但是也需要注意:改这两个数值,需要确保 Xmx 和 Xms 的大小是相同的,另外就是:这两个数值别超过32G啊,前面已经讲过了

4.17、附上一些配置说明

参数名 参数值 说明

cluster.name elasticsearch 配置 ES 的集群名称,默认值是 ES,建议改成与所存数据相关的名称, ES 会自动发现在同一网段下的 集群名称相同的节点 node.name node-1001 集群中的节点名,在同一个集群中不能重复。节点 的名称一旦设置,就不能再改变了。当然,也可以 设 置 成 服 务 器 的 主 机 名 称 , 例 如 node.name: $ node.master true 指定该节点是否有资格被选举成为 Master 节点,默 认是 True,如果被设置为 True,则只是有资格成为 Master 节点,具体能否成为 Master 节点,需要通过选举产生 node.data true 指定该节点是否存储索引数据,默认为 True。数据的增、删、改、查都是在 Data 节点完成的 index.number_of_shards 1 设置索引分片个数,默认是 1 片。也可以在创建索引时设置该值,具体设置为多大值要根据数据量的大小来定。如果数据量不大,则设置成 1 时效率最高 index.number_of_replicas 1 设置默认的索引副本个数,默认为 1 个。副本数越多,集群的可用性越好,但是写索引时需要同步的数据越多 transport.tcp.compress true 设置在节点间传输数据时是否压缩,默认为 False discovery.zen.minimum_master_nodes 1 设置在选举 Master 节点时需要参与的最少的候选主节点数,默认为 1。如果使用默认值,则当网络不稳定时有可能会出现脑裂。 合理的 数 值 为 ( master_eligible_nodes / 2 )+1 , 其 中 master_eligible_nodes 表示集群中的候选主节点数 discovery.zen.ping.timeout 3s 设置在集群中自动发现其他节点时 Ping 连接的超时时间,同时也是选主节点的延迟时间,默认为 3 秒。 在较差的网络环境下需要设置得大一点,防止因误判该节点的存活状态而导致分片的转移

4.18、SpringBoot集成ES

ES官方学习文档中有,链接是:https://www.elastic.co/guide/index.html

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

然后点击other version,选择对应的版本,如:我的是7.8

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

这里面样都有,点击:getting started看一下

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

选择maven

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

  org.elasticsearch.client
  elasticsearch-rest-high-level-client
  7.8.0

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

ElasticSearch 7.8.x技术整理4 - 高级篇( 续 )

建议:有时间去研究一下官网

java操作篇链接:https://www.cnblogs.com/xiegongzi/p/15690534.html

4.19、说一些另外的理论吧

4.19.1、ES的master主节点选举流程

1. 首先选主是由ZenDiscovery来完成的( 它做了两件事:一个是Ping过程 ———— 发现节点嘛 、二是Unicast过程 ———— 控制哪些节点需要Ping通 )

2. 对所有可以成为master的节点( 文件中设置的node.master: true )根据nodeId字典排序,每次”选举节点( 即:参与投票选举主节点的那个节点 )”都把自己知道的节点排一次序,就是把排好序的第一个节点( 第0位 )认为是主节点( 投一票 )

3. 当某个节点的投票数达到一个值时( ( 可以成为master节点数n / 2 ) + 1 ),而该节点也投自己,那么这个节点就是master节点,否则重新开始,直到选出master

另外注意:master节点的职责主要包括集群、节点和索引的管理,不负责文档级别的管理;data节点可以关闭http功能

4.19.2、ES的集群脑裂问题

导致的原因:

  • 网络问题:集群间的网络延迟导致一些节点访问不到master, 认为master 挂掉了从而选举出新的master,并对master上的分片和副本标红,分配新的主分片
  • 节点负载:主节点的角色既为master又为data,访问量较大时可能会导致ES停止响应造成大面积延迟,此时其他节点得不到主节点的响应认为主节点挂掉了,会重新选取主节点
  • 内存回收:data 节点上的ES进程占用的内存较大,引发JVM的大规模内存回收,造成ES进程失去响应

脑裂问题解决方案:

  • 减少误判:discovery.zen ping_ timeout 节点状态的响应时间,默认为3s,可以适当调大,如果master在该响应时间的范围内没有做出响应应答,判断该节点已经挂掉了。调大参数( 如6s,discovery.zen.ping_timeout:6 ),可适当减少误判
  • 选举触发:discovery.zen.minimum. master nodes:1,该参數是用于控制选举行为发生的最小集群主节点数量。当备选主节点的个數大于等于该参数的值,且备选主节点中有该参数个节点认为主节点挂了,进行选举。官方建议为(n / 2) +1, n为主节点个数(即有资格成为主节点的节点个数)
  • 角色分离:即master节点与data节点分离,限制角色
  • 主节点配置为:node master: true,node data: false
  • *从节点置为:node master: false,node data: true

Original: https://www.cnblogs.com/xiegongzi/p/15770665.html
Author: 紫邪情
Title: ElasticSearch 7.8.x技术整理4 – 高级篇( 续 )

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/522613/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球