• ElasticSearch 基本介绍和读写搜索过程


    cluster

    代表一个集群,集群中有多个节点,其中有一个为主节点,这个主节点是可以通过选举产生的,主从节点是对于集群内部来说的。es的一个概念就是去中心化,字面上理解就是无中心节点,这是对于集群外部来说的,因为从外部来看es集群,在逻辑上是个整体,你与任何一个节点的通信和与整个es集群通信是等价的。

    主节点的职责是负责管理集群状态,包括管理分片的状态和副本的状态,以及节点的发现和删除。

    只需要在同一个网段之内启动多个es节点,就可以自动组成一个集群。

    默认情况下es会自动发现同一网段内的节点,自动组成集群。

    集群状态查看:

    http://192.168.57.4:9200/_cluster/health?pretty

    shards

    代表索引分片,es可以把一个完整的索引分成多个分片,这样的好处是可以把一个大的索引拆分成多个,分布到不同的节点上。构成分布式搜索。分片的数量只能在索引创建前指定,并且索引创建后不能更改。

    可以在创建索引库的时候指定

    curl -XPUT 'localhost:9200/test1/' -d'{"settings":{"number_of_shards":3}}'

    默认是一个索引库有5个分片

    index.number_of_shards: 5

    replicas

    代表索引副本,es可以给索引设置副本,副本的作用一是提高系统的容错性,当某个节点某个分片损坏或丢失时可以从副本中恢复。二是提高es的查询效率,es会自动对搜索请求进行负载均衡。

    可以在创建索引库的时候指定

    curl -XPUT 'localhost:9200/test2/' -d'{"settings":{"number_of_replicas":2}}'

    默认是一个分片有1个副本

    index.number_of_replicas: 1

    recovery

    代表数据恢复或叫数据重新分布,es在有节点加入或退出时会根据机器的负载对索引分片进行重新分配,挂掉的节点重新启动时也会进行数据恢复。

    gateway

    代表es索引的持久化存储方式,es默认是先把索引存放到内存中,当内存满了时再持久化到硬盘。当这个es集群关闭再重新启动时就会从gateway中读取索引数据。es支持多种类型的gateway,有本地文件系统(默认),分布式文件系统,Hadoop的HDFS和amazon的s3云存储服务。

    如果需要将数据落地到hadoop的hdfs需要先安装插件

    elasticsearch/elasticsearch-hadoop,然后再elasticsearch.yml配置

    gateway:

       type: hdfs

    gateway:

        hdfs:

        uri: hdfs://localhost:9000

    discovery.zen

    代表es的自动发现节点机制,es是一个基于p2p的系统,它先通过广播寻找存在的节点,再通过多播协议来进行节点之间的通信,同时也支持点对点的交互。

    如果是不同网段的节点如何组成es集群

    禁用自动发现机制

    discovery.zen.ping.multicast.enabled: false

    设置新节点被启动时能够发现的主节点列表

    discovery.zen.ping.unicast.hosts: [“192.168.57.4", "192.168.57.5"]

    Transport

    代表es内部节点或集群与客户端的交互方式,默认内部是使用tcp协议进行交互,同时它支持http协议(json格式)、thrift、servlet、memcached、zeroMQ等的传输协议(通过插件方式集成)。

    settings修改索引库默认配置

    例如:分片数量,副本数量

    查看:curl -XGET http://localhost:9200/hello/_settings?pretty

    curl -XPUT 'localhost:9200/hello/' -d'{"settings":{"number_of_shards":3,"number_of_replicas":2}}'

    Mapping,就是对索引库中索引的字段名称及其数据类型进行定义,类似于关系数据库中表建立时要定义字段名及其数据类型那样,(和solr中的schme类似)不过es的mapping比数据库灵活很多,它可以动态添加字段。一般不需要要指定mapping都可以,因为es会自动根据数据格式定义它的类型,如果你需要对某些字段添加特殊属性(如:定义使用其它分词器、是否分词、是否存储等),就必须手动添加mapping。

    查询索引库的mapping信息

    curl -XGET http://localhost:9200/hello/emp/_mapping?pretty

    mappings修改字段相关属性

    例如:字段类型,使用哪种分词工具

    curl -XPOST master:9200/test -d '{

      "settings": {

           "number_of_shards" : 1

       },

       "mapping" : {

          "type1" : {

              "properties" : {

                   "field1" : {"type":"string", "index": "not-analyzed"}

              }

          }

       }

    }'

    一、es写数据过程

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

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

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

    4、 coordinating node如果发现 primary node和所有replica node都搞定之后,就返回响应结果给客户端。

    二、es读数据过程

    可以通过doc id 来查询,会根据doc id进行hash计算,判断出来当时把doc id分配到了哪个shard上面去,从那个shard去查询。

    1、 客户端发送请求到任意一个node,成为coordinate node

    2、 coordinate node 对doc id进行哈希路由,将请求转发到对应node,此时会使用round-robin随机轮询算法,在primary shard 以及其所有replica中随机选择一个,让读请求负载均衡。

    3、 接收请求的node返回document给coordinate node。

    4、 coordinate node返回document给客户端。

    三、es搜索数据过程

    es最强大的是做全文检索

    1、客户端发送请求到一个node,这个node就是coordinate node。(协调节点)

    2、协调节点将搜索请求转发到所有的shard对应的primary shard 或 replica shard ,都可以。

    3、query phase:每个shard将自己的搜索结果(其实就是一些doc id)返回给协调节点,由协调节点进行数据的合并、排序、分页等操作,产出最终结果。(我自己加的:如果有5个分片的情况下,分页查询10条数据的时候就会查询出50条数据,这个时候就需要将数据进行排序,取出前10条)

    4、fetch phase:接着由协调节点根据doc id去各个节点上拉取实际的document数据,最终返回给客户端。

    写请求是写入primary shard,然后同步给所有的replica shard

    读请求可以从primary shard 或者 replica shard 读取,采用的是随机轮询算法。

    四、写数据底层原理

    1、先写入内存buffer,在buffer里的时候数据是搜索不到的;同时将数据写入translog日志文件。

    如果buffer快满了,或者到一定时间,就会将内存buffer数据refresh 到一个新的segment file中,但是此时数据不是直接进入segment file磁盘文件,而是先进入os cache。这个过程就是 refresh。

    每隔1秒钟,es将buffer中的数据写入一个新的segment file,每秒钟会写入一个新的segment file,这个segment file中就存储最近1秒内 buffer中写入的数据。

    2、但是如果buffer里面此时没有数据,那当然不会执行refresh操作,如果buffer里面有数据,默认1秒钟执行一次refresh操作,刷入一个新的segment file中。

    操作系统里面,磁盘文件其实都有一个东西,叫做os cache,即操作系统缓存,就是说数据写入磁盘文件之前,会先进入os cache,先进入操作系统级别的

    一个内存缓存中去。只要buffer中的数据被refresh 操作刷入os cache中,这个数据就可以被搜索到了。

    3、为什么叫es是准实时的?NRT,全称 near real-time。默认是每隔1秒refresh一次的,所以es是准实时的,因为写入的数据1s之后才能被看到。

    可以通过es的restful api或者 java api,手动执行一次 refresh操作,就是手动将buffer中的数据刷入os cache中,让数据立马就可以被搜索到。只要

    数据被输入os cache中,buffer 就会被清空了,因为不需要保留buffer了,数据在translog里面已经持久化到磁盘去一份了。

    4、重复上面的步骤,新的数据不断进入buffer和translog,不断将buffer数据写入一个又一个新的segment file中去,每次refresh完buffer清空,translog保留。

    随着这个过程的推进,translog会变得越来越大。当translog达到一定长度的时候,就会触发commit操作。

    5、commit操作发生的第一步,就是将buffer中现有的数据refresh到os cache中去,清空buffer。然后将一个commit point写入磁盘文件,里面标识者这个commit

    point 对应的所有segment file,同时强行将os cache中目前所有的数据都fsync到磁盘文件中去。最后清空现有 translog日志文件,重启一个translog,此时commit操作完成。

    6、这个commit操作叫做flush。默认30分钟自动执行一次flush,但如果translog过大,也会触发flush。flush操作就对应着commit的全过程,我们可以通过es api,手动执行

    flush操作,手动将os cache中数据fsync强刷到磁盘上去。

    7、translog日志文件的作用是什么?

    执行commit 操作之前,数据要么是停留在buffer中,要么是停留在os cache中,无论是buffer 还是os cache都是内存,一旦这台机器死了,内存中的数据就全丢了。

    所以需要将数据对应的操作写入一个专门的日志文件translog中,一旦此时机器宕机了,再次重启的时候,es会自动读取translog日志文件中的数据,恢复到内存buffer

    和os cache中去。

    8、translog其实也是先写入os cache的,默认每隔5秒刷一次到磁盘中去,所以默认情况下,可能有5s的数据会仅仅停留在buffer或者translog文件的os cache中,如果

    此时机器挂了,会丢失5秒钟的数据。但是这样性能比较好,最多丢5秒的数据。

    也可以将translog设置成每次写操作必须是直接fsync到磁盘,但是性能会差很多。

    9、es第一是准实时的,数据写入1秒后就可以搜索到:可能会丢失数据的。有5秒的数据,停留在buffer、translog os cache 、segment file os cache中,而不在磁盘上,

    此时如果宕机,会导致5秒的数据丢失。

    10、总结::数据先写入内存buffer,然后每隔1s,将数据refresh到 os cache,到了 os cache数据就能被搜索到(所以我们才说es从写入到能被搜索到,中间有1s的延迟)。

    每隔5s,将数据写入到translog文件(这样如果机器宕机,内存数据全没,最多会有5s的数据丢失),translog达到一定程度,或者默认每隔30min,会触发commit操作,将缓冲区的

    数据都flush到segment file磁盘文件中。

    数据写入 segment file之后,同时就建立好了倒排索引。

    【数据先写入到buffer当中同时写入到translog当中,(buffer当中的数据是查不到的)。 每隔1s,将数据refresh到os cache(系统缓存),每个5s再放入到segment file磁盘文件当中】 重复进行此操作。

    当translog(日志文件)达到一定的长度时候会触发commit操作,commit操作发生的第一步,就是将buffer中现有的数据refresh到os cache中去,清空buffer。然后将一个commit point写入磁盘文件,里面标识者这个commit point 对应的所有segment file,

    同时强行将os cache中目前所有的数据都fsync到磁盘文件中去。最后清空现有 translog日志文件,重启一个translog,此时commit操作完成。

    五、删除/更新数据底层原理

    如果是删除操作,commit的时候会生成一个 .del文件,里面将某个doc标识为 deleted状态,那么搜索的时候根据 .del文件就知道这个doc是否被删除了。

    如果是更新操作,就是将原来的doc标识为deleted状态,然后重新写入一条数据。

    buffer 每refresh一次,就会产生一个segment file,所以默认情况下是1秒钟一个segment file,这样下来segment file会越来越多,此时会定期执行merge。

    每次merge的时候,会将多个segment file合并成一个,同时这里会将标识为 deleted的doc给物理删除掉,然后将新的segment file写入磁盘,这里会写一个commit point,标识所有新的 segment file,然后打开segment file供搜索使用,同时删除旧的segment file。

  • 相关阅读:
    面向对象编程思想(一)
    IT第十九天
    IT第十八天
    关于面试,来自无锡一位尊者的建议
    IT第十一天、第十二天、第十三天
    数据结构 3动态规划
    java 零碎1
    数据结构 2.迭代与递归
    数据结构 1.算法分析
    java 字符串(正则表达式)未完
  • 原文地址:https://www.cnblogs.com/it1042290135/p/14597918.html
Copyright © 2020-2023  润新知