elasticsearch

Scaling Lucene

怎样在Lucene之上构建一个分布式、高度伸缩、接近实时的搜索引擎呢?

  • building blocks
  • partitioning 分区策略最佳的将lucene的索引文档分割到多个分布式的分片中去
  • replication 分区复制方式保证系统的高可用性以及提高搜索的吞吐
  • transaction log 事务日志保证数据一致性

Building Blocks

当我们要构建一个分布式接近实时的搜索引擎,并且要让lucene可伸缩扩展,必须首先知道lucene的关键概念一个他们于我们要达成目标的一些局限性。

Directory

Lucene Directory是一个抽象的文件系统的接口,用来允许你读写文件,不管lucene的索引是存放在内存中还是物理磁盘上,他都是通过lucene的Directory抽象层来访问和维护的。

IndexWriter

IndexWriter用来添加、删除、更新lucene里面的索引文档。这些操作是在内存中完成以保证更好的性能,但是如果要保证这些操作的持久化,这些操作是需要flush到磁盘的。并且,flush操作或者显失的commit提交开销都是很大的,因为这些操作通常需要处理很多的文件,而处理这些文件有涉及到大量的磁盘IO。

此外,每次只能有一个IndexWriter对象来对一个索引目录进行索引操作,并且创建这个对象开销很大,所以次序尽可能去重用这个对象。

Index Segmentgs

lucene索引被分解为很多段(segments)。每个索引段实际上时一个功能完整的lucene索引,一旦一个索引段创建完成,他将是不可变的,并且不能删除段里面的索引文档。commit提交操作用来往索引段里面添加一个新段。lucene内部会来对这段进行合并,所以我们必须要有策略来控制这些合并。(MergePolisy, MergeScheuler, … etc)。Because segments need to be kept at bay they are being merged continuously by internal Lucene processes (MergePolisy, MergeScheuler, … etc).

因为这些段是不可变的,所以可以用来作缓存(caching)是一个很好的选择,你可以加载所有的term词条并且创建一个跳跃列表(skip lists),或者用来构造FieldCache,如果段没有变化,你就不需要重新加载。

IndexReader

IndexReader用来执行搜索索引。这个对象通过IndexWriter来提供,并且创建代价也是比较高。一旦IndexReader打开之后,他就不能够发现打开之后的索引变化,如果要知道这些由IndexWriter产生的索引变化,除非刷新IndexReader对象(当然前提需要flush操作)。搜索操作在内部其实是按段来进行的(每次一个段)。

Near Real-Time Search

获取一个新的IndexReader开销很大,所以也是我们不能每次已有索引操作就真得去获取一个新的IndexReader,你可以隔一段时间去刷新以下,比如每隔一秒钟等。这也是在这里称之为接近实时(near real-time)的原因。

可能用来伸缩Lucene的途径(Possible approach to Scale Lucene)

Distributed Directory

其中一种途径用来伸缩Lucene就是使用分布式文件系统,大文件会被拆分成chunks块并且会保存到分布式文件系统(比如Coherence、Terracata、Gigapaces or Infinispan等等)。这样,IndexWriter和IndexReader都是工作在一个自定义的Directory分布式实现上,每个操作后面其实是分不了很多个节点,每个节点上面存储了索引文件的一部分。

但是这种方案会有一些问题:

  • 产生密集的网络流量。
  • 大的索引必然会时IndexReader变的无法分布式
  • 索引操作也会变得非常困难,因为只有一个单一的IndexWriter能够写索引。

Partitioning

有两种通过将数据分区方式来scale搜索引擎:基于文档(Document based partitioning)和基于词条(Term based partitioning),ES使用的基于文档的分区方式。

基于文档的分区

每一个文档只存在一个分区,每个分区持有整个文档集的一个子集,分区时一个功能完整的索引。

基于词条的分区

Replication

分布式系统的另外一个方面就是复制(replication)了,通过复制可以得到2个主要的好处:

  • High Availability (HA高可用性)
  • scalability (可伸缩性)

一般有两种方式来实现复制:Push Replication (推模式)和Pull Replication(拉模式)。ES使用的是推模式。

Push Replication

Pull Replication

Transaction Log

如前面所述,索引提交(commit)的开销是在太大,但是我们由必须通过提交操作来保证数据被可靠的持久化,如果拥有数据的节点突然崩溃的话,那么最后一个提交操作之后产生的数据操作将会丢失。

数据可靠性(Data Persistency)

Shared gateway snapshot(快照)

peer shared recovery(分片恢复)

shared “Hot”relocation(分片热迁移)

你可能感兴趣的:(elasticsearch)