加入收藏 | 设为首页 | 会员中心 | 我要投稿 岳阳站长网 (https://www.0730zz.com.cn/)- 科技、建站、数据库平台、数据湖、视觉智能!
当前位置: 首页 > 云计算 > 正文

吃透这万字,谁还不是个ElasticSearch操作老手?

发布时间:2022-08-02 11:15:31 所属栏目:云计算 来源:互联网
导读:一、生活中的数据 搜索引擎是对数据的检索,所以我们先从生活中的数据说起。 我们生活中的数据总体分为两种:结构化数据和非结构化数据 。 结构化数据:也称作行数据,是由二维表结构来逻辑表达和实现的数据,严格地遵循数据格式与长度规范,主要通过关系型
  一、生活中的数据
  搜索引擎是对数据的检索,所以我们先从生活中的数据说起。
 
  我们生活中的数据总体分为两种:结构化数据和非结构化数据 。
 
  结构化数据:也称作行数据,是由二维表结构来逻辑表达和实现的数据,严格地遵循数据格式与长度规范,主要通过关系型数据库进行存储和管理。指具有固定格式或有限长度的数据,如数据库,元数据等。
 
  非结构化数据:又可称为全文数据,不定长或无固定格式,不适于由数据库二维表来表现,包括所有格式的办公文档、XML、HTML、word文档,邮件,各类报表、图片和咅频、视频信息等。
 
  说明:如果要更细致的区分的话,XML、HTML可划分为半结构化数据。因为它们也具有自己特定的标签格式,所以既可以根据需要按结构化数据来处理,也可抽取出纯文本按非结构化数据来处理。
 
  根据两种数据分类,搜索也相应的分为两种:结构化数据搜索和非结构化数据搜索 。
 
  对于结构化数据,因为它们具有特定的结构,所以我们一般都是可以通过关系型数据库(mysql,oracle等)的二维表(table)的方式存储和搜索,也可以建立索引。
 
  对于非结构化数据,也即对全文数据的搜索主要有两种方法:顺序扫描法,全文检索 。
 
  顺序扫描:通过文字名称也可了解到它的大概搜索方式,即按照顺序扫描的方式查询特定的关键字。例如给你一张报纸,让你找到该报纸中“平安”的文字在哪些地方出现过。你肯定需要从头到尾把报纸阅读扫描一遍然后标记出关键字在哪些版块出现过以及它的出现位置。
 
  这种方式无疑是最耗时的最低效的,如果报纸排版字体小,而且版块较多甚至有多份报纸,等你扫描完你的眼睛也差不多了。
 
  全文搜索:对非结构化数据顺序扫描很慢,我们是否可以进行优化?把我们的非结构化数据想办法弄得有一定结构不就行了吗?将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的。
 
  这种方式就构成了全文检索的基本思路。这部分从非结构化数据中提取出的然后重新组织的信息,我们称之索引 。这种方式的主要工作量在前期索引的创建,但是对于后期搜索却是快速高效的。
 
  二、先说说 Lucene
  通过对生活中数据的类型作了一个简短了解之后,我们知道关系型数据库的SQL检索是处理不了这种非结构化数据的。这种非结构化数据的处理需要依赖全文搜索,而目前市场上开放源代码的最好全文检索引擎工具包就属于 apache 的 Lucene了。
 
  但是 Lucene 只是一个工具包,它不是一个完整的全文检索引擎。Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。
 
  目前以 Lucene 为基础建立的开源可用全文搜索引擎主要是 Solr 和 Elasticsearch。
 
  Solr 和 Elasticsearch 都是比较成熟的全文搜索引擎,能完成的功能和性能也基本一样。但是 ES 本身就具有分布式的特性和易安装使用的特点,而Solr的分布式需要借助第三方来实现,例如通过使用ZooKeeper来达到分布式协调管理。
 
  不管是 Solr 还是 Elasticsearch 底层都是依赖于 Lucene,而 Lucene 能实现全文搜索主要是因为它实现了倒排索引的查询结构。
 
  如何理解倒排索引呢?假如现有三份数据文档,文档的内容如下分别是:
 
  Java is the best programming language.
  PHP is the best programming language.
  Javascript is the best programming language.
  为了创建倒排索引,我们通过分词器将每个文档的内容域拆分成单独的词(我们称它为词条或 Term),创建一个包含所有不重复词条的排序列表,然后列出每个词条出现在哪个文档。结果如下所示:
 
  复制
  CopyTerm          Doc_1    Doc_2   Doc_3
  -------------------------------------
  Java        |   X   |        |
  is          |   X   |   X    |   X
  the         |   X   |   X    |   X
  best        |   X   |   X    |   X
  programming |   x   |   X    |   X
  language    |   X   |   X    |   X
  PHP         |       |   X    |
  Javascript  |       |        |   X
  -------------------------------------
  1.
  2.
  3.
  4.
  5.
  6.
  7.
  8.
  9.
  10.
  11.
  这种结构由文档中所有不重复词的列表构成,对于其中每个词都有一个文档列表与之关联。这种由属性值来确定记录的位置的结构就是倒排索引。带有倒排索引的文件我们称为倒排文件。
 
  我们将上面的内容转换为图的形式来说明倒排索引的结构信息,如下图所示,
 
  图片
 
  其中主要有如下几个核心术语需要理解:
 
  词条(Term):索引里面最小的存储和查询单元,对于英文来说是一个单词,对于中文来说一般指分词后的一个词。
  词典(Term Dictionary):或字典,是词条Term的集合。搜索引擎的通常索引单位是单词,单词词典是由文档集合中出现过的所有单词构成的字符串集合,单词词典内每条索引项记载单词本身的一些信息以及指向“倒排列表”的指针。
  倒排表(Post list):一个文档通常由多个词组成,倒排表记录的是某个词在哪些文档里出现过以及出现的位置。每条记录称为一个倒排项(Posting)。倒排表记录的不单是文档编号,还存储了词频等信息。
  倒排文件(Inverted File):所有单词的倒排列表往往顺序地存储在磁盘的某个文件里,这个文件被称之为倒排文件,倒排文件是存储倒排索引的物理文件。
  从上图我们可以了解到倒排索引主要由两个部分组成:词典和倒排文件。词典和倒排表是Lucene中很重要的两种数据结构,是实现快速检索的重要基石。词典和倒排文件是分两部分存储的,词典在内存中而倒排文件存储在磁盘上。
 
  三、核心概念
  一些基础知识的铺垫之后我们正式进入今天的主角Elasticsearch的介绍, ES是使用Java编写的一种开源搜索引擎,它在内部使用Lucene做索引与搜索,通过对Lucene的封装,隐藏了Lucene的复杂性,取而代之的提供一套简单一致的 RESTful API。
 
  然而,Elasticsearch 不仅仅是 Lucene,并且也不仅仅只是一个全文搜索引擎。它可以被下面这样准确的形容:
 
  一个分布式的实时文档存储,每个字段可以被索引与搜索。
  一个分布式实时分析搜索引擎。
  能胜任上百个服务节点的扩展,并支持 PB 级别的结构化或者非结构化数据。
  官网对Elasticsearch的介绍是Elasticsearch 是一个分布式 、可扩展 、近实时的搜索与数据分析引擎。我们通过一些核心概念来看下Elasticsearch 是如何做到分布式,可扩展和近实时搜索的。
 
  ​​​1、集群(Cluster)
  ES的集群搭建很简单,不需要依赖第三方协调管理组件,自身内部就实现了集群的管理功能。ES集群由一个或多个Elasticsearch节点组成,每个节点配置相同的 cluster.name 即可加入集群,默认值为 “elasticsearch”。确保不同的环境中使用不同的集群名称,否则最终会导致节点加入错误的集群。
 
  一个Elasticsearch服务启动实例就是一个节点(Node)。节点通过node.name来设置节点名称,如果不设置则在启动时给节点分配一个随机通用唯一标识符作为名称。
 
  1)发现机制
 
  那么有一个问题,ES内部是如何通过一个相同的设置cluster.name 就能将不同的节点连接到同一个集群的?答案是Zen Discovery。
 
  Zen Discovery是Elasticsearch的内置默认发现模块(发现模块的职责是发现集群中的节点以及选举master节点)。它提供单播和基于文件的发现,并且可以扩展为通过插件支持云环境和其他形式的发现。Zen Discovery 与其他模块集成,例如,节点之间的所有通信都使用Transport模块完成。节点使用发现机制通过Ping的方式查找其他节点。
 
  Elasticsearch 默认被配置为使用单播发现,以防止节点无意中加入集群。只有在同一台机器上运行的节点才会自动组成集群。
 
  如果集群的节点运行在不同的机器上,使用单播,你可以为 Elasticsearch 提供一些它应该去尝试连接的节点列表。当一个节点联系到单播列表中的成员时,它就会得到整个集群所有节点的状态,然后它会联系 master 节点,并加入集群。
 
  这意味着单播列表不需要包含集群中的所有节点, 它只是需要足够的节点,当一个新节点联系上其中一个并且说上话就可以了。如果你使用 master 候选节点作为单播列表,你只要列出三个就可以了。这个配置在 elasticsearch.yml 文件中:
 
  复制
  Copydiscovery.zen.ping.unicast.hosts: ["host1", "host2:port"]
  1.
  节点启动后先 ping ,如果discovery.zen.ping.unicast.hosts 有设置,则 ping 设置中的 host ,否则尝试 ping localhost 的几个端口, Elasticsearch 支持同一个主机启动多个节点, Ping 的 response 会包含该节点的基本信息以及该节点认为的 master 节点。选举开始,先从各节点认为的 master 中选,规则很简单,按照 id 的字典序排序,取第一个。如果各节点都没有认为的 master ,则从所有节点中选择,规则同上。
 
  这里有个限制条件就是 discovery.zen.minimum_master_nodes ,如果节点数达不到最小值的限制,则循环上述过程,直到节点数足够可以开始选举。最后选举结果是肯定能选举出一个 master ,如果只有一个 local 节点那就选出的是自己。如果当前节点是 master ,则开始等待节点数达到 discovery.zen.minimum_master_nodes,然后提供服务。如果当前节点不是 master ,则尝试加入 master 。Elasticsearch 将以上服务发现以及选主的流程叫做 ZenDiscovery 。
 
  由于它支持任意数目的集群( 1- N ),所以不能像 Zookeeper 那样限制节点必须是奇数,也就无法用投票的机制来选主,而是通过一个规则,只要所有的节点都遵循同样的规则,得到的信息都是对等的,选出来的主节点肯定是一致的。但分布式系统的问题就出在信息不对等的情况,这时候很容易出现脑裂( Split-Brain )的问题,大多数解决方案就是设置一个 quorum 值,要求可用节点必须大于 quorum (一般是超过半数节点),才能对外提供服务。而 Elasticsearch 中,这个 quorum 的配置就是 discovery.zen.minimum_master_nodes 。
 
  2)节点的角色
 
  每个节点既可以是候选主节点 也可以是数据节点 ,通过在配置文件../config/elasticsearch.yml中设置即可,默认都为true。
 
  复制
  Copynode.master: true  //是否候选主节点
  node.data: true    //是否数据节点
  1.
  2.
  数据节点 负责数据的存储和相关的操作,例如对数据进行增、删、改、查和聚合等操作,所以数据节点(data节点)对机器配置要求比较高,对CPU、内存和I/O的消耗很大。通常随着集群的扩大,需要增加更多的数据节点来提高性能和可用性。
 
  候选主节点 可以被选举为主节点(master节点),集群中只有候选主节点才有选举权和被选举权,其他节点不参与选举的工作。主节点负责创建索引、删除索引、跟踪哪些节点是群集的一部分,并决定哪些分片分配给相关的节点、追踪集群中节点的状态等,稳定的主节点对集群的健康是非常重要的。
 
  图片
 
  一个节点既可以是候选主节点也可以是数据节点,但是由于数据节点对CPU、内存核I/0消耗都很大,所以如果某个节点既是数据节点又是主节点,那么可能会对主节点产生影响从而对整个集群的状态产生影响。
 
  因此为了提高集群的健康性,我们应该对Elasticsearch集群中的节点做好角色上的划分和隔离。可以使用几个配置较低的机器群作为候选主节点群。
 
  主节点和其他节点之间通过Ping的方式互检查,主节点负责Ping所有其他节点,判断是否有节点已经挂掉。其他节点也通过Ping的方式判断主节点是否处于可用状态。
 
  虽然对节点做了角色区分,但是用户的请求可以发往任何一个节点,并由该节点负责分发请求、收集结果等操作,而不需要主节点转发,这种节点可称之为协调节点,协调节点是不需要指定和配置的,集群中的任何节点都可以充当协调节点的角色。
 
  3)脑裂现象
 
  同时如果由于网络或其他原因导致集群中选举出多个Master节点,使得数据更新时出现不一致,这种现象称之为脑裂,即集群中不同的节点对于master的选择出现了分歧,出现了多个master竞争。
 
  “脑裂”问题可能有以下几个原因造成:
 
  网络问题 :集群间的网络延迟导致一些节点访问不到master,认为master挂掉了从而选举出新的master,并对master上的分片和副本标红,分配新的主分片
  节点负载 :主节点的角色既为master又为data,访问量较大时可能会导致ES停止响应(假死状态)造成大面积延迟,此时其他节点得不到主节点的响应认为主节点挂掉了,会重新选取主节点。
  内存回收 :主节点的角色既为master又为data,当data节点上的ES进程占用的内存较大,引发JVM的大规模内存回收,造成ES进程失去响应。

(编辑:岳阳站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读