Elasticsearch介绍

简介

Elasticsearch是一个高可扩展的开源全文搜索和分析引擎,它允许存储、搜索和分析大量的数据,并且这个过程是近实时的。它通常被用作底层引擎和技术,为复杂的搜索功能和要求提供动力。

基础概念

Elasticsearch中有几个核心的概念,理解这些概念对于ES的学习还是很有帮助的。

近实时(Near Realtime NRT)

Elasticsearch是一个近实时的搜索平台,近实时的意思是指从你建立索引到你能够搜索这个文档这个过程,这个过程时间大概是1秒钟。

集群(Cluster)

一个集群包含一个或多个节点(node),用来保存全部数据,并且这些节点联合提供索引和搜索能力。集群使用唯一名称进行不同集群间的区分,默认名称是”elasticsearch”。集群的名称很重要,因为一个节点如果要加入到一个集群中,需要设置节点的集群名称。
在实际应用中,需要确保你的不同环境,所使用的名称是不同的,否则会导致节点加入到其它集群环境中。比如你可以使用:logging-dev、logging-stage、logging-prod分别用来搭建开发、过渡、生产环境。
集群可以只有一个节点,这个集群也能正常提供工作能力。此外,也可以搭建多个Elasticsearch集群,通过集群名称区分。

节点(Node)

在集群中一个节点是一个单独的服务,用来存储数据,为集群的索引和搜索提供能力。集群中的节点,也有唯一标识的,默认在节点启动的时候会随机指定一个UUID(Universally Unique IDentifiter)。如果不使用默认名称,可以为其指定一个名称。节点名称对于集群管理也是很重要的。
一个节点要加入到指定集群,需要为节点指定集群名称。默认情况下,每个节点都设置集群名称为”elasticsearch”,所以当在同一网络环境中,默认启动一些节点,这些节点会组装成一个名为elasticsearch集群。

索引(Index)

一个索引包含许多特征类似的文档。例如,有一个索引用来索引用户数据,另一个索引用来索引产品目录,其它的索引可以索引其它数据。一个索引需要指定一个名称(必须全部小写),执行索引、搜索、修改和删除操作,需要指定对应的索引名称。
在一个集群中,你可以创建多个索引。

类型(Type)

在一个索引中,可以定义多个类型。一个类型可以管理索引中符合特定逻辑的一部分数据。一般来说,类型定义具有公共字段的文档。例如你想创建一个博客平台,并且使用一个索引存储所有数据。在这个索引中,你可以定义一个类型用来存储用户数据,另一个类型用来存储博客数据,还可以创建一个类型用来存储评论。

文档(Documeng)

文档是能够被索引的基础单元。例如一个文档存储一个用户信息,另一个文档存储一个产品信息。Elasticsearch文档使用JSON(JavaScript Object Notation)来表现数据。
在一个索引/文档中可以存储许多文档。需要注意,尽管一个文档在物理存储上是存储在一个索引中的,但文档必须被索引或分配给索引的类型中。

分片(Shard)&副本(Replicas)

在实际应用中可能存在这样的场景,一个索引存储超过了一个节点的物理存储能力。例如一个索引有十亿的文档,超过了1TB的存储,在单个节点无法完全存储,并且对于单个节点的搜索请求是非常慢的。
为了解决这些问题,Elasticsearch提供了为索引切分成多个分片(Shard)的能力,当你创建一个索引的时候,你能够定义索引被分割成多少个shard。每一个shard都是功能完全,能够独立索引的,可以分配到集群中任何一个节点中。

使用分片有两个重要原因:

  • 允许水平分割文档,分布存储。
  • 允许你分配并且执行分片,在多个节点中能够提供查询性能和吞吐量。

shard如何分布,当一个请求发来后如何组织数据,这些对于用户来说都是透明的。
当在一个网络环境中,有可能某个节点或分片丢失。Elasticsearch提供了一种针对这种故障转移的功能,就是副本。Elasticsearch允许你为一个分片创建一个或多个副本。分片和副本又称为主/副分片。

使用副本有两个重要原因:

  • 当一个节点或分片丢失后,能够继续使用。因此,需要注意的是主/副分片不会存储在一个节点中。
  • 当进行搜索的时候,允许搜索所有的副本,所以提高了搜索性能。

所以一个索引能够分割成多个shard,一个索引能够可以有零个或多个副本。每个索引都有主分片(索引切割后的分片,又称原始分片)和副本分片(从原始分片复制过来的)。分片数量和副本数量在创建索引的时候可以被指定,当索引创建后,可以指定改变副本数量,但是不能改变分片数量。默认情况下每个索引在Elasticsearch有5个分片和1个副本,也就是说总共10个shard(副本是对分片来说的,每个shard又一个副本)。每一个shard内部都是一个Lucene索引实例,单个lucene索引最多能够存储2,147,483,519(Integer.MAX_value-128)个文档。

Elasticserach层级

理解Elasticsearch中索引、类型、文档、域(字段)可以和关系型数据库做个简单的对比:

  • Relation DB: database->table->row->column
  • Elasticsearch:index->type->document->field

Elasticsearch安装(5.2.0)

jdk安装

Elasticsearch安装前需要安装jdk,版本最低是1.8,因为ES源码中许多使用了lambda表达式等jdk8的语法。

下载Elasticsearch

https://www.elastic.co/downloads/elasticsearch

解压包

tar -zxvf elasticsearch-5.2.0.tar.gz
进入解压文件
cd elasticsearch-5.2.0/bin

启动ES

./elasticsearch
<pre>
2017-02-28T21:54:27,648][INFO ][o.e.n.Node ] [] initializing ...
[2017-02-28T21:54:27,736][INFO ][o.e.e.NodeEnvironment ] [fkHgUS8] using [1] data paths, mounts [[/ (/dev/disk1)]], net usable_space [117.6gb], net total_space [177.8gb], spins? [unknown], types [hfs]
[2017-02-28T21:54:27,736][INFO ][o.e.e.NodeEnvironment ] [fkHgUS8] heap size [1.9gb], compressed ordinary object pointers [true]
[2017-02-28T21:54:27,737][INFO ][o.e.n.Node ] node name [fkHgUS8] derived from node ID [fkHgUS8UTBOOYxQ4LaPYQg]; set [node.name] to override
[2017-02-28T21:54:27,739][INFO ][o.e.n.Node ] version[5.2.0], pid[4855], build[24e05b9/2017-01-24T19:52:35.800Z], OS[Mac OS X/10.11.6/x86_64], JVM[Oracle Corporation/Java HotSpot(TM) 64-Bit Server VM/1.8.0_91/25.91-b14]
[2017-02-28T21:54:28,453][INFO ][o.e.p.PluginsService ] [fkHgUS8] loaded module [aggs-matrix-stats]
[2017-02-28T21:54:28,453][INFO ][o.e.p.PluginsService ] [fkHgUS8] loaded module [ingest-common]
[2017-02-28T21:54:28,454][INFO ][o.e.p.PluginsService ] [fkHgUS8] loaded module [lang-expression]
[2017-02-28T21:54:28,454][INFO ][o.e.p.PluginsService ] [fkHgUS8] loaded module [lang-groovy]
[2017-02-28T21:54:28,454][INFO ][o.e.p.PluginsService ] [fkHgUS8] loaded module [lang-mustache]
[2017-02-28T21:54:28,454][INFO ][o.e.p.PluginsService ] [fkHgUS8] loaded module [lang-painless]
[2017-02-28T21:54:28,454][INFO ][o.e.p.PluginsService ] [fkHgUS8] loaded module [percolator]
[2017-02-28T21:54:28,454][INFO ][o.e.p.PluginsService ] [fkHgUS8] loaded module [reindex]
[2017-02-28T21:54:28,454][INFO ][o.e.p.PluginsService ] [fkHgUS8] loaded module [transport-netty3]
[2017-02-28T21:54:28,454][INFO ][o.e.p.PluginsService ] [fkHgUS8] loaded module [transport-netty4]
[2017-02-28T21:54:28,455][INFO ][o.e.p.PluginsService ] [fkHgUS8] no plugins loaded
[2017-02-28T21:54:30,225][INFO ][o.e.n.Node ] initialized
[2017-02-28T21:54:30,225][INFO ][o.e.n.Node ] [fkHgUS8] starting ...
[2017-02-28T21:54:30,420][INFO ][o.e.t.TransportService ] [fkHgUS8] publish_address {127.0.0.1:9300}, bound_addresses {[fe80::1]:9300}, {[::1]:9300}, {127.0.0.1:9300}
[2017-02-28T21:54:33,477][INFO ][o.e.c.s.ClusterService ] [fkHgUS8] new_master {fkHgUS8}{fkHgUS8UTBOOYxQ4LaPYQg}{XitBFBRHSYKtMEA-VwIBgw}{127.0.0.1}{127.0.0.1:9300}, reason: zen-disco-elected-as-master ([0] nodes joined)
[2017-02-28T21:54:33,495][INFO ][o.e.h.HttpServer ] [fkHgUS8] publish_address {127.0.0.1:9200}, bound_addresses {[fe80::1]:9200}, {[::1]:9200}, {127.0.0.1:9200}
[2017-02-28T21:54:33,496][INFO ][o.e.n.Node ] [fkHgUS8] started
[2017-02-28T21:54:33,500][INFO ][o.e.g.GatewayService ] [fkHgUS8] recovered [0] indices into cluster_state
</pre>

从启动信息种可以看到节点名称为fkHgUS8,由于是单节点,所以本身就是master,使用端口9200作为REST API访问端口。我们可以通过命令行为其指定集群名称和节点名称:
./elasticsearch -Ecluster.name=es_cluster -Enode.name=node01

探索集群

上面我们把elasticsearch集群启动起来了(虽然只有一个节点),接下来你应该试着与这个集群进行通信。Elasticsearch提供了非常全面和强大的REST API来与集群通信。通过这些API你可以:

  • 检查集群、节点、索引健康、状态和统计
  • 管理集群、节点、索引数据和元数据信息
  • 执行CRUD操作
  • 执行高级的搜索操作,比如分页(paging)、排序(sorting)、脚本(scripting)、聚合(aggregations)和其它操作

Elasticsearch交互

Elasticsearch提供了两种交互方式:java客户端(java api)和http协议(rest api)

  1. java api
    节点客户端(node client):节点客户端加入集群,但是并不存储数据,但知道数据再集群的具体位置,并且能够转发请求到对应节点上。
    传输客户端(Transport client):节点本身不加入集群,只简单发送请求给集群中的节点,这个更轻量。
    两个客户端都是通过9300端口进行访问,并使用Elasticsearch传输协议进行通信(ETP:Elasticsearch Transport Protocol),集群节点间也是使用9300端口进行通信。
  2. 基于http协议
    基于HTTP协议,以JSON为数据交互格式的RESTful API,非java语言可以使用RESTful API形式与ES进行交互,使用9200端口。
    请求格式:
    curl -X<VERB> '<PROTOCOL>://<HOST>:<PORT>/<PATH>?<QUERY_STRING> ‘ -d <BODY>
    VERB:HTTP方法,GET、POST、PUT、HEAD、DELETE
    PROTOCOL:http协议或https协议
    HOST:请求的节点主机
    PORT:端口号,默认9200
    PATH:请求路径
    QUERY_STRING:可选请求参数
    BODY:JSON形式请求的主题
    example:curl -XGET http://localhost:9200/_count
    得到响应主体,如果要请求头,在-XGET前加-i获取

集群健康

集群健康检查,这里会用到_cat语法:
curl http://127.0.0.1:9200/_cat/health?v

集群状态

从结果可以看到,集群名称为elasticsearch,集群状态为绿色(green)。
集群状态分为绿色(green)、黄色(yellow)和红色(red)。

  • 绿色代表集群当前状态是好的(集群功能齐全)。
  • 黄色代表所有数据(主分片)都可用,但是一些副本(副分片)还没有分配(集群功能齐全)。
  • 红色代表一些数据(主分片)不可用。

需要注意的是,即使集群是红色的,它仍然部分功能可用。例如:可用的shard能够继续为搜索提供服务。但是你应该尽快去解决你丢失的数据。
从上面的信息来看,我们就有一个节点(node),并且可以看到有0个shard,这是因为我们还没有导入数据。需要注意一点,我们启动Elasticsearch使用默认名称elasticsearch。由于Elasticsearch默认采用单播网络去发现其它节点,所以如果你启动了多个Elasticsearch实例,则会自动加入这个名称为”elasticsearch”的集群。

可以使用curl http://127.0.0.1:9200/_cat/nodes?v 查看node节点列表

node节点状态

获取所有索引列表
curl http://127.0.0.1:9200/_cat/indices?v

索引列表

会发现没有任何索引纪录,因为我们集群还没有创建任何索引;
创建索引
curl -XPUT http://127.0.0.1:9200/customer

添加索引

然后在查看索引
curl http://127.0.0.1:9200/_cat?indices?v

索引列表

可以看到现在健康状态为yello,之前我们说过yello说明当前副本并未分配,因为我们只有一个节点,而副本不会和主分片在一台机器上的,所以当添加节点(node)后,副本分片被分配后集群恢复green。还可以看到有一个索引名称为customer的索引,有5个主分片(pri)和1个副本分片(rep), 0个文档,删除过0个文档,存储大小,主分片存储大小。

索引操作

索引文档

索引文档,需要为其指定类型,也可以为其手动指定id(如果不指定,Elasticsearch随机提供一个id)
curL -XPUT http://127.0.0.1:9200/customer/external/1?pretty -d '{"name":"yjz”}’
pretty参数是指格式化返回结果
返回结果:
<pre>
{
"_index" : "customer",
"_type" : "external",
"_id" : "2",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"created" : true
}
</pre>

需要注意的是,elasticsearch不需要你在索引文档前提前创建索引或者类型。当你索引文档时候,如果发现索引不存在,则会自动创建。

获取索引

curL -XGET http://127.0.0.1:9200/customer/external/2?pretty
<pre>
{
"_index" : "customer",
"_type" : "external",
"_id" : "2",
"_version" : 1,
"found" : true,
"_source" : {
"name" : "Jok"
}
}
</pre>

能够发现已经找到该索引,_source字段是指索引时候的完整文档。

删除索引

curl -XDELETE http://127.0.0.1:9200/customer/external/2?pretty
<pre>
{
"found" : true,
"_index" : "customer",
"_type" : "external",
"_id" : "2",
"_version" : 2,
"result" : "deleted",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
}
}
</pre>

修改文档

Elasticsearch表面上支持文档的修改,其实底层是将旧的索引删除,然后重新索引一个新的文档,来实现修改功能。
curl -XPOST http://127.0.0.1:9200/customer/external/1?pretty -d '{"name":"Mark”}’
返回结果:
<pre>
{
"_index" : "customer",
"_type" : "external",
"_id" : "1",
"_version" : 2,
"result" : "updated",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"created" : false
}
</pre>

批量操作

Elasticsearch提供了批量操作api(_bulk),来高效完成index、update、delete操作。批量操作可以将操作写在一个文件中,然后在执行命令的时候指定文件。
curl -XPOST 'http://10.4.237.77:9200/_bulk?pretty' --data-binary @esbatch.json
esbatch.json文件内容:
<pre>
{"index":{"_index":"blog","_type":"article","_id":1}}
{"title":"java is first","conent":"java is verry nice"}
{"create":{"_index":"blog","_type":"article","_id":2}}
{"title":"elasticsearch","content":"elasticsearch study"}
{"create":{"_index":"blog","_type":"article","_id":2}}
{"title":"elasticsearchV2","conent":"elasticsearchV2"}
{"delete":{"_index":"blog","_type":"article","_id":4}}
{"delete":{"_index":"blog","_type":"article","_id":1}}
</pre>

批量操作不会因为一个操作活动(action)失败而失败,如果批量操作中有一条纪录之行失败,则批量操作还会继续执行。批量操作会为每个执行活动返回一个执行状态,以便检查是否执行成功。

搜索

搜索可以使用两种方式:REST request URI和REST request BODY,一些简单搜索可以使用URI,而对于一些复杂的搜索可以使用request body。
curl -XGET http://127.0.0.1:9200/customer/_search?q=mark&sort=name:asc&pretty
返回结果:
<pre>
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"failed" : 0
},
"hits" : {
"total" : 1,
"max_score" : 1.0,
"hits" : [
{
"_index" : "customer",
"_type" : "external",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"name" : "Mark"
}
}
]
}
}
</pre>
返回说明:
took:Elasticsearch执行搜索毫秒数
time_out:查询是否超时
_shards:告诉我们搜索了多少个shard,成功多少,失败多少。
hits:搜索结果
hits.total:总共多少个文档符合我们的搜索条件
hits.max_score:匹配最大的分
hits.hits:实际搜索结果数据(默认返回前十条)
Elasticsearch提供了JSON风格的domain-specific-language(DSL:领域特定语言)执行查询,这种查询语言是相当全面的。比如:
curl -XGET http://127.0.0.1:9200/customer/_search?pretty -d '{"query":{"match_all":{}}}’,由于使用curl所以json串看着不友好
如果使用kibana或head,使用还是很有好的:
<pre>
GET /customer/_search
{
“query”:{“match_all”:{}},
“from”:10,
“size”:10,
“sort”:{“balance”:{“order”:”desc"}}
}
</pre>
如果想返回部分字段可以使用_source字段:
<pre>
GET /customer/_search
{
“query”:{“match_all”:{}},
“_source”:[“xxxx”,”xxxx"]
}
</pre>
上面都是match_all全部匹配返回,可以指定匹配条件,下面这个匹配包含hello或word的文档。
<pre>
GET /customer/_search
{
“query”:{“match”:{“name”,”hello word"}}
}
</pre>
也可以匹配短语,就是包含hello word短语的文档,不进行拆词。
<pre>
GET /customer/_search
{
“query”:{“match_phrase”:{“name”,”hello word"}}
}
</pre>

布尔查询

布尔查询可以多条件匹配,可以完成and、or、not组合条件查询。

  • 查询and操作,通过must控制,需要满足所有查询条件。

<pre>
GET /customer/_search
{
“query”:{
“must”:[
{“match”:{“name”:”hello”}},
{“match”:{“name”:”world"}}
]
}
}
</pre>

  • 查询or操作,通过should控制,只需满足部分查询条件。

<pre>
GET /customer/_search
{
“query”:{
“should”:[
{“match”:{“name”:”hello”}},
{“match”:{“name”:”world"}}
]
}
}
</pre>

  • 查询not操作,通过must_not控制,返回不包含条件列表的文档。

<pre>
GET /customer/_search
{
“query”:{
“must_not”:[
{“match”:{“name”:”hello”}},
{“match”:{“name”:”world"}}
]
}
}
</pre>

  • 组合查询条件

<pre>
GET /customer/_search
{
“query”:{
“must”:[
{“match”:{“name”:”hello”}}
],
“must_not”:[
{“match”:{“name”:”world"}}
]
}
}
</pre>

过滤条件

比如range范围匹配
<pre>
GET /customer/_search
{
“query”:{
“must_not”:[
{“match”:{“name”:”hello”}},
{“match”:{“name”:”world"}}
],
“filter”:{
“range”:{
“balance”:{
“gte”:50,
“lte”:60
}
}
}
}
}
</pre>

聚合查询

聚合可以将数据分组和统计,Elasticsearch提供了聚合操作,聚合操作类似SQL中的group by语句。比如返回姓名相同的前十个(默认返回十个)
<pre>
GET /customer/_search
{
“size”:0,
“aggs”:{
“group_by_state”:{
“terms”:{
“field”:”name"
}
}
}
}
</pre>

Elasticsearch提供了近实时的数据操纵和搜索能力。默认情况下从索引、修改、删除到搜索出现在你结果中有1秒钟的延迟,这是和其它平台一个很大的区别,比如SQL数据操作完,立马可见。

关注我

欢迎关注我的公众号,会定期推送优质技术文章,让我们一起进步、一起成长!
公众号搜索:data_tc
或直接扫码:🔽


欢迎关注我
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容