Elasticsearch-介绍

参考地址

1、http://www.ruanyifeng.com/blog/2017/08/elasticsearch.html

2、https://www.cnblogs.com/smartloli/p/6978645.html

3、http://www.infoq.com/cn/articles/apache-kafka

 

基本概念

Node 与 Cluster

Elastic 本质上是一个分布式数据库,允许多台服务器协同工作,每台服务器可以运行多个 Elastic 实例。

单个 Elastic 实例称为一个节点(node)。一组节点构成一个集群(cluster)。

 Index

Elastic 会索引所有字段,经过处理后写入一个反向索引(Inverted Index)。查找数据的时候,直接查找该索引。

所以,Elastic 数据管理的顶层单位就叫做 Index(索引)。它是单个数据库的同义词。每个 Index (即数据库)的名字必须是小写。

Document

Index 里面单条的记录称为 Document(文档)。许多条 Document 构成了一个 Index。相当于关系数据库表中的一个记录。

Type

Document 可以分组,比如weather这个 Index 里面,可以按城市分组(北京和上海),也可以按气候分组(晴天和雨天)。这种分组就叫做 Type,它是虚拟的逻辑分组,用来过滤 Document。相当于关系数据库中的一个表。

不同的 Type 应该有相似的结构(schema),举例来说,id字段不能在这个组是字符串,在另一个组是数值。这是与关系型数据库的表的一个区别。性质完全不同的数据(比如productslogs)应该存成两个 Index,而不是一个 Index 里面的两个 Type(虽然可以做到)。

根据规划,Elastic 6.x 版只允许每个 Index 包含一个 Type,7.x 版将会彻底移除 Type。

这是因为lucene内部是没有type的概念的,并且是会将所有type下的字段平铺来存储的,所以所有不同type下的字段也不得重名。并且此时的字段也是没有类型的,统一存储为不透明字节。

文档

文档元数据

_index文档在哪存放

_type文档表示的对象类别

根据规划,Elastic 6.x 版只允许每个 Index 包含一个 Type,7.x 版将会彻底移除 Type。

这是因为lucene内部是没有type的概念的,并且是会将所有type下的字段平铺来存储的,所以所有不同type下的字段也不得重名。并且此时的字段也是没有类型的,统一存储为不透明字节。

_id文档唯一标识

_source

存储JSON格式源数据,可以选择是否存储该字段用于节省空间。

_all

会将_source中所有字段的值连成一个字符串,在不指定字段查询时就会查询该字段。该字段同样可以配置启用还是不启用,也可以自定义字段。

 

索引

分为正排索引和倒排索引两种,默认会为每个字段创建两种索引。

正排索引

正排索引就是数据库中的根据字段值创建索引,用于相等、范围等查询条件,还可以用于字段排序和聚合。主键索引是主键_id到文档内容的索引,非主键索引是字段到主键_id的映射。

可以通过doc_values字段来禁用正排索引。

倒排索引

倒排索引就是将字段中的关键字拆分,然后创建关键字到文档id的索引,然后再根据字段id得到字段内容。其实是先用倒排索引查找到文档id,然后再使用文档id的正排索引查找到文档内容。可以通过index字段来禁用。

倒排索引分为单词词典和倒排列表两种结构。

单词词典,记录所有的单词,以及单词到倒排列表之间的关联关系。一般使用B+树或者哈希拉链法实现,以满足快速的插入和查询。

倒排列表,记录单词对应的文档信息,由倒排索引项构成。每个索引项包含下列信息:

文档ID

词频TF:单词在文档中出现的次数,用于相关项评分

位置:单词在文档分词中的位置,也就是单词索引,用于文档搜索

偏移:记录单词的开始结束位置,用于高亮显示。

Field_Data

Text类型字段没有doc_values,因此也没法进行排序和聚合处理,但是可以使用Field_Data来实现,但是Field_Data是不会在索引时创建的,只会在第一次使用时动态创建,存储在JVM的heap,因此该功能也是默认关闭的,因为动态创建会造成效率下降,并且还会占用大量的JVM空间。并且使用Text类型的分词进行排序和聚合是没有意义的,因此这个功能尽量不要开启。

而正排索引和倒排索引则是在索引创建时生成的,存储在磁盘中。

 

映射(Mapping)

ES中,所有的文档在存储之前都要首先进行分析。用户可根据需要定义如何将文本分割成token、哪些token应该被过滤掉,以及哪些文本需要进行额外处理等等。

 

分片(Shard)和副本(Replica)

ES的“分片(shard)”机制可将一个索引内部的数据分布地存储于多个节点,它通过将一个索引切分为多个底层物理的Lucene索引完成索引数据的分割存储功能,这每一个物理的Lucene索引称为一个分片(shard)。

每个分片其内部都是一个全功能且独立的索引,因此可由集群中的任何主机存储。创建索引时,用户可指定其分片的数量,默认数量为5个。

Shard有两种类型:primary和replica,即主shard及副本shard。

Primary shard用于文档存储,每个新的索引会自动创建5个Primary shard,当然此数量可在索引创建之前通过配置自行定义,不过,一旦创建完成,其Primary shard的数量将不可更改。

Replica shard是Primary Shard的副本,用于冗余数据及提高搜索性能。

每个Primary shard默认配置了一个Replica shard,但也可以配置多个,且其数量可动态更改。ES会根据需要自动增加或减少这些Replica shard的数量。

ES集群可由多个节点组成,各Shard分布式地存储于这些节点上。同一分片的主分片和副本分片不能分配在同一节点上,如果只有一个节点导致副本分片无法分配会导致集群变黄。

ES可自动在节点间按需要移动shard,例如增加节点或节点故障时。

简而言之,分片实现了集群的分布式存储,而副本实现了其分布式处理及冗余功能。

健康度

如果主分片无法分配会导致集群变红。

如果副本分片无法分配会导致集群变黄。

主分片和副本分片都正常分配集群才是绿色的。

插件

ElasticSearch在设计上支持插件式体系结构,用户可根据需要通过插件来增强ElasticSearch的功能。

目前,常用的通过插件扩展的功能包括添加自定义映射类型、自定义分析器、本地脚本、自定义发现方式等等。

安装及移除插件

插件的安装有两种方式:直接将插件放置于plugins目录中,或通过plugin脚本进行安装。

Marvel、BigDesk及Head这三个是较为常用的插件。

REST API

ElasticSearch提供了易用但功能强大的RESTful API以用于与集群进行交互,这些API大体可分为如下四类:

(1) 检查集群、节点、索引等健康与否,以及获取其相关状态与统计信息;
(2) 管理集群、节点、索引数据及元数据;
(3) 执行CRUD操作及搜索操作;
(4) 执行高级搜索操作,例如paging、filtering、scripting、faceting、aggregations及其它操作;

ELK

ElasticSearch是有其自己的套件的,简称ELK,即ElasticSearch,Logstash以及Kibana。ElasticSearch负责存储,Logstash负责收集数据来源,Kibana负责可视化数据,分工明确。想要分流Kafka中的消息数据,可以使用Logstash的插件直接消费,但是需要我们编写复杂的过滤条件,和特殊的映射处理,比如系统保留的`_uid`字段等需要我们额外的转化。今天我们使用另外一种方式来处理数据,使用Kafka的消费API和ES的存储API来处理分流数据。通过编写Kafka消费者,消费对应的业务数据,将消费的数据通过ES存储API,通过创建对应的索引的,存储到ES中。其流程如下图所示:

  上图可知,消费收集的数据,通过ES提供的存储接口进行存储。存储的数据,这里我们可以规划,做定时调度。最后,我们可以通过Kibana来可视化ES中的数据,对外提供业务调用接口,进行数据共享。

 

routing路由机制

es默认是将数据平均的存储到所有的主分片上,机制就是根据_id的哈希值对主分片数取模,得到的值就是存储的主分片序号。因为_id是随机的,因此能保证随机存储。

但是这种随机平均存储也有一些缺点,比如所有的查询都会去每一个主分片查询,然后将各主分片的返回值汇总之后在返回真正的结果,这样就比较浪费CPU和内存的资源,如果将常用查询条件的同一个值保存在一个主分片上,查询时也可以保证只查这一个分片就够了,这样大大的降低了资源的消耗,通过将取模的值从_id改为常用搜索的字段值就可以了,然后再搜索时也指定使用该字段的routing就可以了。

虽然指定routing可以提高搜索效率,但也可能造成各分片存储资源的不平衡,各节点的磁盘使用不一致,因此要谨慎使用。

 

优化搜索效率的思路

1、数据节点尽可能的多,主分片数跟数据节点保持一致,或者考虑到数据节点的水平扩展,将主分片数设置为数据节点的二倍,设为2倍,是为了每个数据节点上的主分片的数据是一致的,也保证了数据的平均分配,否则就会造成各节点的数据倾斜

2、设置副本分片,分担主分片的查询负载

3、根据时间每天创建一个新的索引,将每天的索引都关联同一个别名,然后使用别名进行搜索。同时对数据定时删除,删除多少天之前的数据,这时也不需要使用deletebyquery,这个删数据太慢,并且数据也不能马上降下来,短时间内还会造成数据的丢失,直接删掉多少天之前的索引就可以了。

posted on 2020-03-28 10:08  simple_孙  阅读(200)  评论(0编辑  收藏  举报

导航