1. 简介
ElasticSearch是一个开源的分布式搜索和分析引擎,它在Lucence基础上做了二次开发,将Lucence繁琐的API调用变为简洁通用的ResetFul API,并提供了Java API,以及与Storm、Spark、Hadoop等大数据开源组件相适配的API接口。通过ElasticSearch,我们可以实现对JSON格式数据源的存储、文本搜索、结构化搜索和分析。ElasticSearch无论是单节点部署还是集群部署都较为简单,它可以自动完成数据存储、数据容灾、数据检索等多种功能,在维基百科、英国卫报、GitHub等得到了广泛应用。
2. Restful API
REST直译为状态形式转移,是近几年极为火热的Client与Sever交互形式,之前的Client与Server主要采用RPC远程调用的方式,Server提供函数API,Client使用函数并将函数参数传递给Server,Server接收到函数执行相应动作并将结果返回。这种交互形式存在的主要弊端就是随着移动互联网的兴起,Client与Server需要同时提供对Web、IOS和Andriod的支持,这对开发和维护人员是一个很大的负担。而Rest形式的交互方式则统一了交互方式,多种Client可以使用统一的Restful API与Server通信。Client与Server的交互无非是对指定的数据进行一系列的操作,在Restful API中,我们将数据资源与执行动作分离开来,每个数据资源都可以通过URL获得,并且每个数据资源是无状态的,不依赖于其他资源,使用GET、PUT、POST、DELETE等指定动作,配合传入的一系列参数,可以实现所有交互,且交互简单,不存在这次交互依赖上次交互的问题(因为所有资源都是无状态的)。
3. 基础架构
ElasticSearch架构中的关键概念分别为:
- 节点(Node)与主节点(Master Node)
- Index、Type、Dcoument与Field
- 主分片与复制分片
在介绍ElasticSearch架构之前,需要先介绍一下ES的存储逻辑。ES的存储逻辑分为索引(Index)、类型(Type)、文档(Documnet)、字段(Field),对应关系型数据库,Index->Database,Type->Table,Dcoument->Row,Field->Column,数据源中的每个Json字符串,都会成为ES中的一个Document,Json中的字段成为Doucment中的Field,ES是基于文档来进行检索的。ES集群中存在多个Index,每一个Index又包含多个Type,每个Type包含多个Document,每个Document中又包含多个字段(Field)。
ES不像其他一下大数据组件那样依赖HDFS,ES的存储由自己管理,并实现高可用(HA)。ES将每个Index的数据分成多个主分片(shard),同时为了保证数据的高可用,每个主分片都有与之对应的复制分片。我们在新建Index时需要指定主分片的个数和每个主分片对应的复制分片个数,主分片数一旦确定即不可更改,复制分片可以在后期进行更改。 为了保证数据的高可用,分片均匀分布与各节点,主分片和复制分片不会存在于同一个Node,否则复制分片将失去意义。
在ElasticSearch集群中每个节点(Node)都是一个ElasticSearch实例,实例中的cluster.name决定该node属于哪个Cluster,我们将cluster.name设为同一个,组成一个ElasticSearch集群。在集群中存在Master Node,Master Node是通过选举产生的,主要工作为管理Index与Node,Client可以对集群中的所有节点(包括主节点)进行读写,因为每个节点都会根据Document ID查找到文档对应的分片(对Document Id的hash值按照主分片数进行求余来判定该文档属于该Index下的那个分片,因此Index的主分片数一经确定即不可更改,同时也说明Document ID用户在设定时需多方面考虑,也可让ES自动生成),因此主节点的工作负载较轻,不会成为集群的性能瓶颈。
上图中NODE1、NODE2、NODE3构成了一个ES集群,NODE1为主节点,我们在该集群上新建一个索引Index,该索引分为3个主分片P0、P1、P2,每个主分片有对应2个复制分片。从图中可以看出,主分片和复制分片没有在同一个Node上,实现了数据的高可用。
ES将集群的健康状态分为了3种,我们可以通过命令:curl -XGET '主机:9200/_cluster/health?pretty'
来获得。
新建、索引与删除文档都是属于对ES集群的Write操作,Write操作需要对Index的主分片进行操作,过程如上图所示:
- 如步骤1,客户端可以对集群中的任意一个节点发起新建、索引与删除文档的请求,比如Node1接收到Write请求,首先会根据请求文档的Document Id经过计算得出该文档属于哪个主分片,比如属于P0分片,Node1则将该请求转发至Node3;
- 如步骤2,Node3接收到Node1转发过来的Write请求,则在P0分片中进行Write操作,执行成功后再将请求转发至P0对应的复制分片R0上;
- 如步骤3,Node1、Node2节点存储有P0分片的复制分片R0,Node1、Node2在接收到Node3转发来的请求,会对复制分片R0进行操作,操作成功后将结果返回Node3;
- Node3在接收到所有复制分片都操作成功后,将Write的操作结果返回给Node1,由Node1将最终结果返回给客户端。
4.2 检索文档
检索文档属于对ES集群的Read操作,Read操作可以对Index的任意分片进行操作,包括主分片和复制分片,过程如上图所示:
- 如步骤1,客户端可以对集群中的任意一个节点发起检索文档的请求,比如Node1接收到Read请求,首先根据请求文档的Document Id经过计算得出该文档哪个分片,比如属于分片0,对于Read请求,为了平衡负载,请求节点会为每个请求选择不同的分片——它会循环所有分片副本。比如Node1决定读取Node2中的复制分片R0;
- 如步骤2,Node2接收到Node1转发的Read请求,对R0分片进行检索,并将检索结果返回至Node1;
- 如步骤3,Node1接手到Node2发来的检索结果,并将结果发送至客户端。
4.3 局部更新
局部更新即Update操作是Read操作与Write操作的结合,过程如上图所示:
- 如步骤1,客户端可以对集群中的任意一个节点发起Update请求,比如Node1接收到Update请求,首先根据请求文档的Document Id经过计算得出该文档哪个分片,比如属于分片0,Node1找到分片0的主分片P0在Node3,并将请求转发至Node3;
- 如步骤2和3,Node3接收到Node1转发的Update请求,对P0主分片进行检索,获得检索结果后对Document进行修改,并重新建立该文档的索引,操作成功后,将新建的该文档索引发送至复制分片R0;
- 如步骤4,复制分片R0在Node1和Node2对该文档重建索引,并将操作结果返回Node3;
- Node3收到所有复制分片均操作成功,则将结果发送至Node1,由Node1将结果发送至客户端;
4.4 批量请求
批量请求其实是被请求节点将所有请求分发至其他节点,由其他节点进行处理,并将各节点的返回结果进行汇总,然后将汇总结果发送至客户端。
5. 插件介绍
网上存在多种插件与ElasticSearch配合,实现更多功能。
- 官方提供的Kibana可以实现图表可视化等功能,可以在Kibana中实现ES的索引配置、Mapping配置、多种过滤条件检索,将检索结果保存并以多种酷炫的图表方式展示出来,显示效果惊艳,由于是官方插件,因此与ES的配合程度很高,但较为消耗机器资源。
- 官方提供的Security(旧称Shield)插件,提供了对ElasticSearch的权限管理,增添的用户权限管理,能够很好的保证数据安全,防止盗窃、篡改和监听。(但该插件是需要付费的,因此寻求免费用户权限管理,需要考虑在Nginx服务器上进行相应处理)
- 官方提供的Monitoring(旧成Marvel)插件,实现了对ElasticSearch集群的状态监控,我们可以直接监控集群健康状态、节点资源使用情况、索引状态等内容。(该插件也需要付费,但有免费授权)
- 除了官方提供的插件,GitHub上也有一些开源的ES插件,其中比较典型的为Head插件,该插件提供了集群管理、数据可视化等诸多功能,我们可以从GitHub上免费下载并安装,需要主要的是Head对ES2.x版本是以插件的形式运行,对ES5.x版本是以独立的服务运行的,安装过程不同。