ElasticSearch总结

简介

ElasticSearch 是一个基于 Lucene 的搜索服务器。它提供了一个分布式多用户能力的全 文搜索引擎,基于 RESTful web 接口。Elasticsearch 是用 Java 开发的,并作为 Apache 许可 条款下的开放源码发布,是当前流行的企业级搜索引擎。

场景

(1)为用户提供按关键字查询的全文搜索功能。
(2)实现企业海量数据的处理分析的解决方案。大数据领域的重要一份子,如著名的 ELK 框架(ElasticSearch,Logstash,Kibana)。 
(3)作为 OLAP 数据库,对数据进行统计分析。

数据库比较

在这里插入图片描述
在这里插入图片描述

特点

天然的分布式数据库

ES 把数据分成多个 shard(分片),下图中的 P0-P2,多个 shard 可以组成一份完整的数据,这些 shard 可以分布在集群中的各个机器节点中。随着数据的不断增加,集群可以增加多个分片,把多个分片放到多个机子上进行备份,已达到负载均衡,横向扩展。

在这里插入图片描述

天然索引之倒排索引

ES 所有数据都是默认进行索引的,这点和 mysql 正好相反,mysql 是默认不加索引, 要加索引必须特别说明,ES 只有不加索引才需要说明。而 ES 使用的是倒排索引和 Mysql 的 B+Tree 索引不同。
1. 传统关系型数据库索引
	记录->单词
	弊端:对于传统的关系性数据库对于关键词的查询,只能逐字逐行的匹配,性能非常差。匹配方式不合理,比如搜索“小密手机” ,如果用           like 进行匹配, 根本匹配不到。但是考虑使用者的用户体验的话,除了完全匹配的记录,还应该显示一部分近似匹配的记录,至           少应该匹配到“手机”。

在这里插入图片描述

2. 倒排索引
  (1)传统的保存数据的方式是 记录 → 单词

在这里插入图片描述

(2)倒排索引的保存数据的方式是 单词→记录
   那么全文索引通常,还会根据匹配程度进行打分,显然 1 号记录能匹配的次数更多。所以显示的时候以评分进行排序的话,1 号记录会排到    最前面。而 2、3 号记录也可以匹配到。

在这里插入图片描述

Es的核心:lucene 倒排索引结构

在这里插入图片描述

可以看到 lucene 为倒排索引(Term Dictionary)部分又增加一层 Term Index 结构,用于快速定位(相当于新华字典中的根据字母查找字),而这 Term Index 是缓存在内存中的,但 mysql 的 B+tree 不在内存中,所以整体 来看 ES 速度更快,但同时也更消耗资源(内存、磁盘)。
                            Term index → Term dictionary → posting list

天然索引之正排索引( Doc Value 列式存储)

1. 倒排索引在搜索包含指定词条的文档时非常高效,但是在相反的操作时表现很差:查询 一个文档中包含哪些词条。具体来说,倒排索引在搜    索时最为高效,但在排序、聚合等与指 定字段相关的操作时效率低下,需要用 doc_values。
2. 列式存储结构非常适合排序、聚合以及字段相关的脚本操作。而且这种存储方式便于压缩,尤其是数字类型。压缩后能够大大减少磁盘空      间,提升访问速度。

Kibana

Kibana 是为 Elasticsearch 设计的开源分析和可视化平台。你可以使用 Kibana 来搜索, 查看存储在 Elasticsearch 索引中的数据并与之交互。你可以很容易实现高级的数据分析和 可视化,以图表的形式展现出来。

DSL

Domain Specific language 特定领域专用语言

名词解释

在这里插入图片描述

对数据的操作

保存的数据结构

有如下对象关系,如果使用关系型数据库保存,会被拆分成多张表.
    public class Movie {
    String id;
     String name;
     Double doubanScore;
     List<Actor> actorList;
    }

    public class Actor{
    String id;
    String name;
    }
1. 使用mysql存储的话,存在多对多的情况,因此要有一个中间表来存储关系。一共三张表。moive,actor,moive_actor
    
2. es存储的话使用json来表示一个document。
    {
     "id":"1",
     "name":"operation red sea",
     "doubanScore":"8.5",
     "actorList":[
        {"id":"1","name":"zhangyi"},
        {"id":"2","name":"haiqing"},
        {"id":"3","name":"zhanghanyu"}
    	]
    }

索引操作(index/table)

1. 创建
    PUT movie_index
2. 删除
	DELETE movie_index
3. 查看索引mapping (desc table)
	GET movie_index/_mapping

数据操作 (doc)

1. 新增文档(幂等)指定documentId
    重复执行会更新数据。
    PUT /movie_index/_doc/1
    { "id":1,
     "name":"operation red sea",
     "doubanScore":8.5,
     "actorList":[
        {"id":1,"name":"zhang yi"},
        {"id":2,"name":"hai qing"},
        {"id":3,"name":"zhang han yu"}
        ]
    }

2. 新增文档 (非幂等)
   重复执行会新增重复数据,_id 会随机生成。
    POST /movie_index/_doc
    {
     "id":3,
     "name":"incident red sea",
     "doubanScore":5.0,
     "actorList":[ 
             {"id":4,"name":"atguigu"}
        ]
    }

3. 查询index所有数据
    GET movie_index/_search
    
4. 查询一个document
    GET movie_index/_doc/3
    
5. 按条件查询(全部)
	GET movie_index/_search
    {
     "query": {
     "match_all": {}
             }
         }
    }
6. 整体替换,和新增没有区别,最终只保留指定的字段
    PUT /movie_index/_doc/3
    {
     "id":"3",
     "name":"incident red sea",
     "doubanScore":5.0,
     "actorList":[
        {"id":"1","name":"shangguigu"}
        ]
    }
7. 仅修改指定字段,其他字段保留原样
    POST movie_index/_update/3
    {
     "doc": {
     "doubanScore":7.0
     }
    }

8. 删除一个 document
    DELETE movie_index/_doc/3

分布式读写原理

写流程(基于_id)

在这里插入图片描述

(1)写操作必须在主分片上面完成之后才能被复制到相关的副本分片
(2)客户端向 Node 1 发送写操作请求,此时 Node1 为协调节点(接收客户端请求的节点)。
(3)Node1 节点使用文档的_id 通过公式计算确定文档属于分片 0 。请求会被转发到Node 3,因为分片 0 的主分片目前被分配在Node3上
(4)Node 3 在主分片上面执行请求。如果成功了,它将请求并行转发到 Node 1 和Node 2 的副本分片上。一旦所有的副本分片都报告成功,      Node 3 将向协调节点报告成功,协调节点向客户端报告成功。
(5)那么如果 shard 的数量变化,是不是数据就要重新 rehash 呢?
		不会,因为一个 index 的 shards 数量是不能改变的。
补充:redis会存在rehash吗?
	 redis使用槽来进行hash,不根据主机个数来进行分区。

读流程 (基于_id)

在这里插入图片描述

(1)读操作可以从主分片或者从其它任意副本分片检索文档 
(2)客户端向 Node 1 发送读请求,Node1 为协调节点 
(3)节点使用文档的 _id 来确定文档属于分片 0 。分片 0 的主副分片存在于所有的 三个节点上。协调节点在每次请求的时候都会通过轮询      的方式将请求打到不同的节点上来达 到负载均衡,假设本次它将请求转发到 Node 2 。 
(4)Node 2 将文档返回给 Node 1 ,Node1 然后将文档返回给客户端。

搜索流程(_search)

在这里插入图片描述

(1)搜索被执行成一个两阶段过程,我们称之为 Query Then Fetch 
(2)在初始查询阶段时,查询会广播到索引中每一个分片(主分片或者副本分片)。 每 个分片在本地执行搜索并构建一个匹配文档的大小为      from + size 的优先队列。 PS:在搜索的时候是会查询 Filesystem Cache 的,但是有部分数据还在 Memory Buffer, 所以搜索是      近实时的。
(3)每个分片返回各自优先队列中 所有文档的ID和排序值 给协调节点,它合并这 些值到自己的优先队列中来产生一个全局排序后的结果表。 
(4)接下来就是取回阶段,协调节点辨别出哪些文档需要被取回并向相关的分片提交 多个 GET 请求。每个分片加载并丰富文档,接着返回文      档给协调节点。一旦所有的文档都 被取回了,协调节点返回结果给客户端。

文档的修改和并发控制

ElasticSearch 中的全部文档数据都是不可变的,数据不能修改,只能通过版本号的方式 不断增加。这样做的主要目的是解决更新过程中的并发冲突问题

在这里插入图片描述

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

 2)乐观并发控制 
 Elasticsearch 中使用的这种方法假定冲突是不可能发生的,并且不会阻塞正在尝试的操 作。 然而,如果源数据在读写当中被修改,更新将会失败。应用程序接下来将决定该如何 解决冲突。 例如,可以重试更新、使用新的数据、或者将相关情况报告给用户。例如上图中数据库中不仅存储了100这个数据,同时存储了它的版本号0,如果一个线程去操作这个数据,另一个线程也去操作这个数据,这两个线程取到数据100和版本号0,当线程一比较快操作完,准备写入数据库中时候,先和数据库中的版本号进行比较,如果数据库中的版本号还是0,那么写入成功。线程二比较慢,操作完成后,比较发现数据库版本号变为了1,那么失败。

删除方式

如果进行删除文档操作,也不会直接物理删除,而是通过给文档打删除标记,进行逻辑 删除,至到该索引触发段合并时,才物理删除,释放存储空间。

shard数量规划

1. shard太多带来的危害
    每个分片都有 Lucene 索引,这些索引都会消耗 cpu 和内存。同样的数据,分片越多,额外消耗的 cpu 和内存就越多,会出现“1+1”>2     的情况。shard 的目的是为了负载均衡让每个节点的硬件充分发挥,但是如果分片多,在单个节点上的多个 shard 同时接受请求,并对本     节点的资源形成了竞争,实际上反而造成了内耗。
2. 如何规划shard的数量 
	a. 根据每日数据量规划shard数量。单日数据低于10g,一个分片。超过10g,单一分片不要超过30g.
	b. 根据堆内存规划shard数量。

shard优化

1. 及时归档冷数据
   一些不常用了的数据,不是热点数据,将数据取出去存储到存储代价较低的地方(HDFS),可以只存储归档数据的统计结果(一些会使用的    聚合结果),明细数据会取走。
2. 降低单个分片占用的资源消耗,具体方法就是:合并分片中的多个segment(段)  
   下图为数据的物理提交流程:
   a. 其中translog是记录操作的文件,当数据再内存中,但是es崩了,那么可以使用translog来进行数据回复
   b. 一个段中存储的数据量取决于refresh的数据量
   c. 段越多,索引越多,维护起来占用的资源越大。
   d. 在生产环境中,使用手动优化,找准时机进行优化,放置对其他操作造成影响。
降低单个分片占用的资源消耗,具体方法就是:合并分片中的多个segment(段)  
   下图为数据的物理提交流程:
   a. 其中translog是记录操作的文件,当数据再内存中,但是es崩了,那么可以使用translog来进行数据回复
   b. 一个段中存储的数据量取决于refresh的数据量
   c. 段越多,索引越多,维护起来占用的资源越大。
   d. 在生产环境中,使用手动优化,找准时机进行优化,放置对其他操作造成影响。

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值