构建在全文检索开源软件Lucene之上的Elasticsearch,其实已经蜕变为一个完整的分布式大数据分析平台。它能对海量规模数据完成实时分析,完成分布式索引与检索,提供数据聚合功能,应用非常广泛,图1.2是部分采用Elasticsearch作为其搜索业务基础的公司。下面是国外一些著名企业使用Elasticsearch的例子 [3] 。
图1.2 使用Elasticsearch的部分知名IT企业
Elasticsearch是由Shay Banon发起的一个开源搜索服务项目,并于2010年2月公开了源码。Elasticsearch不仅仅能提供全文检索功能,它还能提供高效的分布式数据存储、索引、搜索,能完成对大数据的自动分片、自动负载索引,并提供RESTful Web的风格接口。
Tips: REST(REpresentational State Transfer)意即“表现层状态转化”,RESTful是目前流行的一种互联网软件架构,具有结构清晰、符合标准、易于理解、扩展方便等特点,这种架构下的每一个URI代表一种资源,客户端通过GET(获取资源)、POST(新建或更新资源)、PUT(更新资源)、DELETE(删除资源)方式来对服务器端资源进行操作。
Elasticsearch是面向文档型的NoSQL数据库,可以在Elasticsearch中索引、搜索、排序和过滤这些文档。它不仅继承了Lucene的简洁语法表述,同时还可以进行以下工作:
另外,Elasticsearch支持插件机制,如与mongoDB、couchDB同步的River插件、中文分词插件、Hadoop插件、脚本支持插件等。在使用Elasticsearch时,有很多基础服务可以用插件的方式来提供。
其实,Elasticsearch的优点很多,比如它执行搜索的速度更快,可以简单地通过HTTP方式,使用JSON来操作数据,并支持对分布式集群的搜索。这也是很多Lucene用户在面对大数据时转而使用Elasticsearch的原因之一。Elasticsearch的一个主要的特点是对分布式的支持,其索引能分拆为多个分片,每个分片可有零或多个副本,集群中的每个数据节点都可承载一个或者多分片,并且能协调和处理各种操作;负载再平衡(Rebalancing)和路由(Routing)在大多数情况下都是自动完成的。
参照文献 [16] ,这里给出有关Elasticsearch中相关概念的解释。
(1)Cluster和Node——Elasticsearch中的Cluster是对外提供搜索服务的集群,组成这个Cluster的各个节点叫做Node。节点Node是Elasticsearch运行的实例;集群Cluster是一组有着同样cluster.name的节点,它们协同工作,互相分享数据,提供了故障转移和扩展的功能。Node又可分为IndexNode(提供读写)、DataNode(只提供数据存储和访问,负载均衡)等。节点之间是对等关系的(去中心化),而弱化的Master节点只不过多了维护集群状态的功能。每个节点上面的集群状态数据都是实时同步的。如果Master节点出故障,按照预定的程序,其他一台Node机器会被选举成为新的Master。从这点来看,它就比某些大数据处理平台的鲁棒性强 [6] 。
(2)Shards——Elasticsearch将一个完整的索引分成若干部分,每个部分就是一个Shards,每个Shard实际上就是一个基于Lucene的索引。Shards存储在相同或不同的Node上;Shards的数量一般在索引创建前指定,且索引创建后不能更改(其初始配置也是可以修改的)。检索时,Elasticsearch会将查询发送到不同的Shards上并将返回结果合并,这个过程对用户来说是透明的。
(3)Replicas——Replicas是索引的冗余备份,可用于防止数据丢失或用来做负载均衡。一般地,Elasticsearch会自动对搜索请求进行负载均衡。
(4)Recovery——在有节点加入或退出集群Cluster或故障节点重新启动时,Elasticsearch会根据机器的负载情况,对索引分片Shards进行重新分配。
(5)River——River是一个运行在Elasticsearch集群内部的插件,主要用来从外部获取异构数据,然后在Elasticsearch里创建索引。常见的有couchD Briver Plugin、RabbitMQ river Plugin、Twitter river Plugin、Wikipedia river Plugin、MongoDB river Plugin、JDBC river Plugin等。
(6)Gateway——是Elasticsearch索引数据快照的存储方式,当Elasticsearch集群关闭再重新启动时,就会从Gateway中读取索引数据快照。Elasticsearch支持多种类型的Gateway,有本地文件系统(像普通的Lucene索引一样,这也是默认方式)、分布式文件系统(如freeds)、Hadoop的HDFS和Amazon的S3云存储服务等。
Tips: Gateway与workDir的区别:Gateway存储完整的索引数据,workDir对外提供相应查询操作;Gateway可以是本地文件系统、共享文件系统或HDFS等云存储,workDir可以是内存、本地文件系统或两者结合;Gateway被假设是可靠的,持久化的数据存储,workDir被假设是不安全的运行环境,数据允许丢失。
(7)Discovery.zen——Discovery.zen代表Elasticsearch的自动发现节点机制。Zen用来实现节点自动发现和Master节点选举,Master节点负责处理节点的加入和退出以及分片Shard的重新分配。Master不是固定不变的,当前Master出故障后,其他节点自动选举产生新的Master。只有当节点准备就绪以后,该节点才会被通知可以被使用。在config/elasticsearch.yml中可以进行相应参数的设置。
Tips: Elasticsearch是一个基于P2P的系统,它通过广播机制寻找存在的节点,再通过多播协议来进行节点间的通信,同时也支持点对点的交互。因此,需要节点发现与Master选举机制。
(8)Transport——Transport代表Elasticsearch内部节点或集群与客户端的交互方式,默认内部是使用TCP协议进行交互,同时它支持HTTP协议(JSON格式)、Thrift、Servlet、Memcached、ZeroMQ等的传输协议(通过插件方式集成)。
(9)Index、Type、Document、Field——Index是Elasticsearch存储数据的地方,可以快速高效地对索引中的数据进行全文索引,类似于RDBMS数据库中的Database;在Index下一般会有多个存放数据的Type,Type类似于Database中的Table,用来存放具体数据;Document是类似关系数据库的一行数据,在一个Type里的每一Document都有一个唯一的ID作为区分,这里与RDBMS不同的是,Document不需要有固定的结构,不同文档可以具有不同的字段集合;Field类似关系数据库的某一列,是Elasticsearch数据存储的最小单位。
为了更好地理解Elasticsearch中的相应概念,文献 [29] 中给出相关概念在传统的关系型数据库(如SQL Server)和Elasticsearch中的对应关系,见表1.1。
表1.1 相关概念在关系型数据库和Elasticsearch中的对应关系
(10)Mapping——Mapping定义索引下Type的字段处理规则,如索引如何建立、索引数据类型、是否保存原始索引JSON文档、是否压缩原始JSON文档、是否需要分词处理、如何进行分词处理等。一般地,一个索引文件下能存储不同映像(Mapping)的类型文件(Types)。Mapping也可通过语句删除,此时对应的类型文件下所有数据也会被删除。
1. 非客户端方式
(1)通过HTTP方式的JSON格式进行调用。关于HTTP的相关参数设置可在elasticsearch.yml中进行相关设置(出于安全考虑,也可禁用HTTP接口,只需在配置文件中将http.enabled设置为false即可)。本书在介绍Elasticsearch的使用时,除第5章外,都是基于这种方式使用Elasticsearch API的。
(2)通过Thrift软件框架方式。Thrift结合了功能强大的软件堆栈和代码生成引擎,以构建在C++、Java等编程语言间的无缝、高效服务。可通过Thrift方式实现跨语言操作,参见本书第5章基于Java客户端的编程实现方法。
(3)通过Memcached方式。Memcached是分布式内存对象缓存系统,用于在动态系统中减少数据库负载,提升性能。它适合大型的分布式系统,对于单台服务器的应用,此种方式有时可能是不合适的。
2. 客户端方式
另外,对应Java编程者来说,Elasticsearch内置了两个客户端:
(1)节点客户端。它以一个无数据节点的身份加入到集群中。换句话说,它自身是没有任何数据的,但是知道什么数据在集群中的哪一个节点上,然后就可以将请求转发到正确的节点上并进行连接。
(2)传输客户端。更加轻量的传输客户端可被用来向远程集群发送请求。它并不加入集群本身,而是把请求转发到集群中的节点。
这两个客户端都使用Elasticsearch的传输协议,通过9300端口与Java客户端进行通信。集群中的各个节点也是通过9300端口进行通信。
Tips: Elasticsearch的9200端口是HTTP接口,9300端口是Transport接口。
Elasticsearch的社区支持力度是比较大的。众多Java开源社区提供的丰富插件可以有效地帮助Elasticsearch初学者和中高级用户有效使用Elasticsearch。有些插件是可以自己安插到Elasticsearch中的,如对于Head插件,用户可以从http://mobz.github.io/elasticsearch-head下载,之后进入Elasticsearch的bin文件夹,执行如下命令即可把Head安装到Elasticsearch环境中:
Plugin -install mobz/elasticsearch-head
其实,在Elasticsearch的RTF版本中,已经集成了部分常用的插件,部分插件是可以直接在浏览器中看到其作用效果的。RTF中的plugins文件夹中就是已经安装好的插件,下面对部分插件功能进行说明。
Tips: 汉语自动分词是中文自然语言处理的重要一环。构建于词之上的各种后续语言分析手段才有展示身手的舞台。例如,Ansj是基于ICTCLAS中文分词算法而开发的开源的Java中文分词工具;IK Analyzer是一个开源的基于Java语言开发的轻量级的中文分词工具包;MMSEG是基于中文分词之最大匹配法扩展而来的中文分词工具。几种分词算法各有优势。
1. Head
Head是一个用来监控Elasticsearch状态的客户端插件。用户在浏览器中输入http://localhost:9200/_plugin/head/,会打开类似图1.3的界面。图中显示了具有两个节点的结果(分别是Jackal和Vargas,见左下角),每个节点拥有不同index的数据(这里的两份index分别为myfirstindex和page)。
图1.3 Head界面
Head插件可以为用户(特别是初学者)提供很多便利,例如可以使用Head提供的HTTP客户端,通过HTTP的方式来操作Elasticsearch。在Head中可以单击界面的Any Request标签来构建HTTP请求,辅以必要的PUT、GET等操作就能实现对应的功能。本书后续给出的例子有一部分就是基于Head插件来实现的。
2. Marvel
Marvel是Elasticsearch的图形化监控客户端,可以通过Marvel来查看Elasticsearch当前的各项状态指标,使用方法是在浏览器中输入http://localhost:9200/_plugin/marvel/,会显示出类似图1.4的内容。
图1.4 Marvel
3. Health
Health是用来查看集群目前健康状态的。在浏览器中输入http://localhost:9200/_cluster/health会显示当前集群的部分信息,如图1.5所示。
图1.5 Health界面
Elasticsearch的基本架构如图1.6所示。从图中可以看出,Elasticsearch可以接受本地、共享及云平台上的数据;在Lucene提供的基本功能上,通过构建分布式索引,完成对大数据的加工处理。其中,Zen用来做节点自动发现和Master节点选举;EC2(Elastic Compute Cloud)借由提供Web服务的方式让使用者可以弹性地运行自己的Amazon机器映像,提供可调整的云计算能力。通过提供的Thrift、Memcached、HTTP等方式使用Elasticsearch的API。在顶层,用户可以基于RESTful和客户端(如Java客户端)的方式来通过Elasticsearch API完成数据操作、管理等工作。
图1.6 Elasticsearch的基本架构
RESTful接口URL的格式是:
http://localhost:9200/<index>/<type>/[<id>]
其中,index、type是必须提供的(index可以理解为数据库;type理解为数据表);id是可选的(相当于数据库表中记录的主键,是唯一的。如果不提供,Elasticsearch会自动生成)。增、删、改分别对应HTTP请求的PUT、GET、DELETE方法。对于PUT方法来说,调用时如果数据不存在,就创建;如果数据已存在,就更新。Elasticsearch可能会返回一个HTTP状态码(类似如图1.1所示)以及一个JSON格式的主体。
Tips: Elasticsearch的语句包括可能的如下几个部分 [6] :