最近换工作了,现在需要用到一些大数据的东西,例如ES,找了一圈,还是官方文档最实在,只不过看起来略有些麻烦,既然要翻译,那就记录一下吧,万一有人需要呢。
入门简介
Elasticsearch是一个高度可伸缩的开源全文搜索和分析引擎。可以用它几近实时的来存储、搜索和分析大量的数据。通常,我们使用它作为底层引擎技术给拥有复杂搜索功能需求的应用赋能。
下面是Elasticsearch几个应用场景:
- 你运营一家可以让用户搜索你出售的商品的网上商店。此时,你可以用ES存储全部商品的目录和存货,然后,给用户提供搜索和自动填充功能。
- 你想要收集日志或交易数据,用来分析趋势、统计数据、概要和异常。此时,你可以使用Logstash(Elasticsearch/Logstash/Kibana技术栈的一部分)来收集,聚合,解析数据,然后将其存入ES。一旦数据在ES里了,你就可以用搜索和聚合挖掘任何你感兴趣的数据。
- 你有一个可以让懂行的顾客制定类似“我对这个小玩意儿挺感兴趣的,当这个东西的价格在下个月之前降到X块钱了通知我”规则的价格预警平台。此时,你可以抹去卖主的价格,存入ES中,使用逆向搜索(Percolator)能力,根据用户的查询来匹配价格的变动,最终,一旦价格匹配,给用户推送提醒。
- 你有分析学和商业策略的需求,需要快速的在一大堆数据(想象有上十亿的记录)里研究,分析,做可视化,作特定的询问。此时,你可以用ES存储你的数据,然后用Kibana(Elasticsearch/Logstash/Kibana技术栈的一部分)来定制可以让你的重要数据可视化的仪表盘。不仅如此,你可以用ES的聚合功能,根据你的数据作复杂的商业策略查询。
这个教程的余下部分,我逐步会引导你,首先将ES跑起来,然后看看ES能做什么,尝试基础的索引,搜索,更新数据操作。在这个教程的最后,你应该就知道了ES是个什么玩意儿,它怎么工作的,希望看到你用ES建造精致的搜索应用,或者从数据里挖到有用的情报。
基础概念
下面是一些ES的核心概念。从开始理解这些概念会极大的简化学习进程。
几乎实时(NRT)
ES是一个几乎实时的搜索平台。这意味着从你给一个文档作索引到这个文档能被搜索会有一个轻微的延迟(通常一秒)。
集群
集群是一个或多个节点(服务器)的集合,存储你全部的数据,提供在所有节点间联合索引和搜索能力。一个集群用一个特定的名称标识,默认是elasticsearch
。这个名称很重要,因为节点只能用这个名字才能成为集群的一部分。
确保你不会在不同的环境中重用同样的集群名称,不然,你可能会让节点加入错误的集群。例如。你可以用logging-dev
,logging-stage
,logging-prod
代表开发,预发布,生产集群。
节点
节点是集群中的单个服务器,用来存储数据,参与集群的索引和搜索能力。像集群一样,节点也用一个名称来标识,默认是一个全局唯一标识(UUID),在节点启动的时候分配。如果不想要默认的,你可以随意设定。这个名字用于管理集群中哪些服务器对应哪些节点。
节点可以通过集群名称配置加入一个具体的集群。默认情况下,每一个被设置加入一个名为elasticsearch
的集群。这意味着,如果你在你的网络中启动几个节点(假设他们能发现彼此),那么他们会自动的组织并加入一个名为elasticsearch
的集群。
在一个集群中,你可以想配多少节点就配多少。此外,如果你的网络中没有其他ES节点运行,那么启动一个节点会默认组织成一个名为elasticsearch
的单节点集群。
索引
译者注:这里的索引不是通常意味的索引,可以认为是RMDB中的表。
索引是存在几分类似特征的文档集合。例如,你可以有一个顾客索引,还有一个商品目录索引,还有其他数据的索引。索引通过一个名称标识(必须全是小写的),这个名称用于在索引中针对文档进行创建索引,搜索,更新,和删除操作。
在一个集群中,索引可任意指定。
类型
在一个索引中,你可以定义一个或多个类型。类型是对索引的逻辑区分,语义完全归你自己决定。通常,会为一组共同字段的文档定义一个类型。例如,假设你运营一个博客平台并将所有数据存放在单独一个索引中。在这个索引中,你可以为用户数据定义一个类型,为博客数据定义另一个类型,为评论数据定义另一个类型。
文档
文档是可以被索引的基本信息单元。例如,你可以有一个存储单个用户数据的文档,一个存储单个产品的文档,一个存放单个订单的文档。文档用JSON表达,不必多解释。
在一个索引/类型中,只要你想,你可以存尽可能多的文档。注意,尽管文档物理上存在于索引之中,但还是必须得分配一个索引中的类型给它。
分片&复制
索引可以存储超过单台节点硬件限制的数据。例如,一个占用1TB硬盘空间存储十亿文档的单个索引可能在单个节点的硬盘上存不下,或者单个节点相应查询速度太慢。
为了解决这个问题,ES提供了切分索引为多块被称为分片的能力。当你创建一个索引,你可以轻易的指定你需要的分片个数。每个分片自己都是一个完整功能且独立的“索引”,可以寄宿在集群中的任何一个节点上。
分片主要有两个目的:
- 允许你水平分割/扩展你的内容容量
- 允许你在分片(潜在地,位于多个节点上)之上进行分布式的、并行的操作,进而提高性能/吞吐量
分片如何分布,文档如何聚集为搜索请求的机制,全权由ES负责,对用户透明。
在网络/云环境下,出错难以避免,为了避免一个分片或节点不明原因突然离线或消失,有一个故障转移机制是非常有用而且非常推荐的。为了达到这个目的,ES允许你创建一个或多个索引分片的拷贝,可以称之为复制分片,或简称复制。
复制主要由两个目的:
- 为避免分片/节点出错提供高可用。为了达到这点,复制分片和原始分片不要放在同一个节点上。
- 扩展搜索量/吞吐量,因为搜索可以在所有的复制上并行运行
总而言之,一个索引可以被切分为多个分片。一个索引也可以被复制零(就是不复制)或多次。一旦复制了,每个节点将会有主分片(作为复制源的原来的分片)和复制分片(主分片的拷贝)。在索引创建时可以指定分片和复制的数量。在索引创建之后,你可以在任何时候动态的修改复制的数量,但你不能修改分片的数量。
默认情况下,ES中每一个索引分配了5个主分片和1个复制分片,这意味着,如果你的集群中至少有两个节点,那么你的索引将会有5个主分片和另外5个复制分片(1个完整复制),一个索引一共有10个分片。
每一个ES分片是一个Lucene索引。在单个Lucenes索引中有个最大文档限制,为2,147,483,519 (= Integer.MAX_VALUE - 128) 。你可以用_cat/shards API监控分片大小。
这些问题搞清楚之后,我们就要进入好玩的部分了...
安装
ES要求至少是Java 8。在这个文章书写之时,建议使用Oracle JDK version 1.8.0_131。Java 的安装在此不多赘述。
使用tar安装
使用下面的命令下载ES 5.6.2:
curl -L -O https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.6.2.tar.gz
解压
tar -xvf elasticsearch-5.6.2.tar.gz
运行
cd elasticsearch-5.6.2/bin
./elasticsearch
node成功启动
如果安装没问题了,你会看到下面一堆信息:
[2016-09-16T14:17:51,251][INFO ][o.e.n.Node ] [] initializing ...
[2016-09-16T14:17:51,329][INFO ][o.e.e.NodeEnvironment ] [6-bjhwl] using [1] data paths, mounts [[/ (/dev/sda1)]], net usable_space [317.7gb], net total_space [453.6gb], spins? [no], types [ext4]
[2016-09-16T14:17:51,330][INFO ][o.e.e.NodeEnvironment ] [6-bjhwl] heap size [1.9gb], compressed ordinary object pointers [true]
[2016-09-16T14:17:51,333][INFO ][o.e.n.Node ] [6-bjhwl] node name [6-bjhwl] derived from node ID; set [node.name] to override
[2016-09-16T14:17:51,334][INFO ][o.e.n.Node ] [6-bjhwl] version[5.6.2], pid[21261], build[f5daa16/2016-09-16T09:12:24.346Z], OS[Linux/4.4.0-36-generic/amd64], JVM[Oracle Corporation/Java HotSpot(TM) 64-Bit Server VM/1.8.0_60/25.60-b23]
[2016-09-16T14:17:51,967][INFO ][o.e.p.PluginsService ] [6-bjhwl] loaded module [aggs-matrix-stats]
[2016-09-16T14:17:51,967][INFO ][o.e.p.PluginsService ] [6-bjhwl] loaded module [ingest-common]
[2016-09-16T14:17:51,967][INFO ][o.e.p.PluginsService ] [6-bjhwl] loaded module [lang-expression]
[2016-09-16T14:17:51,967][INFO ][o.e.p.PluginsService ] [6-bjhwl] loaded module [lang-groovy]
[2016-09-16T14:17:51,967][INFO ][o.e.p.PluginsService ] [6-bjhwl] loaded module [lang-mustache]
[2016-09-16T14:17:51,967][INFO ][o.e.p.PluginsService ] [6-bjhwl] loaded module [lang-painless]
[2016-09-16T14:17:51,967][INFO ][o.e.p.PluginsService ] [6-bjhwl] loaded module [percolator]
[2016-09-16T14:17:51,968][INFO ][o.e.p.PluginsService ] [6-bjhwl] loaded module [reindex]
[2016-09-16T14:17:51,968][INFO ][o.e.p.PluginsService ] [6-bjhwl] loaded module [transport-netty3]
[2016-09-16T14:17:51,968][INFO ][o.e.p.PluginsService ] [6-bjhwl] loaded module [transport-netty4]
[2016-09-16T14:17:51,968][INFO ][o.e.p.PluginsService ] [6-bjhwl] loaded plugin [mapper-murmur3]
[2016-09-16T14:17:53,521][INFO ][o.e.n.Node ] [6-bjhwl] initialized
[2016-09-16T14:17:53,521][INFO ][o.e.n.Node ] [6-bjhwl] starting ...
[2016-09-16T14:17:53,671][INFO ][o.e.t.TransportService ] [6-bjhwl] publish_address {192.168.8.112:9300}, bound_addresses {{192.168.8.112:9300}
[2016-09-16T14:17:53,676][WARN ][o.e.b.BootstrapCheck ] [6-bjhwl] max virtual memory areas vm.max_map_count [65530] likely too low, increase to at least [262144]
[2016-09-16T14:17:56,731][INFO ][o.e.h.HttpServer ] [6-bjhwl] publish_address {192.168.8.112:9200}, bound_addresses {[::1]:9200}, {192.168.8.112:9200}
[2016-09-16T14:17:56,732][INFO ][o.e.g.GatewayService ] [6-bjhwl] recovered [0] indices into cluster_state
[2016-09-16T14:17:56,748][INFO ][o.e.n.Node ] [6-bjhwl] started
目前不过多解释,可以看到我们名称为6-bjhwl
(你运行时应该不同)的节点跑起来了,然后选举自己为单个集群中的主。先别担心不知道主是什么意思。这里主要关注,我们在一个集群中启动了一个节点。
像之前提到的,我们可以覆盖默认的集群和节点名称。这可以通过下面的命令做到:
./elasticsearch -Ecluster.name=my_cluster_name -Enode.name=my_node_name
也要注意一下有http标记的那一行,它提供了有关HTTP地址(192.168.8.112)和端口(9200)的信息,通过这个地址和端口我们就可以访问我们的节点了。默认情况下,Elasticsearch使用9200来提供对其REST API的访问。如果有必要,这个端口是可以配置的。