Elasticsearch学习笔记(二)单节点准实时索引的实现
为什么要学习架构?
Elasticsearch的一些架构设计,对我们做性能调优、故障处理,具有非常重要的影响。下面将从Elasticsearch
的准实时索引的实现、自动发现、rounting和replica的读写过程,shard的allocate控制
使文本可以被搜索?
在传统的数据库中,一个字段存一个值,但是这对于全文搜索是不足的。想要让文本中的而每个单词都可以
被搜索,这意味着数据库需要多个值。
支持一个字段多个值的最佳数据结构是倒排索引。倒排索引包含了出现在所有文档中唯一的值或或词的有序列
表,以及每个词所属的文档列表。
倒排索引存储了比包含一个term的文档列表多地多的信息,它可能包含每一个term的文档数量,一个term出现
在制定文档中的频次,每个文档中term的顺序,每个文档的长度,所有文档的平均长度等等。这些统计信息使
Elasticsearch知道哪些term更重要,哪些文档更重要,也就是相关性。
在全文搜索的早些时候,会为整个文档集合建立一个大索引,并且写入磁盘。只有新索引准备好了它就会替代
旧的索引,最近的修改可以被检索。
不可变性
写入磁盘的倒排索引是不可变的,它有如下好处:
- 不需要锁。如果从来不需要跟新一个索引,就不必担心多个程序见同时尝试修改。
- 一旦索引被读入文件系统的缓存,它就一直在那儿,因为不会改变。只要文件系统缓存有足够的空
- 在索引的声明周期内,所有的其他缓存都可用。他们不需要再每次数据变化了都重建,因此数据不会变。
- 写入单个大的倒排索引,可以压缩数据,较少的磁盘IO和需要缓存索引的大小。
当然,不可变的索引有它的缺点,首先是它不可变。如果想要搜索一个新文档,必须重建整个索引。这不仅限
制了一个索引所能装下的数据,还有一个索引可以被更新的频次。
准实时索引的实现?
本文主要介绍Elasticsearch的准实时索引的实现,至于基于Lucene的倒排索引将不在这里介绍,有兴趣的读者
可以去Lucene的相关文章,或者阅读《Lucene in Action》等书籍。下面将介绍Elasticsearch索引流程中发生的
具体操作,重点在于其中的segment、buffer和translog三部分对性能方面的影响。
1、动态更新的Lucene索引
要做到实时跟新条件下数据的可用和可靠,就需要在倒排索引的基础上,再做一系列更高级的处理。
总结一下Lucene的处理办法:新收到的数据写入新的索引文件里。
Lucene把每次生成的倒排索引,叫做一个段(segment)。然后另外使用一个commit文件,记录索引内的所有
segment。而生成segment的数据来源,则是内存中的buffer,也就是说,动态跟新过后过程如下:
1)当前磁盘上有三个segement可用,同时有一个commit文件记录当前的segment
2)新收到的数据进入内存buffer,索引状态如下所示。
3)buffer刷到磁盘,生成一个新的segment,commit文件同步跟新。
这样可以完成跟新,也产生了几个问题:1、每次一有数据就刷新到磁盘,会增大对磁盘的操作2、刷新到磁盘的
时间占据很大一部分时间3、如果刷新的过程中刷新失败应该怎么控制呢?