个人笔记--Elasticsearch

ES是如何产生的?

(1)思考:大规模数据如何检索?

如:当系统数据量上了10亿、100亿条的时候,我们在做系统架构的时候通常会从以下角度去考虑问题: 

1)用什么数据库好?(mysql、sybase、oracle、达梦、神通、mongodb、hbase…) 

2)如何解决单点故障;(lvs、F5、A10、Zookeep、MQ) 

3)如何保证数据安全性;(热备、冷备、异地多活) 

4)如何解决检索难题;(数据库代理中间件:mysql-proxy、Cobar、MaxScale等;) 

5)如何解决统计分析问题;(离线、近实时)

(2)传统数据库的应对解决方案

对于关系型数据,我们通常采用以下或类似架构去解决查询瓶颈和写入瓶颈: 

解决要点: 

1)通过主从备份解决数据安全性问题; 

2)通过数据库代理中间件心跳监测,解决单点故障问题; 

3)通过代理中间件将查询语句分发到各个slave节点进行查询,并汇总结果 

(3)非关系型数据库的解决方案

对于Nosql数据库,以mongodb为例,其它原理类似: 

解决要点: 

1)通过副本备份保证数据安全性; 

2)通过节点竞选机制解决单点问题; 

3)先从配置库检索分片信息,然后将请求分发到各个节点,最后由路由节点合并汇总结果 

另辟蹊径——完全把数据放入内存怎么样?

我们知道,完全把数据放在内存中是不可靠的,实际上也不太现实,当我们的数据达到PB级别时,按照每个节点96G内存计算,在内存完全装满的数据情况下,我们需要的机器是:1PB=1024T=1048576G 

节点数=1048576/96=10922个 

实际上,考虑到数据备份,节点数往往在2.5万台左右。成本巨大决定了其不现实!

从前面讨论我们了解到,把数据放在内存也好,不放在内存也好,都不能完完全全解决问题。 

全部放在内存速度问题是解决了,但成本问题上来了。 

为解决以上问题,从源头着手分析,通常会从以下方式来寻找方法: 

1、存储数据时按有序存储; 

2、将数据和索引分离; 

3、压缩数据; 

这就引出了Elasticsearch。

1. ES 基础一网打尽

1.1 ES定义

ES=elaticsearch简写, Elasticsearch是一个开源的高扩展的分布式全文检索引擎,它可以近乎实时的存储、检索数据;本身扩展性很好,可以扩展到上百台服务器,处理PB级别的数据。 

Elasticsearch也使用Java开发并使用Lucene作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的RESTful API来隐藏Lucene的复杂性,从而让全文搜索变得简单。

1.2 Lucene与ES关系?

1)Lucene只是一个库。想要使用它,你必须使用Java来作为开发语言并将其直接集成到你的应用中,更糟糕的是,Lucene非常复杂,你需要深入了解检索的相关知识来理解它是如何工作的。

2)Elasticsearch也使用Java开发并使用Lucene作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的RESTful API来隐藏Lucene的复杂性,从而让全文搜索变得简单。

1.3 ES主要解决问题:

1)检索相关数据; 

2)返回统计结果; 

3)速度要快。

1.4 ES工作原理

当ElasticSearch的节点启动后,它会利用多播(multicast)(或者单播,如果用户更改了配置)寻找集群中的其它节点,并与之建立连接。这个过程如下图所示: 

1.5 ES核心概念

1)Cluster:集群。

ES可以作为一个独立的单个搜索服务器。不过,为了处理大型数据集,实现容错和高可用性,ES可以运行在许多互相合作的服务器上。这些服务器的集合称为集群。

2)Node:节点。

形成集群的每个服务器称为节点。

3)Shard:分片。

当有大量的文档时,由于内存的限制、磁盘处理能力不足、无法足够快的响应客户端的请求等,一个节点可能不够。这种情况下,数据可以分为较小的分片。每个分片放到不同的服务器上。 

当你查询的索引分布在多个分片上时,ES会把查询发送给每个相关的分片,并将结果组合在一起,而应用程序并不知道分片的存在。即:这个过程对用户来说是透明的。

4)Replia:副本。

为提高查询吞吐量或实现高可用性,可以使用分片副本。 

副本是一个分片的精确复制,每个分片可以有零个或多个副本。ES中可以有许多相同的分片,其中之一被选择更改索引操作,这种特殊的分片称为主分片。 

当主分片丢失时,如:该分片所在的数据不可用时,集群将副本提升为新的主分片。

5)全文检索。

全文检索就是对一篇文章进行索引,可以根据关键字搜索,类似于mysql里的like语句。 

全文索引就是把内容根据词的意义进行分词,然后分别创建索引。

1.6 ES数据架构的主要概念(与关系数据库Mysql对比)

在一个关系型数据库里面,schema定义了表、每个表的字段,还有表和字段之间的关系。 与之对应的,在ES中:Mapping定义索引下的Type的字段处理规则,即索引如何建立、索引类型、是否保存原始索引JSON文档、是否压缩原始JSON文档、是否需要分词处理、如何进行分词处理等。 

参考:图解Elasticsearch中的_source、_all、store和index属性

1.7 ELK是什么?

ELK=elasticsearch+Logstash+kibana 

elasticsearch:后台分布式存储以及全文检索 

logstash: 日志加工、“搬运工” 

kibana:数据可视化展示。 

ELK架构为数据分布式存储、可视化查询和日志解析创建了一个功能强大的管理链。 三者相互配合,取长补短,共同完成分布式大数据处理工作。

2. ES特点和优势

1)分布式实时文件存储,可将每一个字段存入索引,使其可以被检索到。 

2)实时分析的分布式搜索引擎。 

分布式:索引分拆成多个分片,每个分片可有零个或多个副本。集群中的每个数据节点都可承载一个或多个分片,并且协调和处理各种操作; 

负载再平衡和路由在大多数情况下自动完成。 

3)可以扩展到上百台服务器,处理PB级别的结构化或非结构化数据。也可以运行在单台PC上(已测试) 

4)支持插件机制,分词插件、同步插件、Hadoop插件、可视化插件等。

3、ES性能

3.1 性能结果展示

(1)硬件配置: 

CPU 16核 AuthenticAMD 

内存 总量:32GB 

硬盘 总量:500GB 非SSD

(2)在上述硬件指标的基础上测试性能如下: 

1)平均索引吞吐量: 12307docs/s(每个文档大小:40B/docs) 

2)平均CPU使用率: 887.7%(16核,平均每核:55.48%) 

3)构建索引大小: 3.30111 GB 

4)总写入量: 20.2123 GB 

5)测试总耗时: 28m 54s.

4. ES的应用场景是怎样的?

通常我们面临问题有两个:

1)新系统开发尝试使用ES作为存储和检索服务器; 

2)现有系统升级需要支持全文检索服务,需要使用ES。 

参考:Elasticsearch的使用场景深入详解

5. 如何部署ES?

1)java版本要求:最低1.7 

2)下载地址: 

3)启动 

bin/elasticsearch.bat 

输入如下网址,结果是下面这样代表成功安装(单实例运行成功)

4)关闭 

需要对ES节点进行重新启动或正常关机的时候,有三种方法可以关闭ES:

1.在控制台中,使用CTRL+C组合键.

2.通过发送TERM信号终止服务器进程.

3.使用REST APIcurl -XPOST 'http://localhost:9200/_shutdown'.

5)安装插件:

Head插件

使用:

在head源代码目录下启动nodejs:

grunt server

访问地址:http://localhost:9100

6. ES对外接口

1)JAVA API接口

https://www.elastic.co/guide/en/elasticsearch/client/java-api/5.6/index.html

https://www.elastic.co/guide/en/elasticsearch/client/java-rest/5.6/java-rest-high-search.html

1.简介

  它提供了两种方法连接到Elasticsearch:创建一个本地节点并加入集群(cluster),或者利用传输(transport)。这两种方法都是利用一个Client(org.elasticsearch.client.Client)实例来实现的。

2.两种连接方法的说明和比较

  使用第一种方法的思想,是讲创建的本地节点作为集群的一部分,这样这个创建的本地节点就可以是知道整个集群的情况,比如relevant shard是如何分配的已经如何进行高效的查询。

Node node = nodeBuilder().clusterName("escluster2").client(true).node();   Client client = node.client();

使用NodeBuilder来创建一个node,使用clusterName()方法来指定我们想要连接的集群。为了避免本地节点关机后集群将shard移动到本地节点,从而造成数据丢失的情况,我们需要client(true);

  第二种方法:通过ImmutableSettings我们设置了希望连接的集群的名称,接下来创建了一个TransportClient,通过建立InetSocketTransportAddress实例来提供Elasticsearch server所在的IP地址已经传输层的监听端口(JAVA API 默认9300,并非REST API的9200 )。

Settings settings = ImmutableSettings.settingsBuilder()         .put("cluster.name", "escluster2").build(); TransportClient client = new TransportClient(settings); client.addTransportAddress(new InetSocketTransportAddress("127.0.0.1", 9300));

关于两种方法的选择,第一种方法:建立本地节点会需要一些时间,但是在执行一些操作的事情会节省很多时间,因为本地阶段知道整个集群中indice和shard情况。 第二种方法:建立TransportClient是比较高效的,但是发送查询信息以及数据就需要更多的资源,因为TransportClient不清楚整个集群的拓扑,所以她不能直接将数据发送到目的节点,而是发送至一个初始化后的transport节点,ElasticSearch完成接下来的转发。  注意:如果需要连接到不用网络中的Elasticsearch集群,就必须使用第二种方法(TransportClient对象)。

聚合:

桶(Buckets)

满足特定条件的文档的集合

指标(Metrics)

对桶内的文档进行统计计算

如:最小值、平均值、最大值,还有汇总

翻译成粗略的SQL语句来解释吧:

SELECT COUNT(color)  FROM table GROUP BY color 
1.COUNT(color) 相当于指标(Metrics)。
2.GROUP BY color 相当于桶(Bucket)。

term是代表完全匹配,也就是精确查询,搜索前不会再对搜索词进行分词,所以我们的搜索词必须是文档分词集合中的一个

TermsBuilder:构造聚合函数

AggregationBuilders:创建聚合函数工具类

BoolQueryBuilder:拼装连接(查询)条件

QueryBuilders:简单的静态工厂”导入静态”使用。主要作用是查询条件(关系),如区间\精确\多值等条件

NativeSearchQueryBuilder:将连接条件和聚合函数等组合

SearchQuery:生成查询

elasticsearchTemplate.query:进行查询

Aggregations:Represents a set of computed addAggregation.代表一组添加聚合函数统计后的数据

Aggregations种类分为:

l  Metrics, Metrics 是简单的对过滤出来的数据集进行avg,max等操作,是一个单一的数值。

l  java api:AggregationBuilders.dateHistogram

l  Bucket, Bucket 你则可以理解为将过滤出来的数据集按条件分成多个小数据集,然后Metrics会分别作用在这些小数据集上。

l  java api:AggregationBuilders.terms

例子1:

在ES里面所有的聚合实例都由AggregationBuilders类提供静态方法构造,我们先看下常用有哪些方法使用:

(1)统计某个字段的数量   ValueCountBuilder vcb=  AggregationBuilders.count("count_uid").field("uid"); (2)去重统计某个字段的数量(有少量误差)  CardinalityBuilder cb= AggregationBuilders.cardinality("distinct_count_uid").field("uid"); (3)聚合过滤 FilterAggregationBuilder fab= AggregationBuilders.filter("uid_filter").filter(QueryBuilders.queryStringQuery("uid:001")); (4)按某个字段分组 TermsBuilder tb=  AggregationBuilders.terms("group_name").field("name"); (5)求和 SumBuilder  sumBuilder= AggregationBuilders.sum("sum_price").field("price"); (6)求平均 AvgBuilder ab= AggregationBuilders.avg("avg_price").field("price"); (7)求最大值 MaxBuilder mb= AggregationBuilders.max("max_price").field("price");  (8)求最小值 MinBuilder min= AggregationBuilders.min("min_price").field("price"); (9)按日期间隔分组 DateHistogramBuilder dhb= AggregationBuilders.dateHistogram("dh").field("date"); (10)获取聚合里面的结果 TopHitsBuilder thb=  AggregationBuilders.topHits("top_result"); (11)嵌套的聚合 NestedBuilder nb= AggregationBuilders.nested("negsted_path").path("quests"); (12)反转嵌套 AggregationBuilders.reverseNested("res_negsted").path("kps ");

上面这些基本就是常用的聚合查询了,在嵌套(nested)下面的子聚合查询就是嵌套查询了,除了嵌套查询,其他的聚合查询也可以无限级添加子查询

举一个二级分组的例子:

SearchRequestBuilder search = client.prepareSearch("index").setTypes("type");  TermsBuilder one=  AggregationBuilders.terms("group_name").field("name"); TermsBuilder two=  AggregationBuilders.terms("group_age").field("age"); one.subAggregation(two) search.addAggregation(one);    Terms terms= search.get().getAggregations().get("group_name");   for(Terms.Bucket name_buk:terms.getBuckets()){    //一级分组的内容    Terms terms_age= name_buk.getAggregations().get("group_age");    for(Terms.Bucket age_buk:terms_age.getBuckets()){     //二级分组的内容      System.out.println(name_buk.getKey()+"  "+age_buk.getKey()+"  "+age_buk.getDocCount());     } }

注意上面的例子 ,二级子查询可以添加多种类型,比如第一级按照名字分组,第二级可以添加一个max或者min的子聚合查询。

下面看一个嵌套聚合的例子:

-        //嵌套查询root节点   NestedBuilder nestedBuilder= AggregationBuilders.nested("negsted").path("quests");   //嵌套查询的子查询中分组count   TermsBuilder tb=  AggregationBuilders.terms("group_name").field("quests.name");    //添加子查询到root节点里面   nestedBuilder.subAggregation(tb);   //获取一级嵌套      Nested ntd= search.get().getAggregations().get("negsted");         //打印一级嵌套的结果   System.out.println(ntd.getDocCount());   //从一级嵌套查询的结果中获取二级嵌套查询结果    Terms term=  ntd.getAggregations().get("group_name");   //获取嵌套下面的结果   for(Terms.Bucket tbket:term.getBuckets()){    System.out.println(tbket.getKey()+"  "+tbket.getDocCount());   }

嵌套的查询功能非常丰富,此外还有更强大Pipeline Aggregations聚合可以对上层的嵌套结果继续做操作,例如sql里面的having功能也可以实现,本篇简单的介绍了es的聚合查询的种类和简单使用,感兴趣的朋友可以通过官网详细学习下。

/*例子2:

    计算每个球队总年薪,并按照总年薪倒序排列

    select team, sum(salary) as total_salary from player group by team order by total_salary desc;

    TermsBuilder teamAgg= AggregationBuilders.terms("team").order(Order.aggregation("total_salary ", false);

    SumBuilder salaryAgg= AggregationBuilders.avg("total_salary ").field("salary");

    sbuilder.addAggregation(teamAgg.subAggregation(salaryAgg));

    SearchResponse response = sbuilder.execute().actionGet();

    需要特别注意的是,排序是在TermAggregation处执行的,Order.aggregation函数的第一个参数是aggregation的名字,第二个参数是boolean型,true表示正序,false表示倒序。

    默认情况下,search执行后,仅返回10条聚合结果,如果想返回更多的结果,需要在构建TermsBuilder 时指定size

    TermsBuilder teamAgg= AggregationBuilders.terms("team").size(15);

    总结:

    聚合操作主要是调用了SearchRequestBuilder的addAggregation方法,通常是传入一个TermsBuilder,子聚合调用TermsBuilder的subAggregation方法,可以添加的子聚合有TermsBuilder、SumBuilder、AvgBuilder、MaxBuilder、MinBuilder等常见的聚合操作。

    从实现上来讲,SearchRequestBuilder在内部保持了一个私有的 SearchSourceBuilder实例, SearchSourceBuilder内部包含一个List<AbstractAggregationBuilder>,每次调用addAggregation时会调用 SearchSourceBuilder实例,添加一个AggregationBuilder。

    同样的,TermsBuilder也在内部保持了一个List<AbstractAggregationBuilder>,调用addAggregation方法(来自父类addAggregation)时会添加一个AggregationBuilder

* */

API:

https://www.elastic.co/guide/en/elasticsearch/client/java-rest/5.6/java-rest-high-aggregation-builders.html

2)RESTful API接口

常见的增、删、改、查操作实现: 

http://blog.csdn.net/laoyang360/article/details/51931981

A.query_string参数

如:GET /index/type/_search  ==》搜索所有文档

官网参考:

https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html

Elasticsearch 默认按照相关性得分排序,即每个文档跟查询的匹配程度

B.查询表达式

高亮设置:

https://www.elastic.co/guide/en/elasticsearch/reference/master/search-request-highlighting.html

Elasticsearch检索分类深入详解—基础篇

 http://blog.sina.com.cn/s/blog_17784909f0102xwd0.html

7.ES遇到问题怎么办?

1)国外:https://discuss.elastic.co/ 

2)国内:http://elasticsearch.cn/

8.Elasticsearch 尽可能地屏蔽了分布式系统的复杂性。这里列举了一些后台自动执行的操作:

l  分配文档到不同的容器 或 分片 中,文档可以储存在一个或多个节点中

l  按集群节点来均衡分配这些分片,从而对索引和搜索过程进行负载均衡

l  复制每个分片以支持数据冗余(重复的数据),从而防止硬件故障导致的数据丢失

l  将集群中任一节点的请求路由到存有相关数据的节点

l  集群扩容时无缝整合新节点,重新分配分片以便从离群节点恢复

9.集群内原理

如果我们启动了一个单独的节点,里面不包含任何的数据和索引,那我们的集群看起来就是下图:

图 1. 包含空内容节点的集群

一个运行中的 Elasticsearch 实例称为一个节点,而集群是由一个或者多个拥有相同 cluster.name 配置的节点组成, 它们共同承担数据和负载的压力。当有节点加入集群中或者从集群中移除节点时,集群将会重新平均分布所有的数据。

当一个节点被选举成为主节点时, 它将负责管理集群范围内的所有变更,例如增加、删除索引,或者增加、删除节点等。 而主节点并不需要涉及到文档级别的变更和搜索等操作,所以当集群只拥有一个主节点的情况下,即使流量的增加它也不会成为瓶颈。 任何节点都可以成为主节点。

作为用户,我们可以将请求发送到 集群中的任何节点 ,包括主节点。 每个节点都知道任意文档所处的位置,并且能够将我们的请求直接转发到存储我们所需文档的节点。 无论我们将请求发送到哪个节点,它都能负责从各个包含我们所需文档的节点收集回数据,并将最终结果返回給客户端。 Elasticsearch 对这一切的管理都是透明的。

集群健康==》

Elasticsearch 的集群监控信息中包含了许多的统计数据,其中最为重要的一项就是 集群健康,它在 status 字段中展示为 green 、 yellow 或者 red 。

查看状态:

GET /_cluster/health

三种状态:

green

所有的主分片和副本分片都正常运行。

yellow

所有的主分片都正常运行,但不是所有的副本分片都正常运行。

red

有主分片没能正常运行。

添加索引

我们往 Elasticsearch 添加数据时需要用到索引——保存相关数据的地方。索引实际上是指向一个或者多个物理分片的逻辑命名空间 

分片内部原理:

https://www.elastic.co/guide/cn/elasticsearch/guide/current/inside-a-shard.html

一个分片是一个 Lucene 的实例,以及它本身就是一个完整的搜索引擎

我们的文档被存储和索引到分片内,但是应用程序是直接与索引而不是与分片进行交互

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

索引内任意一个文档都归属于一个主分片,所以主分片的数目决定着索引能够保存的最大数据量

技术上来说,一个主分片最大能够存储 Integer.MAX_VALUE - 128 个文档,但是实际最大值还需要参考你的使用场景:包括你使用的硬件, 文档的大小和复杂程度,索引和查询文档的方式以及你期望的响应时长

在索引建立的时候就已经确定了主分片数,但是副本分片数(备份)可以随时修改。

索引在默认情况下会被分配5个主分片 但是为了演示目的,我们将分配3个主分片和一份副本(每个主分片拥有一个副本分片):

PUT /blogs {    "settings" : {       "number_of_shards" : 3,       "number_of_replicas" : 1    } }

我们的集群现在是下图  所有3个主分片都被分配在 Node 1 。

图 2. 拥有一个索引的单节点集群

如果我们现在查看集群健康, 我们将看到如下内容:

{   "cluster_name": "elasticsearch",   "status": "yellow",

   "timed_out": false,   "number_of_nodes": 1,   "number_of_data_nodes": 1,   "active_primary_shards": 3,   "active_shards": 3,   "relocating_shards": 0,   "initializing_shards": 0,   "unassigned_shards": 3,

"delayed_unassigned_shards": 0,   "number_of_pending_tasks": 0,   "number_of_in_flight_fetch": 0,   "task_max_waiting_in_queue_millis": 0,   "active_shards_percent_as_number": 50 }

1.集群 status 值为 yellow 。

2.没有被分配到任何节点的副本数。

集群的健康状况为 yellow 则表示全部主分片都正常运行(集群可以正常服务所有请求),但是副本分片没有全部处在正常状态。 实际上,所有3个副本分片都是 unassigned —— 它们都没有被分配到任何节点。 在同一个节点上既保存原始数据又保存副本是没有意义的,因为一旦失去了那个节点,我们也将丢失该节点上的所有副本数据。

当前我们的集群是正常运行的,但是在硬件故障时有丢失数据的风险。

添加故障转移

当你在同一台机器上启动了第二个节点时,只要它和第一个节点有同样的 cluster.name 配置,它就会自动发现集群并加入到其中。 但是在不同机器上启动节点的时候,为了加入到同一集群,你需要配置一个可连接到的单播主机列表。

详细信息请查看重要配置的修改:

https://www.elastic.co/guide/cn/elasticsearch/guide/current/important-configuration-changes.html#unicast

如果启动了第二个节点,我们的集群将会下图。

图 3. 拥有两个节点的集群——所有主分片和副本分片都已被分配

当第二个节点加入到集群后,3个 副本分片 将会分配到这个节点上——每个主分片对应一个副本分片。 这意味着当集群内任何一个节点出现问题时,我们的数据都完好无损。

所有新近被索引的文档都将会保存在主分片上,然后被并行的复制到对应的副本分片上。这就保证了我们既可以从主分片又可以从副本分片上获得文档。

cluster-health 现在展示的状态为 green ,这表示所有6个分片(包括3个主分片和3个副本分片)都在正常运行。

{   "cluster_name": "elasticsearch",   "status": "green",

"timed_out": false,   "number_of_nodes": 2,   "number_of_data_nodes": 2,   "active_primary_shards": 3,   "active_shards": 6,   "relocating_shards": 0,   "initializing_shards": 0,   "unassigned_shards": 0,   "delayed_unassigned_shards": 0,   "number_of_pending_tasks": 0,   "number_of_in_flight_fetch": 0,   "task_max_waiting_in_queue_millis": 0,   "active_shards_percent_as_number": 100 }

1.集群 status 值为 green

我们的集群现在不仅仅是正常运行的,并且还处于 始终可用 的状态。

水平扩容

怎样为我们的正在增长中的应用程序按需扩容呢? 当启动了第三个节点,我们的集群将会看起来如下

图 4. 拥有三个节点的集群——为了分散负载而对分片进行重新分配

在运行中的集群上是可以动态调整副本分片数目的 ,我们可以按需伸缩集群。让我们把副本数从默认的 1 增加到 2 :

PUT /blogs/_settings {    "number_of_replicas" : 2 }

如下所示, blogs 索引现在拥有9个分片:3个主分片和6个副本分片。 这意味着我们可以将集群扩容到9个节点,每个节点上一个分片。相比原来3个节点时,集群搜索性能可以提升 3 倍。

图 5. 将参数 number_of_replicas 调大到 2

当然,如果只是在相同节点数目的集群上增加更多的副本分片并不能提高性能,因为每个分片从节点上获得的资源会变少。 你需要增加更多的硬件资源来提升吞吐量。

但是更多的副本分片数提高了数据冗余量:按照上面的节点配置,我们可以在失去2个节点的情况下不丢失任何数据。

如果我们关闭第一个节点,这时集群的状态为下图

图 6. 关闭了一个节点后的集群

我们关闭的节点是一个主节点。而集群必须拥有一个主节点来保证正常工作,所以发生的第一件事情就是选举一个新的主节点: Node 2 。

在我们关闭 Node 1 的同时也失去了主分片 1 和 2 ,并且在缺失主分片的时候索引也不能正常工作。 如果此时来检查集群的状况,我们看到的状态将会为 red :不是所有主分片都在正常工作。

幸运的是,在其它节点上存在着这两个主分片的完整副本, 所以新的主节点立即将这些分片在 Node 2 和 Node 3 上对应的副本分片提升为主分片, 此时集群的状态将会为 yellow 。 这个提升主分片的过程是瞬间发生的,如同按下一个开关一般。

为什么我们集群状态是 yellow 而不是 green 呢? 虽然我们拥有所有的三个主分片,但是同时设置了每个主分片需要对应2份副本分片,而此时只存在一份副本分片。 所以集群不能为 green 的状态,不过我们不必过于担心:如果我们同样关闭了 Node 2 ,我们的程序 依然 可以保持在不丢任何数据的情况下运行,因为 Node 3 为每一个分片都保留着一份副本。

数据输入和输出

Elastcisearch 是分布式的文档存储。它能存储和检索复杂的数据结构--序列化成为JSON文档--以 实时 的方式。 换句话说,一旦一个文档被存储在 Elasticsearch 中,它就是可以被集群中的任意节点检索到。

在 Elasticsearch 中, 每个字段的所有数据 都是 默认被索引的 。 即每个字段都有为了快速检索设置的专用倒排索引。

文档

通常情况下,我们使用的术语 对象 和 文档 是可以互相替换的

区别:对象可能包含了另外一些对象。在 Elasticsearch 中,术语 文档 有着特定的含义。它是指最顶层或者根对象, 这个根对象被序列化成 JSON 并存储到 Elasticsearch 中,指定了唯一 ID。

字段的名字可以是任何合法的字符串,但不可以包含时间段。

文档元数据

三个必须的元数据元素如下:

_index

文档在哪存放

索引管理https://www.elastic.co/guide/cn/elasticsearch/guide/current/index-management.html

命名:必须小写,不能以下划线开头,不能包含逗号

_type

文档表示的对象类别

命名:可以是大写或者小写,但是不能以下划线或者句号开头,不应该包含逗号, 并且长度限制为256个字符

_id

文档唯一标识

要么提供自己的 _id ,

PUT /website/blog/123 {   "title": "My first blog entry",   "text":  "Just trying this out...",   "date":  "2014/01/01" }

在 Elasticsearch 中每个文档都有一个版本号。当每次对文档进行修改时(包括删除), _version 的值会递增。

要么让 Elasticsearch 帮你生成:

 不再使用 PUT 谓词(“使用这个 URL 存储这个文档”), 而是使用 POST 谓词(“存储文档在这个 URL 命名空间下”)。

POST /website/blog/ {   "title": "My second blog entry",   "text":  "Still trying this out...",   "date":  "2014/01/01" }

其他元数据

https://www.elastic.co/guide/cn/elasticsearch/guide/current/mapping.html

 处理冲突:

有一天,管理层决定做一次促销。突然地,我们一秒要卖好几个商品。 假设有两个 web 程序并行运行,每一个都同时处理所有商品的销售,如下图。

图 7. Consequence of no concurrency control

web_1 对 stock_count 所做的更改已经丢失,因为 web_2 不知道它的 stock_count 的拷贝已经过期。 结果我们会认为有超过商品的实际数量的库存,因为卖给顾客的库存商品并不存在,我们将让他们非常失望。

变更越频繁,读数据和更新数据的间隙越长,也就越可能丢失变更。

在数据库领域中,有两种方法通常被用来确保并发更新时变更不会丢失:

悲观并发控制

这种方法被关系型数据库广泛使用,它假定有变更冲突可能发生,因此阻塞访问资源以防止冲突。 一个典型的例子是读取一行数据之前先将其锁住,确保只有放置锁的线程能够对这行数据进行修改。

乐观并发控制

https://www.elastic.co/guide/cn/elasticsearch/guide/current/optimistic-concurrency-control.html

Elasticsearch 中使用的这种方法假定冲突是不可能发生的,并且不会阻塞正在尝试的操作。 然而,如果源数据在读写当中被修改,更新将会失败。应用程序接下来将决定该如何解决冲突。 例如,可以重试更新、使用新的数据、或者将相关情况报告给用户。

文档的部分更新

https://www.elastic.co/guide/cn/elasticsearch/guide/current/partial-updates.html

程攀博客:

http://blog.csdn.net/napoay/article/category/6507166/1

ELK:

https://www.cnblogs.com/xing901022/p/4704319.html

猜你喜欢

转载自www.cnblogs.com/kz2017/p/9008778.html