分布式搜索引擎(ES)连杀

ElasticSearch是一个基于Lucene的分布式、RESTful 风格的搜索和数据分析引擎。

  1. 什么是倒排索引
    正排索引:文档ID到文档内容、单词的关联关系
    倒排索引:单词到文档ID的关联关系 (还可以扩充关系,如增加出现的次数,位置等)
    在这里插入图片描述

  2. ES的基本概念
    Cluster-> Node-> Index-> Document-> Field

    1. Cluster
      集群: 集群由一个或多个节点组成,保存所有的数据,并对外提供索引和搜索服务。在所有的节点,一个集群有一个唯一的名称默认为“ElasticSearch”,此名称很重要,因为每个节点只能是集群的一部分,当该节点被设置为相同的集群名称时,就会自动加入集群。当需要多个集群的时候,要确保每个集群的名称不能重复,否则,节点可能会加入错误的集群。
    2. Node
      节点: 一个节点就是一个单独的服务,是集群的一部分,保存着数据,参与集群的索引和搜索服务。每个节点也有自己的名称,默认在节点启动时会初始化一个随机的UUID作为节点的名称,节点默认启动时会加入到名为elasticsearch的集群中,可以通过设置节点的cluster name来更改要加入的集群。
    3. Index
      索引:一个索引就是拥有相同特征的一个文档集合。每个索引有一个唯一的name,该name必须为小写
    4. Type
      类型:6.0以后已不建议使用
    5. Document
      文档:文档是存储在Elasticsearch中的一个JSON(JavaScript Object Notation) 对象,相当于数据库中表的一行。
    6. Shards & Replicas
      分片和副本:一个索引可能非常大,其存储的数据大小可能超过了你物理机的存储空间。为了解决该问题,Elasticsearch允许将索引分成多分(即分片),可以自己定义分片数。在分布式情况下,节点可能失效,此时在此节点上的索引将不可用,为了解决该问题,Elasticsearch允许将数据复制多份(即副本),副本数可自己配置。
      索引创建的时候就该定好分片数和副本数,一旦索引创建成功后,分片数将不可改变,但是副本数可变。
  3. es的分布式架构原理能说一下么(es是如何实现分布式的啊)?
    集群,分片:一个集群中会有一个主节点,主节点选举遵循少数服从多数的原则(过半同意),其选举方法为Elasticsearch自己实现的一套Zen discovery。其中只有配置了node.master: true的节点才能参与选举.

    # 表示是否参与选举master
    node.master: true/false 
    # 表示是否存储数据
    node.data: true/false
    # 节点发现和leader选举相关配置
    discovery.zen.ping.unicast.hosts: [1.1.1.1, 1.1.1.2, 1.1.1.3] #这里只配置参与了master选举的节点
    discovery.zen.minimum_master_nodes: 2
    

    何时选举:
    当一个节点发现包括自己在内的多数派的master-eligible节点认为集群没有master时,就可以发起master选举

    如何选举:

    1. 选所有master-eligible节点中clusterStateVersion最大的:

      为了确保新的master拥有最新的meta信息

    2. clusterStateVersion一样时则选节点ID最小的(节点ID是第一次启动时生成的一个随机字符串)

      统一规则,稳定选举

    如何选举成功:
    当一个master-eligible node发起一次选举时,它会按照上述排序策略选出一个它认为的master。 每个参与选举的节点都有一票,当获取到minimum_master_nodes个选票时,则该节点被作为master node。如果一个节点正在竞选master,收到选票时,会等待一段时间,看自己是否能成为master,直到超时(会发起下一轮选举)或者别的节点成为了master;如果成功竞选成为master后,此时再接收到选票时,则会更新cluster_state中的信息并更新到集群中。

    如何扩容和缩容:

    1. 只存储数据节的点(DataNode):
      扩容直接增加数据节点机器即可,节点会自动加入到集群中,集群会自动进行rebalance;也可以手动调用接口进行rebalance;
      POST /_cluster/reroute

      详细请参考
      cluster-reroute

      缩容的话需要先禁止分配Shard到要缩容的机器上,然后把该机器的数据迁移到其他节点;最后再让集群进行rebalance即可

      详细请参考
      allocation-filtering
      shards-allocation

    2. 可参与选举的节点(MasterNode):
      扩容需要先修改minimum_master_nodes配置,再增加master-eligible节点
      缩容则是先减少master-eligible节点,再修改minimum_master_nodes配置

  4. es写入数据的工作原理是什么啊?es查询数据的工作原理是什么啊?
    es写数据过程

    1. 客户端选择一个node发送请求过去,这个node就是coordinating node(协调节点)

    2. coordinating node,对document进行路由,将请求转发给对应的node(有primary shard)coordinating node,对document进行路由,将请求转发给对应的node(有primary shard)

    3. 实际的node上的primary shard处理请求,然后将数据同步到replica node实际的node上的primary shard处理请求,然后将数据同步到replica node

      Primary写入的时候,请求会先写入Lucene(即写入内存中,保证数据更快被查询到,同时避免先写入translog成功,后写入lucence失败的复杂情况),然后写入translog(类似于commit log,落盘,保证数据的安全性)

    4. coordinating node,如果发现primary node和所有replica node都搞定之后(只要有返回即可并不要求所有节点都写成功),就返回响应结果给客户端coordinating node,如果发现primary node和所有replica node都搞定之后,就返回响应结果给客户端
      那么会引出问题: 如果一个节点始终都写失败,那么客户端岂不是有可能一直读到旧的数据?

      这个问题是说,假如一个Replica持续写入失败,那么这个Replica上的数据可能落后Primary很多。我们知道ES中Replica也是可以承担读请求的,那么用户是否会读到这个Replica上的旧数据呢?
      答案是如果一个Replica写失败了,Primary会将这个信息报告给Master,然后Master会在Meta中更新这个Index的InSyncAllocations配置,将这个Replica从中移除,移除后它就不再承担读请求。在Meta更新到各个Node之前,用户可能还会读到这个Replica的数据,但是更新了Meta之后就不会了

    es读数据过程:

    1. 客户端发送请求到任意一个节点,成为协调节点
    2. 协调节点根据document的id路由,将请求转发到对应的节点(在包含该docment的节点中随机选举)
    3. 接收请求的节点返回document数据给协调节点
    4. 再由协调节点将数据返回给客户端

    es搜索数据:

    1. 客户端发送请求到一个协调节点
    2. 协调节点将搜索请求转发到所有的shard对应的primary shard或replica shard
    3. 每个shard将自己的搜索结果(docid),返回给协调节点,由协调节点进行数据的合并、排序、分页等操作,产出最终结果
    4. 接着由协调节点,根据doc id去各个节点上拉取实际的document数据并返回给客户端
    //todo: 更底层的写入分析
    
  5. es在数据量很大的情况下(数十亿级别)如何提高查询性能啊?

    1. 增加filesystem cache的大小(两方面,一是直接增加对应的内存大小;一是只保存需要搜索的数据字段,其余的数据放数据库或者hbase之类的)
    2. 还是内存不够的情况下,则需要做数据预热,对于热点数据,可以后台定时的去查询,让其保留在内存中
    3. 冷热分离,将热点数据和冷门数据分机子存放
    4. docment设计,复杂查询在设计的时候就要尽量避免;比如一些复杂逻辑可以查出数据之后在java端再处理
    5. 分页优化(避免使用默认的深度分页,因为ES是将所有分片中的数据查询出来之后,一起再做的处理,所以分页越到后面,汇聚出来的总数据就会非常大,影响性能; 可以使用scroll api)

      Scroll API: 一般搜索请求都是返回一"页"数据,无论数据量多大都一起返回给用户,Scroll API可以允许我们检索大量数据(甚至全部数据)。Scroll API允许我们做一个初始阶段搜索并且持续批量从Elasticsearch里拉取结果直到没有结果剩下。这有点像传统数据库里的cursors(游标)。
      Scroll API的创建并不是为了实时的用户响应,而是为了处理大量的数据。从 scroll 请求返回的结果只是反映了 search 发生那一时刻的索引状态,就像一个快照。后续的对文档的改动(索引、更新或者删除)都只会影响后面的搜索请求

  6. es生产集群的部署架构是什么?每个索引的数据量大概有多少?每个索引大概有多少个分片?
    自己没干过?
    别慌,找公司其他项目中用过的同事去了解情况,问问他们的业务场景,当前数据量,数据增量,索引个数;
    服务器配置部署状态,是否遇到过什么问题等。


引用参考 :
倒排索引与分词
Elasticsearch分布式一致性原理剖析系列

发布了37 篇原创文章 · 获赞 58 · 访问量 16万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览