ElasticSearch

2017-12-03  本文已影响71人  过去今天和未来

接近实时(NRT)

      Elasticsearch是一个接近实时的搜索平台。这意味着,从索引一个文档直到这个文档能够被搜索到有一个轻微的延迟(通常是1秒)。

集群(cluster)

       一个集群就是由一个或多个节点组织在一起,它们共同持有你整个的数据,并一起提供索引和搜索功能。一个集群由一个唯一的名字标识,这个名字默认就是 “elasticsearch”。这个名字是重要的,因为一个节点只能通过指定某个集群的名字,来加入这个集群。在产品环境中显式地设定这个名字是一个好 习惯,但是使用默认值来进行测试/开发也是不错的。

节点(node)

      一个节点是你集群中的一个服务器,作为集群的一部分,它存储你的数据,参与集群的索引和搜索功能。和集群类似,一个节点也是由一个名字来标识的,默认情况 下,这个名字是一个随机的漫威漫画角色的名字,这个名字会在启动的时候赋予节点。这个名字对于管理工作来说挺重要的,因为在这个管理过程中,你会去确定网 络中的哪些服务器对应于Elasticsearch集群中的哪些节点。

        一个节点可以通过配置集群名称的方式来加入一个指定的集群。默认情况下,每个节点都会被安排加入到一个叫做“elasticsearch”的集群中,这意 味着,如果你在你的网络中启动了若干个节点,并假定它们能够相互发现彼此,它们将会自动地形成并加入到一个叫做“elasticsearch”的集群中。

        在一个集群里,只要你想,可以拥有任意多个节点。而且,如果当前你的网络中没有运行任何Elasticsearch节点,这时启动一个节点,会默认创建并加入一个叫做“elasticsearch”的集群。

索引(index)

       一个索引就是一个拥有几分相似特征的文档的集合。比如说,你可以有一个客户数据的索引,另一个产品目录的索引,还有一个订单数据的索引。一个索引由一个名 字来标识(必须全部是小写字母的),并且当我们要对对应于这个索引中的文档进行索引、搜索、更新和删除的时候,都要使用到这个名字。

在一个集群中,如果你想,可以定义任意多的索引。

类型(type)

       在一个索引中,你可以定义一种或多种类型。一个类型是你的索引的一个逻辑上的分类/分区,其语义完全由你来定。通常,会为具有一组共同字段的文档定义一个 类型。比如说,我们假设你运营一个博客平台并且将你所有的数据存储到一个索引中。在这个索引中,你可以为用户数据定义一个类型,为博客数据定义另一个类 型,当然,也可以为评论数据定义另一个类型。

文档(document)

        一个文档是一个可被索引的基础信息单元。比如,你可以拥有某一个客户的文档,某一个产品的一个文档,当然,也可以拥有某个订单的一个文档。文档以 JSON(Javascript Object Notation)格式来表示,而JSON是一个到处存在的互联网数据交互格式。

在一个index/type里面,只要你想,你可以存储任意多的文档。注意,尽管一个文档,物理上存在于一个索引之中,文档必须被索引/赋予一个索引的type。

分片和复制(shards & replicas)

        一个索引可以存储超出单个结点硬件限制的大量数据。比如,一个具有10亿文档的索引占据1TB的磁盘空间,而任一节点都没有这样大的磁盘空间;或者单个节点处理搜索请求,响应太慢。

         为了解决这个问题,Elasticsearch提供了将索引划分成多份的能力,这些份就叫做分片。当你创建一个索引的时候,你可以指定你想要的分片的数量。每个分片本身也是一个功能完善并且独立的“索引”,这个“索引”可以被放置到集群中的任何节点上。

分片之所以重要,主要有两方面的原因:

1) 允许你水平分割/扩展你的内容容量

2) 允许你在分片(潜在地,位于多个节点上)之上进行分布式的、并行的操作,进而提高性能/吞吐量

至于一个分片怎样分布,它的文档怎样聚合回搜索请求,是完全由Elasticsearch管理的,对于作为用户的你来说,这些都是透明的。

       在一个网络/云的环境里,失败随时都可能发生,在某个分片/节点不知怎么的就处于离线状态,或者由于任何原因消失了,这种情况下,有一个故障转移机制是非 常有用并且是强烈推荐的。为此目的,Elasticsearch允许你创建分片的一份或多份拷贝,这些拷贝叫做复制分片,或者直接叫复制。

复制之所以重要,有两个主要原因:

- 在分片/节点失败的情况下,提供了高可用性。因为这个原因,注意到复制分片从不与原/主要(original/primary)分片置于同一节点上是非常重要的。

- 扩展你的搜索量/吞吐量,因为搜索可以在所有的复制上并行运行

总之,每个索引可以被分成多个分片。一个索引也可以被复制0次(意思是没有复制)或多次。一旦复制了,每个索引就有了主分片(作为复制源的原来的分片)和 复制分片(主分片的拷贝)之别。分片和复制的数量可以在索引创建的时候指定。在索引创建之后,你可以在任何时候动态地改变复制的数量,但是你事后不能改变 分片的数量。

默认情况下,Elasticsearch中的每个索引被分片5个主分片和1个复制,这意味着,如果你的集群中至少有两个节点,你的索引将会有5个主分片和另外5个复制分片(1个完全拷贝),这样的话每个索引总共就有10个分片。

Elasticsearch内置两个客户端

节点客户端:非数据节点加入集群,本身不保存数据,但知道数据在集群中那个节点

传输客户端:可以将请求转发到集群中的一个节点上。

Elasticsearch请求

curl -XGET 'http://localhost:9200/_count?pretty' -d '

{

"query": {

"match_all": {}

}

}'

Elasticsearch 面向文档,不仅存储文档,而且索引每个文档的内容使之可以被检索。在Elasticsearch中,你对文档进行索引、检索、排序和过滤,而不是对行列数据。

倒排索引:Elasticsearch使用倒排索引的结构达到检索数据的速度。类似数据库中索引

实例:我们雇于megacorg公司,并创建一个雇员目录。

做如下操作:

每个雇员索引一个文档,包含该雇员的所有信息。

每个文档都将是 employee 类型 。

该类型位于 索引 megacorp 内。

该索引保存在我们的 Elasticsearch 集群中

存放操作

PUT /megacorp/employee/1

{

"first_name" : "John",

"last_name" :  "Smith",

"age" :        25,

"about" :      "I love to go rock climbing",

"interests": [ "sports", "music" ]

}

检索操作

GET /megacorp/employee/1

GET /megacorp/employee/_search?q=last_name:Smith(轻量)

GET /megacorp/employee/_search

{

"query" : {

"match" : {  (match属于查询类型)

"last_name" : "Smith"

}

}

}

搜索姓氏Smith并年龄大于30

GET /megacorp/employee/_search

{

"query" : {

"bool": {

"must": {

"match" : {

"last_name" : "smith"

}

},

"filter": {

"range" : {  (range是一个过滤器) gt表示 大于 great than

"age" : { "gt" : 30 }

}

}

}

}

}

全文搜索

GET /megacorp/employee/_search

{

"query" : {

"match" : {

"about" : "rock climbing"

}

}

}

Elasticsearch 按照相关性得分排序,每个文档跟查询的匹配程度进行展示。

短语搜索

GET /megacorp/employee/_search

{

"query" : {

"match_phrase" : {

"about" : "rock climbing"

}

}

}

Elasticsearch具有聚合功能,允许我们基于数据生成一些精细的分析结果,类似上去sql中group by

GET /megacorp/employee/_search

{

"aggs": {

"all_interests": {

"terms": { "field": "interests" }

}

}

}

聚合还支持分级汇总  主要查询特定兴趣爱好员工的平均年龄

GET /megacorp/employee/_search

{

"aggs" : {

"all_interests" : {

"terms" : { "field" : "interests" },

"aggs" : {

"avg_age" : {

"avg" : { "field" : "age" }

}

}

}

}

}

空集群:一个集群拥有多个cluster.name共同承担。当节点加入集群或移除,集群会重新分配所有数据。用户发出请求到集群中任何几点,每个节点都会知道任意文档所处位置。主节点能负责从各个包含我们所需文档的节点收集回数据,并将最终结果返回給客户端。

索引实际是指向一个或多个屋里分片的逻辑命名空间

一个分片是一个Lucene 的实例

ES利用分片将数据分发到集群内各处的。分片是数据的容器,文档保存在分片内,分片又被分配到集群内的各个节点里,当扩大会缩小,ES自动在各节点中迁移分片,使得数据均匀分布在集群中。

文档元数据  _index 文档在哪里存放  _type 文档表示的对象类别  _id 文档唯一标识

创建索引

PUT /{index}/{type}/{id}

{

"field": "value"

}

取回文档

GET /website/blog/123?pretty    pretty使得json响应体更加可读

更新整个文档

PUT /website/blog/123

相同内容,es会将-version字段增加,created为false表示已经存在文档

原理:1.从旧文档构建JSON 2.更新JSON 3.删除旧文档 4.索引一个新文档

创建新文档

PUT /website/blog/123/_create

{ ... }

如果具有相同的 _index 、 _type 和 _id 的文档已经存在,es将返回409 响应码

删除文档

DELETE /website/blog/123  如果文档未找到 found为false version将增加,这个是es内部记录的一部分,用来确保这些改变在扩多节点时以正确顺序执行。

文档部分更新,他只是与现有的文档进行合并,合并在一起,覆盖现有字段,增加新的字段

POST /website/blog/1/_update

{

"doc" : {

"tags" : [ "testing" ],

"views": 0

}

}

取回多个文档

GET /website/blog/_mget{}

分页

GET /_search?size=5&from=5

轻量搜索

GET /_all/tweet/_search?q=tweet:elasticsearch  查询tweet类型中tweet字段包含elasticsearch单词的所有文档

1.和Elasticsearch交互

java 可以使用Restful API访问

2.ES是面向文档,存储整个对象或文档。es中是对文档进行索引、检索、排序过滤。es使用JSON作为文档序列化格式。

3.使用雇员目录作为实例

索引雇员文档:PUT /megacorp/employee/1{}

检索文档 GET /megacorp/employee/1

单条件查询 GET /megacorp/employee/_search?q=last_name:Smith

查询表达式

GET /megacorp/employee/_search

{

"query" : {

"match" : {

"last_name" : "Smith"

}

}

}

更复杂查询:姓氏为Smith,且年龄大于30的

GET /megacorp/employee/_search

{"query" : {

"bool": {

"must": {

"match" : {

"last_name" : "smith"

}

},

"filter": {

"range" : {

"age" : { "gt" : 30 }

}

}

}

}

}

全文搜索: 使用相似性查询

GET /megacorp/employee/_search

{

"query" : {

"match" : {

"about" : "rock climbing"

}

}

}

match是相似性查询match_phrase精准性查询

高亮搜索: highlight 高亮部分

分析:可以进行聚合操作,相当于sql中group by

分布式特性: 分配文档到容器或分片

集群均衡分配这些分片

复制分片支持数据冗余

请求路由到存有相关数据节点

集群扩容,无缝整合

索引:是指向一个或多个分片的逻辑空间。一个分片可以是主分片或副本分片,索引内的文档归属于一个主分片。

集群中只有一个节点容易故障,只需要启动一个节点防止数据丢失

水平扩容:集群会重新进行分配,保证每个节点分配均匀

主分片在索引创建时就确定下。能够存储最大的数据量。读操作可以同时被主分片或副本所处理,当你拥有越多副本就有越高的吞吐量。

关闭节点

关闭节点会失去分片(主+副),检查集群状况将会为red,其他节点存在分片,其他节点存在这两个主分片的完整副本,新的主节点立即将这个分片在节点上对应的副本分片提升为主分片,集群状态为yellow

如果重新启动,集群会缺失分片再次进行分配。

文档元数据:文档存放哪里(_index) 文档表示对象类别(_type) 文档唯一标识(_id)

悲观并发控制:阻塞访问资源防止冲突

乐观并发控制:文档创建、更新或删除,新版本的文档必须复制到集群其他节点同时也是异步和并发的,这些复制请求被并行发送,并到达目的地顺序是乱的,es需要一种方法确保旧版本不会覆盖新版本

当文档修改版本号递增。ES使用version号确保变更以正确顺序得到执行。我们利用version号确保应用中相互冲突的变更不会导致数据丢失。通过指定想要修改文档的 version 号来达到这个目的如果该版本不是当前版本号,我们的请求将会失败(报错)。

更新整个文档:检索并修改它,然后重新索引整个文档。

update更新 发生在分片内部,这样避免多次请求的网络开销。通过检索和重建索引的时间

文档存储

shard = hash(文档ID)%主分片的数量。得到的余数就是我们寻求文档所在的分片的位置。所以创建索引就确定好主分片的数量不会改变

主副节点交互

ES文档更新、删除、创建,新版文档复制到集群中其他节点

ES版本冲突 ES是异步和并发的,这些复制被并发发送。为确保旧版本不会覆盖新版本,每个文档都有一个version号,当文档被修改时版本号递增。如果旧版本文档在新版本之后到达,它可以被简单忽略。

新建索引

客户端发送新建索引请求,节点通过文档ID确定它属于那个分片。不在该节点则会被转发到node3.node3在主分片执行请求成功,将请求转发给其他节点。成功后Node 3 将向协调节点报告成功,协调节点向客户端报告成功

ES为了确保完整性consistency一致性,试图执行写操作,主分片要求规定数量的分片副本处于活跃可用状态。consistency设为one时,只要主分片OK就允许执行写操作,all主分片和副本分片都没问题才允许执行写

路由文档到一个分片中

当索引文档时,文档被存储到一个主分片。在创建文档时,文档会按照公式路由到相应的分片中 shard = hash(routing) % number_of_primary_shards,所以在创建时就确定好主分片的数量

新建文档

1.客户端发送请求

2.节点使用文档ID确定文档属于哪个分片,并将转发到相应分片。

3.分配后并执行成功后将请求并行转给其他分片的副本上。

4.一旦所有副本分片成功,该分片向协调节点报告成功返回给客户端。

当在试图执行写操作之前,主分片要求有规定数量的分片副本处于活跃可用状态,才会执行写操作。为了避免网络分区故障时进行写操作,进而导致数据不一致。

取回单文档

1.客户端发送请求  2.节点使用文档ID确定文档属于哪个分片。

在solr中,使用一个或多个ducument构建索引

Document包括多个Field(包括名称、内容、solr如何处理内容的元数据)

上一篇 下一篇

猜你喜欢

热点阅读