1.Lucene
在PaaS的日志集中管理中,我们使用Elasticsearch作为底层的搜索引擎。在大数据、搜索引擎平台流行之前,用户对于数据的存储与检索是通过关系型数据库实现的。最基础的方法是将文本内容存储在数据库表中,通过SQL语言的like操作符来匹配文档。不同的数据库在like操作符上又引入了高级功能,例如用正则表达式来支持更灵活的查询。即便引入了各类高级方法,用户还是有大量的工作要做,比如对查询输入的分词管理、设计在海量数据上的弹性可伸缩方案等。针对以上问题,开源社区开发了一个全文搜索库——Lucene,注意它是一个库文件,也就是说开发人员能够使用它来构建自己的全文搜索引擎,它为开发人员提供了全文索引与查询的具体实现。Elasticsearch是基于Lucene库文件的搜索引擎,它是一个产品,开箱即用,提供丰富的接口来索引、检索数据。
Lucene是Elasticsearch的基础,它是一个独立的Java库文件,具有高性能、可扩展、轻量级的具体实现。作为一个全文检索引擎,其具有如下突出的优点。
- ·索引文件格式独立于应用平台。Lucene定义了一套以8位字节为基础的索引文件格式,使得兼容系统或者不同平台的应用能够共享建立的索引文件。
- ·在传统全文检索引擎的倒排索引的基础上实现了分块索引,能够针对新的文件建立小文件索引,提升索引速度。然后通过与原有索引的合并,达到优化的目的。
- ·优秀的面向对象的系统架构,使得对于Lucene扩展的学习难度降低,方便扩充新功能。
- ·设计了独立于语言和文件格式的文本分析接口,索引器通过接收Token流完成索引文件的建立,用户扩展新的语言和文件格式,只需要实现文本分析的接口。
- ·已经默认实现了一套强大的查询引擎,用户无须自己编写代码即可使系统获得强大的查询能力,在Lucene的查询实现中默认实现了布尔操作、模糊查询、分组查询等。
图12-10体现了应用程序与Lucene的关系,开发人员在应用程序中可通过Lucene实现索引与查询功能。Lucene采用的是一种被称为反向索引(Inverted Index)的机制。反向索引就是说我们维护了一个词/短语表,则对于这个表中的每个词/短语,都有一个链表来描述有哪些文档包含了这个词/短语。这样用户在输入查询条件时,就能非常快地得到搜索结果。对文档建立好索引后,就可以在这些索引上面进行搜索了。搜索引擎首先会对搜索的关键词进行解析,然后在建立好的索引上面进行查找,最终返回和用户输入的关键词相关联的文档。
图12-10 应用程序与Lucene的关系
2.Elasticsearch
Elasticsearch是基于Lucene库构建的开源搜索引擎平台,它用Java语言实现,以RESTful的Web接口对外提供服务,交互内容采用JSON文档格式,其作者谢伊巴农(Shay Banon)于2010年将其开源贡献给了社区,之后Elasticsearch快速发展,目前和Solr(另一个流行搜索引擎平台)并驾齐驱,成为互联网上最流行的两大企业搜索引擎平台。也许你对Lucene和Elasticsearch都有了一定的了解,但我们还是从介绍一些基本概念来认识Elasticsearch。
1)数据结构概念
Elasticsearch是这样定义数据结构的。
•Index
在Elasticsearch中,“Index”是一个名词,它将数据存放在一个或者多个Index中。Index这个词很容易产生歧义,因为在计算机中它代表索引这个动作或者代表数据的索引。如果将其与关系型数据库进行类比,则实际上Index相当于之前数据库中的一张表,用来存储用户的相关数据。
•Document
Document是从Lucene中引入的一个概念,它相当于关系型数据库的一行记录。在Lucene搜索世界中,所有数据对象都是以文档方式存在的。在数据的结构化要求上,文档型(Document)要比行(Row)松散很多。在Document中也包含了很多字段(Field),这与关系型数据库行中的字段是一样的,但Document没有严格的规定一个文档有哪些字段及字段类型是什么,因此用户在将一个文档存储到一个Index时,可以灵活地增加、减少相关字段。Document遵循JSON格式,结合Logstash来看,最终从Logstash中输出的就是一个包含多字段的Document。
•Mapping
Mapping是Elasticsearch中很重要的一个概念,刚刚说过在Elasticsearch中并没有类似于关系型数据库中的Schema概念,我们并不需要定义在一个Document中要有哪些字段。但是当Document发送过来并进行存储前,Elasticsearch需要首先对文档中的字段进行索引,我们依据什么规则来进行索引呢?我们将Mapping理解为对字段进行索引的规则。一个Mapping由一个或多个Analyzer组成,一个Analyzer又由一个或多个Filter组成。Elasticsearch在索引文档时,把字段中的内容传递给相应的Analyzer,Analyzer再传递给各自的Filter。这些Filter完成最终的索引工作,包括分词、大小写忽略及删除标签等。Document中的字段默认为对应的Mapping,Elasticsearch依据字段的类型来分配默认的Mapping,当然用户可以自定义Mapping,并在对文档进行索引前指定字段的Mapping。
2)组件概念
•Node和Cluster
Elasticsearch以单实例形式运行Node。单实例部署的Elasticsearch的Node可以满足一些基础场景的需求,但在生产环境涉及可用性、容错性、高性能等要求时,会将多个Node组合成一个Cluster集群。
•Shard
在集群部署的Elasticsearch多节点中,为了提升整体的性能,Elasticsearch会将数据存储到多个节点的Lucene Index中,只有将这些节点中的数据聚合在一起才是一个完整的Index,每个节点上的数据被称为Shard,代表Index的一段分片。在用户向Cluster提交一次查询动作时,Elasticsearch内部会自动完成各个节点之间的交互,从每个Shard中检索数据并完成聚合操作。
•Replica
Shard用于将一份全量数据分成多片,放到不同的集群节点来提升检索性能。Replica是一份Shard的复制,它的作用是对同一份数据提供冗余,防止在某节点失效时数据丢失;同时Replica的份数越多,读取操作的性能也会有很大的提升。
•Gateway
Elasticsearch运行时会产生大量的关于集群状态、Index设置相关的元数据信息,这些数据在Gateway中持久化。
3)索引与查询
搜索引擎平台提供的两个主要操作接口是索引、查询,在Elasticsearch集群中由于Index数据分散到各个节点中的Shard中,并且每一个Shard还有自己的冗余备份Replica,因此每一次索引与查询动作都涉及Cluster集群中的多节点交互。
Elasticsearch的索引接口有多种方式,我们可以使用HTTP发起索引访问,将文档发送给Elasticsearch,也可以采用无状态的UDP,牺牲可靠性来提供请求性能。一个请求索引的文档有一个或者自动生成一个Document ID,Elasticsearch依据此ID来判断该文档应该被存储在哪个Shard中,只有Shard所在的节点才能完成索引动作,Replica节点仅仅同步数据和提供查询。如图12-11所示是一个索引操作流程,客户端发起一个文档索引请求,它可以连接到Cluster集群中的任意一个节点。在该例中连接的是node_2,node_2对Document ID进行判断,发现数据应当由node_1上的shard_2来处理,于是它将请求转发到node_1。
图12-11 索引操作流程图
Elasticsearch的检索请求要比索引更加复杂,在一个Cluster集群环境中,Elasticsearch必须询问所有的Node,将获取的数据汇总后才发送给用户。如图12-12所示是一次数据检索操作,客户端发起请求给node_2,node_2内部会对用户发起的检索请求进行处理,搜索相关数据,同时会与集群内的其他节点进行通信,收集在其他节点检索出来的数据,最后,所有节点将数据发送到node_2中进行汇总,统一返回给客户端。
图12-12 数据检索操作