elasticsearch 学习笔记02

2018-10-25  本文已影响4人  咸鱼佬

Match Query

对字段作全文检索、常使用Api


image.png

查询流程

对查询语句分词、将其分为alfred 和 way 然后分别根据username的倒排索引进行匹配算分、然后再进行汇总得分、然后根据得分进行排序返回文档给客户端

相关性算分

相关性算分是指文档与查询语句间的相关度、英文relevance
通过倒排索引可以获取与查询语句相匹配的文档列表、那么如何将最符合用户查询需求的文档放在前列

相关性算分有几个重要的概念如下:

相关性算分模型

主要有两个

  1. TF/IDF 模型
  2. BM25 模型 beast match 25(25指迭代了25次才计算方法)
image.png

Cluster Status

es集群相关的数据称为cluster status、主要记录如下信息:

  1. 节点信息、比如说节点的名称、连接地址
  2. 索引信息、比如说索引名称、配置等
  3. cluster status 存储在每一个节点上、master维护最新版本并同步给其他节点

Master 节点

Coordinating 节点

数据节点

存储数据的节点称为data 节点、默认节点都是data类型、相关配置node.data:true

分片

分片数的设定很重要、需要提前规划好

  1. 过小会导致后续无法通过增加节点实现水平扩容
  2. 过大会导致一个节点分布过多分片、造成资源浪费、同时也会影响查询性能

cluster health

分布式特性

es 集群由多个es实例组成

  1. 不同集群通过集群名字来区分、可以通过cluster.name进行修改、默认为elasticsearch
  2. 每个es实例本质上是一个jvm进程、且有自己的名字、通过node.name进行修改

故障转移

image.png
image.png
image.png
image.png

文档分布式存储

文档最终会存储在分片上、那么document是如何存储到某一个分片上、选择这个分片的原因是啥

这个就涉及到文档到分片的映射算法
需要这么做的目的就是使文档均匀的分布在所有的分片上、以充分利用资源

es通过如下公式计算文档对应的分片

shard = hash(routing) % number_of_primary_shards
hash 算法可以保证可以将数据均匀地分散在分片中
routing是一个关键参数、默认是文档id、也可以自行指定
number_of_primary_shards 是主分片数
该算法与主分片数相关、这也是分片数一旦确定后便不能改变的原因

文档创建和读取流程

image.png
image.png

脑裂问题

split-brain 是分布式系统中经典的网络问题

image.png

解决方案就是 仅在可选举master-eligible 节点数大于等于quorum 时才可以进行master选举
quorum = master-eligible 节点数/2 + 1 例如三个master-eligible 节点时、quorum 为2
通过设定discovery.zen.minimun_master_nodes 为quorum 避免脑裂

倒排索引的不可变更

倒排索引一旦生成、不能更改
好处如下

文档搜索的实时性

但是倒排索引不可变带来的坏处就是写入新文档时、必须重新构建倒排索引文件、替换老文件后、新文档才能被检索、导致文档的实时性差

而这个的解决方法就是 新文档直接生成新的倒排索引文件、查询的时候同事查询所有的倒排文件、然后做结果汇总计算即可

image.png

Lucene 便是采用这种解决方案、它构建的单个倒排索引称为 segment 合在一起称为Index 与ES的Index概念不同、ES中的一个Shard 对应一个Lucene

Lucene 会有一个专门的文件记录所有的segment 信息、称为commit point

image.png

segment 写入磁盘的过程依然很耗时、可以借助文件系统缓存的特性、先将segment在缓存中创建并开放查询进一步来提升实时性、该过程在es中称为refresh

在refresh之前文档会先存储在一个buffer中、refresh时将buffer中的所有文档清空并生成segment

es默认每一秒执行一次refresh、因此文档的实时性被提高到一秒、这也是es被称为近实时的原因

image.png

translog

如果在内存中的segment还没有写入到磁盘前发生了宕机、那么其中的文档就无法恢复了、如何解决这个问题

es引入translog 机制、写入文档到buffer时、同时将该操作写入到translog。

translog 文件会即时写入到磁盘(fsync)、6.x默认每个请求都会写入请求、就是每个请求都会马上写入到磁盘中持久化、 这个值可以通过 index.translog.*去修改 比如设置为5秒写一次、那么这样子就会有丢失 5 秒内的数据
es 启动时会检查translog 文件、并从中恢复数据
每个分片都有自己的translog文件

flush

flush 负责将内存中的segment写入磁盘、主要做如下工作

  1. 将还在内存中的translog写入到磁盘中(index.translog.* 这个参数是否是实时落盘)
  2. 将index buffer 清空、其中的文档生成一个新的segment、相当于一个refresh操作
  3. 执行fsync操作、将内存中的segment写入磁盘中、
  4. 更新commit point 并写入磁盘
  5. 删除translog 文件
image.png

refresh触发时机

  1. 间隔时间达到、通过index.settings.refresh_interval来设定、默认是 1秒
  2. index.bffer占满时、其大小通过indices.memory.index_buffer_size设置、默认为jvm heap的10% 所有shard共享
  3. flush 发生时也会发生refresh

flush发生的时机

  1. 间隔时间达到时、默认是30分钟、5.x之前可以通过index.transog.flush_threshold_period修改、之后就无法修改
  2. translog占满时、其大小可以通过index.translog.flush_threshold_size控制、默认是512mb 每个分片都有自己的translog
  3. segment合并的时候

删除和更新文档

segment一旦生成就不能更改、那么如果你要删除文档该如何操作

  1. Lucene专门维护一个.del的文件、记录所有已经删除的文档、注意.del上记录的是文档在Lucene内部的id
  2. 查询结果返回前会过滤掉.del中的所有文档

更新文档如何进行

segment合并

随着segment的增多、由于一次性查询的segment数量增多、查询速度会变慢
es会定时在后台进行segment merge操作、减少segment的数量、小段合并成大、再合成更大的段、尚未flush的segment可以与已经flush的segment合并
合并的时候会触发 flush操作、也会删除对应的.del 文件

整体视角

image.png
上一篇下一篇

猜你喜欢

热点阅读