Elasticsearch原理

106 阅读3分钟

这是我参与11月更文挑战的第28天,活动详情查看:2021最后一次更文挑战

数据如何存储

每次新收到的数据会写到新的索引文件里,每次生成的倒排索引叫做segment, 使用commit文件记录索引中所有的segment,生成segment的数据来源是buffer。

数据写入buffer的时候,还会记录translog日志。refresh发生的时候translog保持原样,如果这期间发生异常,ES会从commit位置开始,恢复整个translog文件的记录,保持数据一致性。当refresh完成,从commit文件更新后,translog文件清空,这个步骤是flush, 可以调用_flush接口。可以通过index.translog.flush_threshold_periodindex.translog.flush_threshold_size 参数修改. 默认30分钟或文件大于512M主动进行flush。

ES每5秒或每次请求操作结束前,强制刷新translog日志到磁盘。

ES不断在后台运行任务,将零散的segment做数据归并, 尽量让索引内只保有少量的,每个都比较大的segment文件, 由单独的线程来进行的, 并不影响新的segment产生。归并完成后, 较大的segment刷新到磁盘,commit文件作出相应的变更, 删除之前的小segment,合成大的segment。

近实时搜索怎么实现的

segment刷新到文件系统缓存, 就可以检索新的segment, 文件系统缓存真正刷新到磁盘, commit文件更新。刷新到文件系统缓存的这个步骤, 默认设置1秒,或通过调用_refresh实现。

路由和副本的读写过程

路由

默认使用shard = hash(routing) % number_of_primary_shards公式进行计算,routing参数默认情况下使用_id值, _id计算哈希后, 对索引主分片数取余

副本

数据写入流程:

  • 请求发送给Node1节点
  • Node1用数据的_id取余得到应将数据存储的分片, 通过cluster state信息可以发现分片的主分片分配到的node,转发数据给对应Node
  • Node完成请求数据的索引过程,存入主分片0, 并行转发数据给分配有这个分片的副本分片的Node1和Node2, 当收到任一节点汇报副本分片数据写入成功, Node就返回给初始的节点Node1,宣布数据写入成功,Node1返回成功响应给客户端

参数wait_for_active_shards控制需要有几个节点写入成功才算成功

节点选举

ZenDiscovery是ES自己实现的一套用于节点发现和选主等功能的模块。 ES采用了常见的分布式系统思路,保证选举出的master被多数派(quorum)的master-eligible node认可,以此来保证只有一个master。这个quorum通过以下配置进行配置:discovery.zen.minimum_master_nodes: ``2

当一个master-eligible节点发现满足以下条件时发起选举:

  • 节点的当前状态不是master。
  • 节点通过ZenDiscovery模块的ping操作询问其已知的集群其他节点,没有任何节点连接到master
  • 包括本节点在内,当前已有超过minimum_master_nodes个节点没有连接到master。

选举方法:

  • 先根据节点的clusterStateVersion比较,clusterStateVersion越大,优先级越高。
  • clusterStateVersion相同时,进入compareNodes,其内部按照节点的Id比较(Id为节点第一次启动时随机生成)。