<返回更多

花几分钟看一下Elasticsearch原理解析与性能调优

2020-11-09    
加入收藏

基本概念

定义

用途

VS传统数据库

专有名词

PUT /megacorp/employee/1
{
    "first_name" : "John",
    "last_name" :  "Smith",
    "age" :        25,
    "about" :      "I love to go rock climbing",
    "interests": [ "sports", "music" ]
}

例如

交互

RESTful API

curl -X<VERB> '<PROTOCOL>://<HOST>:<PORT>/<PATH>?<QUERY_STRING>' -d '<BODY>'

VERB适当的 HTTP 方法 或 谓词 : GET、 POST、 PUT、 HEAD 或者 DELETE。PROTOCOLhttp 或者 https(如果你在 Elasticsearch 前面有一个 https 代理)HOSTElasticsearch 集群中任意节点的主机名,或者用 localhost 代表本地机器上的节点。PORT运行 Elasticsearch HTTP 服务的端口号,默认是 9200 。PATHAPI 的终端路径(例如 _count 将返回集群中文档数量)。Path 可能包含多个组件,例如:_cluster/stats 和 _nodes/stats/jvm 。QUERY_STRING任意可选的查询字符串参数 (例如 ?pretty 将格式化地输出 JSON 返回值,使其更容易阅读)BODY一个 JSON 格式的请求体 (如果请求需要的话)

例子

request:

curl -XGET 'http://localhost:9200/_count?pretty' -d '
{
    "query": {
        "match_all": {}
    }
}
'

response:

{
    "count" : 0,
    "_shards" : {
        "total" : 5,
        "successful" : 5,
        "failed" : 0
    }
}

检索文档功能

分布式特性

ES自动执行的分布式动作

水平扩展VS垂直扩展

ES对水平扩展是友好的,通过购置更多的机器,可以更好的使用ES的分布式功能

集群

集群拥有一个或多个节点,当有节点加入或者退出集群时,集群会重新平均分配所有数据的分布

主节点功能

索引分片的元数据在每个ES节点都有存储,每个节点在接到请求后,都知道到哪台ES node找到数据,通过转发请求到ES node所在的机器

一个分片的最大文档数:(2^31-128)

一个索引的主分片数在建立时被确定,且无法修改:因为文档的存储是用shard = hash(routing) % number_of_primary_shards来确定文档的位置的。routing默认是id,也可以自定义

分片的副本数可以随时修改

建立索引

PUT /blogs
{
   "settings" : {
      "number_of_shards" : 3,
      "number_of_replicas" : 1
   }
}
花几分钟看一下Elasticsearch原理解析与性能调优

 

故障转移

增加一台机器到集群

花几分钟看一下Elasticsearch原理解析与性能调优

 

删除节点

花几分钟看一下Elasticsearch原理解析与性能调优

 

分布式写入冲突

花几分钟看一下Elasticsearch原理解析与性能调优

 


对于多个client的写入ES,有可能造成写入冲突,导致数据的丢失

在一些场景下,数据丢失是可以接受的

但是在某些场景下,是不允许的。

悲观控制并发

传统数据库的控制方式。通过对记录加锁,来实现并发的串行执行

乐观并发控制

ES采用乐观控制

所谓乐观控制,就是服务器假设大部分情况下,是不会发生冲突的,如果发生冲突,则拒绝修改,客户端可以需要通过重新获取并重试进行处理。

过程如下图

花几分钟看一下Elasticsearch原理解析与性能调优

 

分布式文档存储

确定文档位于那个shard

shard = hash(routing) % number_of_primary_shards

API支持带routing参数,来自定义路由,来确保相关文档路由到同一个分片

以ID新建,写入和删除文档

花几分钟看一下Elasticsearch原理解析与性能调优

 

一致性保证

如果暂时没有足够的分片活跃,ES会等待,默认等待1分钟,可以通过参数timeout改变这个值,如果超时,则失败返回

新索引默认有 1 个副本分片,这意味着为满足 规定数量 应该 需要两个活动的分片副本。 但是,这些默认的设置会阻止我们在单一节点上做任何事情。为了避免这个问题,要求只有当 number_of_replicas 大于1的时候,规定数量才会执行。

以ID检索文档

与上图类似

以ID更新文档

与上图类似,但在更新完文档后,会重建索引

在局部更新文档的时候,主分片会以整份文档来同步给副本,来保证数据的完整性

通过条件获取多个文档

花几分钟看一下Elasticsearch原理解析与性能调优

 

搜索

返回特殊字段

GET /_search
{
   "hits" : {
      "total" :       14,
      "hits" : [
        {
          "_index":   "us",
          "_type":    "tweet",
          "_id":      "7",
          "_score":   1,
          "_source": {
             "date":    "2014-09-17",
             "name":    "John Smith",
             "tweet":   "The Query DSL is really powerful and flexible",
             "user_id": 2
          }
       },
        ... 9 RESULTS REMOVED ...
      ],
      "max_score" :   1
   },
   "took" :           4,
   "_shards" : {
      "failed" :      0,
      "successful" :  10,
      "total" :       10
   },
   "timed_out" :      false
}

分页

GET /_search?size=5&from=5

此方式只适用于浅分页,如果查询过深,会导致严重的性能问题。

因为例如查询size为5,from=10000。那么ES会从各分片中都查询10005条记录,如果有100个shard,那么就会有100*10005条记录,ES再对这100*10005排序,并仅返回5条记录

深分页

使用游标scroll

它在ES中建立了一个有有效期的快照,提供给scroll进行数据的深度查询

倒排索引

对一下文档进行倒排:

  1. The quick brown fox jumped over the lazy dog
  2. Quick brown foxes leap over lazy dogs in summer

得到:

Term      Doc_1  Doc_2
-------------------------
Quick   |       |  X
The     |   X   |
brown   |   X   |  X
dog     |   X   |
dogs    |       |  X
fox     |   X   |
foxes   |       |  X
in      |       |  X
jumped  |   X   |
lazy    |   X   |  X
leap    |       |  X
over    |   X   |  X
quick   |   X   |
summer  |       |  X
the     |   X   |
------------------------

倒排面临的挑战

理解相关性

相关性的分数是一个模糊的概念。没有精确值,没有唯一正确的答案。是一种根据各种规则对文档进行的一种量化的估计。

它评分的准则如下:

相关性破坏

在使用全文检索某个关键字的时候,会出现,相关度低的文档的得分高于相关度高的文档的得分。

例如检索词milk。索引内有两个主分片,milk在P1出现了5次,在P2出现了6次。由于P1和P2的词分布不一样。

P1的词量比P2的词量高,那么milk算在P1出现占比小,导致在P1得相关性得分高,而在P2,占比da,导致在P2的相关性得分低。

原因

是因为局部数据分布不均匀导致的

解决方法

查询过滤bitset

每次使用检索词查询,都会为检索词建立一个bitset,bitset包含了匹配的文档的序号。在热搜索的检索词,ES会对这些bitset有针对的进行缓存,而不用在再次查询的时候,重新查找倒排索引。

对于多个查询可以有下图

花几分钟看一下Elasticsearch原理解析与性能调优

 

当倒排索引重建的时候,bitset在缓存会自动失效

缓存的策略

索引管理

创建索引

可以显式创建,也可以隐式创建。

在大集群下,索引的创建,涉及元数据的同步,有可能导致集群负载的大量增加。此时需要禁用索引的隐式创建

action.auto_create_index: false

删除索引

删除索引,会涉及大量数据的删除,如果用户意外地试图通过一条命令,把所有索引删掉,这可能导致可怕的后果

通过禁用此操作,可以设置如下

action.destructive_requires_name: true

分析器

每个索引都可以设置自己的分析器,分析器的用途主要是在全文索引上面,通过对不同的语言,使用不同的分词,不同的词转换来构造倒排索引和计算相关性。

分片

倒排索引的不变性

好处

不好

如何保证新数据能实时能查询到

用更多的索引。

对于新的文档,不马上重建索引,而是通过新增额外的索引。在查询数据时,通过轮询所有的索引,并合并结果返回。

花几分钟看一下Elasticsearch原理解析与性能调优

 

ES并不是严格意义上的实时,准确来说是准实时,由于data从插入到建立倒排索引这段时间,新数据是不能访问的

聚合

像数据库的group by。只是语法不一样。功能相通

应用层性能调优

调大 refresh interval

默认刷新时间是1s,每次刷新都会有一次磁盘写入,并创建一个新的段。通过设置更大的刷新时间,可以让磁盘写入的次数更低,写入的段更大。减少段合并的次数。

禁止OS把ES置换出去

OS的内核会在内存紧张的时候,把进程置换到外村。而对于性能跟内存强相关的ES来说,置换到外存是致命的。通过设置进程在内核的参数,禁止置换,可以避免OS的这种动作

预留大量的文件系统缓存给ES

由于ES大部分数据的不变性,使得ES的大部分磁盘操作,都可以通过文件系统的缓存来加快速度。一旦ES的倒排索引和数据缓存到系统,如果没有其他进程的干扰,而且是比较频繁访问的数据,则会一直驻留在系统缓存,使得ES的大部分操作都是走内存的。一般来说,分配一半的内存给文件系统,是合适的。

使用自动生成ID

如果指定ID,ES会在集群内检查是否ID已经存在,这对大集群来说,是昂贵的。如果ID是自动生成的,ES会跳过检查,直接插入文档

更好的硬件

不要使用join关联查询

ES不适合做关联查询,会导致严重的性能问题。

如果业务一定要join,可以把关联的数据都写到一个索引内,或者通过应用程序来做关联的动作。

强制merge只读索引

merge成一个单一的段,会得到更好的性能

增加副本

有更多的机器,通过提高副本数,可以提高读效率

不要返回大数据

ES不适合这场景

避免稀疏

不要把不相关的信息存入同一个索引

数据预热

对于热点数据,可以通过一个客户端请求ES,让数据先占据filesystem cache。

冷热数据分离

冷热数据部署在不同的机器,可以让热数据在缓存内不会被冷数据冲走

内核层性能调优

限流

如果ES出现高负载的请求,ES的协调节点会累积大量的请求在内存在等待处理,随着请求数的增加,协调节点的内存占用会越来越大,最后导致OOM。

通过限流,可以有效缓解。

大查询

如果客户端发来了一个复杂的查询,使得需要返回的数据异常的大,这也会导致OOM问题。

通过修改内核,让如果请求的内存占用超过系统可以承受的范围,则截断来解决

FST过大引发OOM

FST是对倒排索引在内存的索引,它通过前缀状态机的方法,快速的定位检索词在倒排索引的磁盘位置,达到减少磁盘访问次数而加快检索速度的目的。

但由于FST是常驻内存的,如果倒排索引达到一定规模时,FST必然会引起OOM问题。而且FST是存放在JVM堆内内存的。堆内内存的上限时32G。

而10 TB的数据就需要10G到15G的内存来存放FST。

作者:谭英智

来源:https://www.cnblogs.com/kukafeiso/p/13947142.html

声明:本站部分内容来自互联网,如有版权侵犯或其他问题请与我们联系,我们将立即删除或处理。
▍相关推荐
更多资讯 >>>