Elasticsearch源码解析与优化实战-Elasticsearch介绍

Scroll Down

基本概念和原理

Elasticsearch是实时的分布式搜索分析引擎,内部使用Lucene做索引与搜索。
何谓实时?新增到ES中的数据在1秒后就可以被检索到,这种新增数据对搜索的可见性称为准实时搜索。分布式意味着可以动态调整集群规模,弹性扩容,而这一切操作起来都非常简便,用户甚至不必了解集群原理就可以实现。集群规模支持上千个节点,但是分片总数量不宜过多,主节点在管理大量分片时会有比较大的压力。因此,目前我们认为ES更适合中等数据量的业务,尽量避免产生单个集群存储数十万分片的场景。
Lucene是Java语言编写的全文搜索框架,用于处理纯文本的数据,但它只是一个库,提供建立索引,执行搜索等接口,但不包含分布式服务,这些正是ES做的。什么是全文?对全部的文本内容进行分析,建立索引,使之可以被搜索,因此称为全文。

索引结构

ES是面向文档的,各种文本内容以文档的形式存储到ES中,文档可以是一封邮件,一条日志,或者一个网页的内容。一般使用JSON作为文档的序列化格式,文档可以有很多字段,在创建索引的时候,我们需要描述文档中每个字段的数据类型,并且可能需要指定不同的分析器。
在存储结构上,由_index、 _type、和_id唯一标识一个文档。

_index指向一个或多个物理分片的逻辑命名空间,_type类型用于区分同一个集合中的不同部分,在不同的部分中,数据的整体模式是相同或相似的,不适合完全不同类型的数据。多个_type可以在相同的索引中存在,只要它们的字段不冲突即可,_id文档标记符由系统自动生成或使用者提供。

分片(shard)

在分布式系统中,单机无法存储规模巨大的数据,要依靠大规模集群处理和存储这些数据,一般通过增加机器数量来提高系统的水平扩展能力。因此,需要将数据分成若干小块分配到各个机器上。然后通过某种路由策略找到某个数据块所在的位置。
除了将数据分片以提高水平扩展能力,分布式存储中还会把数据复制成多个副本,放置到不同的机器中,这样一来可以增加系统的可用性,同时数据副本还可以使读操作并发执行,分担集群压力。但是多数据副本也带来了一致性的问题:部分副本写成功,部分副本写失败。
为了应对并发更新问题,ES将数据副本分为主从两部分,即主分片(primary shard)和副分片(replica shard)。主数据作为权威数据,写过程中先写主分片,成功后再写副分片,恢复阶段以主分片为准。
分片(shard)是底层的基本读写单元,分片的目的是分割巨大索引,让读写可以并行操作,由多台机器共同完成,读写请求最终落到某个分片上,分片可以独立执行读写工作。ES利用分片将数据分发到集群内各处。分片是数据的容器,文档保存在分片内,不会跨分片存储。分片又被分配到集群内的各个节点里,当集群规模扩大或缩小时,ES会自动在各个节点中迁移分片,使数据依然均匀分布在集群里。
一个ES索引包含很多分片,一个分片是一个Lucene的索引,它本身就是一个完整的搜索引擎,可以独立执行建立索引和搜索任务,Lucene索引又由很多分段组成,每个分段都是一个倒排索引。ES每次refresh都会生成一个新的分段,其中包含若干个文档的数据。在每个分段内部,文档的不同字段被单独建立索引。每个字段的值由若干词(Term)组成,Term是原文本内容经过分词器处理和语言处理后的最终结果。
索引建立的时候就需要确定好主分片数。

动态更新索引

为文档建立索引,使其每个字段都可以被搜索,通过关键词检索文档内容,会使用倒排索引的数据结构。倒排索引一旦被写入文件后就具有不可变性,不变性具有许多好处;对文件的访问不需要加锁,读取索引时可以被文件系统缓存等。

近实时搜索

在写操作中,一般会先在内存中缓冲一段数据,再将这些数据写入磁盘,每次写入磁盘的这批数据称为一个分段,如同任何写操作一样,一般情况下(direct方式除外),通过操作系统write接口写到磁盘的数据先到达系统缓存(内存),write函数返回成功时,数据未必被刷到磁盘,通过手工调用flush,或者操作系统通过一定策略将系统缓存刷到磁盘。这种策略大幅度提升了写入效率。从write函数返回成功开始,无论数据有没有被刷到磁盘,该数据已经对读取可见。

段合并

在ES中,每秒清空一次写缓冲,将这些数据写入文件,这个过程称为refresh,每次refresh会创建一个新的Lucene段。但是分段数量太多会带来较大的麻烦,每个段都会消耗文件句柄、内。每个搜索请求都需要轮流检查每个段,查询完再对结果进行合并;所以段越多,搜索也就越慢。因此需要通过一定的策略将这些较小的段合并为大的段,常用的方案是选择大小相似的分段进行合并。在合并过程中,标记为删除的数据不会写入新分段,当合并过程结束,旧的分段数据被删除,标记删除的数据才从磁盘删除。