基本概念
Elasticsearch是实时的分布式搜索分析引擎,内部使用Lucene进行索引与搜索。 特点:
- 准实时:新增数据秒级可以被检索到
- 分布式:支持动态调整集群规模,弹性扩容。目前,ES比较适合中等数据量的业务,支持“上百”个节点,不适合存储海量数据。
- Lucene:全文检索框架,提供建立检索、执行搜索等接口。
索引结构
ES是面向文档的,一般使用json作为文档的序列化格式。
在存储结构上,由_index, _type, _id唯一标识一个文档。(_type已经废弃了)
分片(shard)
一个索引可以分为多个分片。同一个分片可以存在多个副本。为了应对并发更新问题,ES将数据副本分为主从两部分,即主分片(primary shard)和副分片(replica shard)。主数据作为权威数据,写过程先写主分片,成功后在写副分片,恢复阶段以主分片为准。(主从模式)
一个ES索引可以包含多个分片,一个分片对应一个Lucene索引,它本身是一个完整的搜索引擎,可以独立执行索引和搜索任务。Lucene索引又由很多分段(Segment)做成,每个分段都是一个倒排索引。ES每次“refresh”都会生成一个新的分段,其中包含若干文档的数据。在每个分段内部,文档的不同字段被单独建立索引。每个字段的值由若干词(Term)组成,Term是原文本内容经过分词器处理和语言处理后的最终结果。
段合并
在ES中,每秒清空一次写缓冲,将这些数据写入文件,这个过程称为refresh,每次refresh会创建一个新的Lucene段。因此需要通过一定的策略将这些较小的段合并为大的段,常用的方案是选择大小相似的分段进行合并。在合并过程中,标记为删除的数据不会写入新分段,当合并过程结束,旧的分段数据被删除,标记删除的数据才从磁盘删除。
集群内部原理
ES使用主从(Master-Slave)模式。
集群节点角色
- 主节点(Master node) 主节点负责集群层面的相关操作,管理集群变更。主节点是全局唯一的,将从有资格称为master的节点中进行选举。
- 数据节点(Data node) 负责保存数据、执行数据相关操作:CRUD、搜索、聚合等。
- 协调节点(Coordinating node) 协调节点负责处理客户端的请求,然后将请求转发给保存数据的数据节点。然后,将每个数据节点的结果合并为单个全局结果。
- 其他:预处理节点(Ingest node)、部落节点(Tribe node)。
集群健康状态
- Green,所有的主分片和副分片都正常运行。
- Yellow,所有的主分片都正常运行,但不是所有的副分片都正常运行。
- Red,有主分片没能正常运行。 每个索引也有上述三种状态。
集群状态
集群状态元数据是全局信息,元数据包含内容路由信息、配置信息等,其中最重要的是内容路由信息,它描述了“哪个分片位于哪个节点”的路由信息。
集群状态由主节点负责维护,如果主节点从数据节点接收更新,则将这些更新广播到集群的其他节点,让每个节点上的集群状态保持最新。
集群扩容
当扩容集群、添加节点时,分片会均衡地分配到集群的各个节点,从而对索引和搜索过程进行负载均衡,这些都是系统自动完成的。
主要内部模块简介
cluster
cluster模块是主节点执行集群管理的封装实现,管理集群状态,维护集群层面的配置信息。主要功能如下:
- 管理集群状态,将新生成的集群状态发布到集群的所有节点。
- 调用allocation模块执行分片分配,决策哪些分片应该分配到哪个节点。
- 在集群各节点中直接迁移分片,保持数据平衡。
allocation
封装了分片分配相关的功能和策略,包括主分片的分配和副分片的分配,本模块由主节点调用。创建新索引、集群完全重启都需要分片分配的过程。
discovery
discovery模块负责发现集群中的节点,以及选举主节点。从某种角度来说,发现模块起到类似ZooKeeper的作用,选主并管理集群拓扑。
gateway
负责对收到master广播下来的集群状态(cluster state)数据的持久化保存,并在集群完全重启时恢复它们。
indices
indices模块管理全局级的索引设置,不包括索引级的(索引设置分为全局级和每个索引级)。 它还封装了索引数据恢复功能。集群启动阶段需要的主分片恢复和副分片恢复就是在这个模块实现的。
HTTP
HTTP模块允许通过JSON over HTTP的方式访问ES的API,HTTP模块本质上是完全异步的,这意味着没有阻塞线程等待响应。使用异步通信进行 HTTP 的好处是解决了 C10k 问题(10k量级的并发连接)。
Transport
传输模块用于集群内节点之间的内部通信。从一个节点到另一个节点的每个请求都使用传输模块。 传输模块使用 TCP 通信,每个节点都与其他节点维持若干 TCP 长连接。内部节点间的所有通信都是本模块承载的。
engine
engine模块封装了对Lucene的操作及translog的调用,它是对一个分片读写操作的最终提供者。
Guice
ES使用Guice框架进行模块化管理。Guice是Google开发的轻量级依赖注入框架(IoC)。
模块结构
在Guice框架下,一个典型的模块由Service和Module类(类名可以自由定义)组成,Service用于实现业务功能,Module类中配置绑定信息。
AbstractModule是Guice提供的基类,模块需要从这个类继承。Module类的主要作用是定义绑定关系。
模块管理
定义好的模块由ModulesBuilder类统一管理,ModulesBuilder是ES对Guice的封装,内部调用Guice接口,主要对外提供两个方法。
- add方法:添加创建好的模块
- createInjector方法:调用Guice.createInjector创建并返回Injector,后续通过Injector获取相应Service类的实例。