社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Elasticsearch

Elasticsearch权威指南学习笔记

kinnylee • 5 年前 • 391 次点击  
阅读 75

Elasticsearch权威指南学习笔记

前言

  • 为什么es查询和聚合都这么快?底层是如何实现的?
  • 数据在es集群中如何存储的?如何做到自动分布式的?
  • 为什么es的主分片数设置了之后就不能调整,而副本分片数可以调整?
  • 如何优化索引方式和查询方式,有效利用缓存,提高查询效率?
  • 如果保证不停服的情况下,平滑升级或扩容?
  • 如何优化查询效率?

相信看完Elasticsearch权威指南这本书,所有疑问都将得到解答

一. 基本概念

1. 分片

  • 最小级别的工作单元,保存索引中一部分数据。是一个Lucene实例,本身就是一个完整的搜索引擎。但是应用程序不会直接与分片通讯。
  • 可以想象成容器,节点间数据迁移以分片为单位
  • 分为主分片和副分片(主分片的副本)
  • 索引创建的时候,主分片的数量就固定了,但是副本分片数量可调整
  • 默认一个索引分配5个主分片
  • 主分片所在节点挂掉后,重新选举主节点,并将副分片升级为主分片
  • 故障节点重新启动后,会同步故障期间未同步到到数据

2. 文档

  • 根对象序列化成到json对象
  • 每次对文档的操作(包括修改,删除),_version都会加一
  • 文档是不可修改的。update是先删除,再新建一个新的
  • 删除的文档并不会被立即移除,只是标记为删除。之后后台再清理
  • 自己设置文档的版本:添加version_type=external参数

3. 冲突解决

  • 通过版本号实现乐观锁解决冲突问题

4. 文档元数据

  • _index 文档存储的地方
  • _type 文档代表的对象的类
  • _id 文档的唯一标识。可手动设置也可自动生成(22位长)

5. 集群架构图

两个节点,三个主分片,一个副分片的效果图

扩展到三个节点到效果图

6. 集群状态

集群状态是一个数据结构,集群状态存在每个客户端中。保存以下信息

  • 级别设置
  • 集群节点
  • 索引以及相关的映射,别名等信息
  • 索引的分片,以及分配的节点

集群状态-status

  • green:所有主分片和副分片都以及分配
  • yellow:所有主分片都已分配,至少有一个副本分配没有分配
  • red:至少一个主分片(或全部副分片)缺失

二. 集群工作原理

1. 数据是如何在分布式系统存储的

  • 文档通过路由存放到分片
  • 通过以下算法得出该文档存储时到分片编号
    shard = hash(routing) % number_of_primary_shards
    复制代码
  • routing是任意字符串,默认是_id
  • 主分片到数量不可改变,否则之前的路由失效,文档就找不到了
  • 自定义路由可以保证有关联性的文档被保存在同一个分片

2. 主分片和复制分片如何交互?

  • 我们能够发送请求给任意节点
  • 每个节点都有能力处理任意请求
  • 每个节点都知道任意文档所在节点,并转发请求
  • 发送请求时最好循环每个节点以负载均衡

2.1 write操作(新建、删除、索引)

顺序步骤

  • 客户端发送请求(新建,删除,索引)到node1节点
  • 节点使用hash算法得出分片编号0.因为分片0在节点3,将请求转发到节点3
  • node3成功保存数据到主分片,如果成功,转发请求到node1和node2到副节点
  • 所有复制节点成功,发送成功回复到请求节点1,节点1再返回给客户端
可调到参数
  • replication:默认为sync,主分片得到复制分片成功响应才返回。async表示请求在主分片执行成功就返回,依旧转发请求到副分片,不过不知道成功与否
  • consistency:主分片尝试写入时,需要规定数量(quorum)或过半的分片可用。可为one,all,quorum(默认)。quorum只有在number_of_replicas大于1时才生效
    int((primary[总是1] + number_of_replicas) /2 + 1)
    复制代码
  • timeout:分片不足时,等待时间。默认1min

2.2 read操作

  • 客户端发送get请求到node1
  • 节点使用hash算法,得到文档所属到主分片为0分片
  • 找到分片0的副分片所在节点为node1,node2,node3
  • 通过某种策略选定某个副分片节点,比如node2
  • node2返回文档给node1
  • 然后node1返回给客户端

2.3 update操作

顺序步骤

  • 客户端给node1发送更新请求
  • 通过哈希算法得到主分片位置,转发请求到node3
  • node3检索出文档,修改_source字段到json文档,然后重建索引。如果有其他进程修改了文档,它以retry_on_conflict设置到次数重复这一步,都未成功则放弃
  • node3更新成功则发送整个新文档(并不是修改请求)到node1和node2的复制节点重建索引,都成功则返回给node1,再返回给客户端

2.4 多文档模式

mget 多文档read

  • 客户端发送mget请求给node1
  • node1为每个分片构建一个请求,并转发到对于分片所在节点
  • 当所有回复被接收,node1组合这些响应,返回给客户端
bulk 多文档write

  • 客户端向node1发送请求
  • node1为每个分片构建批量请求,然后转发到这些主分片上
  • 主分片按序执行,每一个完成时,发送到副分片上
  • 所有操作都完成后节点整理响应返回给客户端

3. 索引是如何建立的

3.1 基本概念

  • 映射(mapping):用于字段确认,每个字段匹配为确认的数据类型
  • 分析(analysis):全文文本分词,以建立反向索引
  • 倒排索引:由文档中单词的唯一列表和单词在文档中的位置组成,用于快速检索结果而设计

3.2 分析(analysis)

分析的过程
  • 分析由分析器(analyzer)完成
  • 分析过程先标记一段文本为单独的词(item)
  • 然后标准化(比如全部转为小写)item,以提高搜索性
  • 分析的详情可通过_analyze API查看
分析器包括的组件

es提供很多可用直接使用的组件,可自定义组合使用

  • 字符过滤器(character filter):字符串先经过这做一些过滤操作
  • 分词器(tokenizer):将文本切分为单词,比如空格,逗号等。中文可用专门的分词器
  • 标记过滤器(token filter):修改词语,比如转小写,去掉语气词,增加同义词
内置的分析器
  • 标准分析器:默认使用这个。标准切分,去掉大部分符号,最后转为小写
  • 空格分析器:按空格切分,不转换为小写
  • 语言分析器:根据特定语言的特性做分析
查询方式
  • 字段查询:精确匹配,查询前不会将被查询的字符串分析
  • 全文查询:查询前会先用分析器分析要查询的字符串
手动指定分析器

当往es中加入字符串时,es会自动用标准分析器做分词,但是可能某些字符就是普通的id,标签等字段,不需要做分析,可手动指定映射

创建索引时查找分析器的顺序
  • mapping文件中指定字段的analyzer
  • 文档本身的_analyzer字段
  • mapping文件中指定类型的默认analyzer
  • mapping文件中全局默认的analyzer
  • 节点级别默认的analyzer
  • 标准analyzer
查找索引时查找分析器的顺序
  • 查询参数中的analyzer
  • mapping文件中指定字段的analyzer
  • mapping文件中指定类型的analyzer
  • mapping文件中全局默认的analyzer
  • 节点级别默认的analyzer
  • standard analyzer

3.3 映射

作用

定义字段类型,字段的数据类型以及被es处理的方式。

支持的字段类型
类型 表示的数据类型
String string
Whole Number byte short integer long
Floating point float double
Boolean boolean
Date date

新的字段如果没有配置映射,es会自动猜测字段类型

自定义字段映射可实现的功能
  • 区分全文字符串(需要分词)和精确字符串(不需要分词)
  • 使用特定语言的分析器
  • 优化部分匹配字段
  • 指定自定义日期格式
映射包含的参数
  • properties:列出了可能包含的每个字段的映射
  • 元数据字段:_type, _id, _source
  • dynamic:确定字段添加时的策略(_source会一直保存)
    • ture 自动添加
    • false 忽略字段
    • strict 抛出异常
  • 设置项:如analyzr
  • 其他设置
自定义字段映射注意点
  • 要映射的字段参数为type,除了string外,很少需要映射其他type
  • string字段的index字段,控制字符串以什么方式被索引。
    含义
    analyzed 分词索引
    not_analyzed 不分词索引
    no 不索引
  • string字段选择anlyzed为index时,analyzer指定分析器。如:simple, english, whitespace
  • 更新映射只能添加字段,不能修改已经被添加的字段。否则会导致出错索引不到
文档字段的属性
  • type
  • index
  • analyzer
  • ip
  • geo_point
  • geo_shape
元数据_source字段
  • 作用: 用于保存原始json字段
  • 为什么需要
    • 搜索结果能得到完整文档
    • 缺少它,部分更新请求不起作用
    • 更新映射文件时,可直接取内容
    • 更易排查错误
  • 怎么禁用:enabled:false
  • 使用:搜索时可以通过_source指定只返回哪些列
元数据_all字段

查询不知道指定哪个字段时,使用_all。也可禁用。使用_all时,会将其他所有字段的值作为一个大的字符串进行索引

动态模版

dynamic_templates 设置通过字段名或类型动态匹配不同的映射

  • match_mapping_type 模版使用的数据类型
  • match 模版使用的字段名
  • path 模版使用的字段全路径(嵌套json)

三. 结构化查询语言

1. 过滤

概述

文档的字段是否包含特定值,比查询更快,结果可缓存

原则上全文索引或者需要其他相关性评分的使用查询语句,其他情况都用过滤。

重要的过滤语句

  • term:精确匹配
  • terms:多个条件的精确匹配
  • range:范围过滤
  • exists:是否包含指定字段
  • missing:没有某个字段
  • bool:合并多个过滤查询结果
    • must:and
    • must_not:not
    • shoud:or

2. 查询

简述

每个文档的字段与特定字段的匹配程度如何,比过滤慢,结果不可缓存

重要的查询语句

  • math_all:查询所有文档
  • match:标准查询,全文和精确都支持

    match指定多个值时,内部分词后会执行多个match并放入bool查询。默认为or。可通过operator参数改为“and”

  • multi_match:同时搜索多个字段,支持通配符
  • bool:同bool过滤,多的是要计算_score

过滤顺序

  • 过滤顺序对性能有很大影响
  • 更详细的过滤条件应该放在最前,以便排除更多的文档
  • 被缓存的过滤应该放到不会缓存的过滤前面(缓存参考后面章节)

相关性排序

排序方式

  • _score:默认排序方式,默认倒序
  • 字段排序:_score不需要计算,默认正序
  • 多级排序:可指定多个字段。先用第一个字段排序,第一个相同时排第二个
  • 字符串参数排序:

被分析的字段进行强制排序会消耗大量内存

相关性简介

相似度算法:TF/IDF(检索词词频/反向文档频率)
  • TF: 词频,出现在当前文档次数越多,相关性越大
  • IDF:反转文档频率,所有文档数与出现这个词的文件数百分比,词出现频率越大,IDF越小
  • 由于性能问题,每个分片只会计算该分片内的IDF,而不是所有文档
  • boost参数可以设置权重

3. 分布式搜索的执行方式

概述

搜索包括查询多个分片,并将多个分片元信息合并,然后再根据元数据获取真正数据两个步骤。

查询多个索引和查询一个索引完全一致,无非是多差了几个索引。扩展的时候,可以不用将旧数据迁移到新索引,直接新建索引,然后查询两个索引,或者别名索引即可

查询(query)

  • 客户端发送search给node3,创建一个from+size的空优先级队列

  • 广播请求到每个分片,每个分片在本地执行查询,并放到一个大小为from+size的本地优先级队列里

  • 每个节点返回查询结果(id和_score)给node3,node3将结果全局排序

    • 多个请求会轮询所有的分片副本以负载均衡,提高系统吞吐率
    • 多索引的工作机制和单索引类似,只不过多了些分片
    • 深度分页会导致排序过程非常繁重,占用巨大cpu和宽带

取回(fetch)

  • 协调节点辨别出哪些文档需要取回,并向相应分片发送请求
  • 每个分片加载文档,并做相关处理(比如高亮),然后返回给协调节点
  • 协调节点将数据返回给客户端

搜索选项(可选参数)

  • preference:控制使用哪个分片或节点处理请求
  • timeout:协调节点等待多久就放弃其他节点的结果
  • routing:限制只搜索哪些分片,对于大规模系统很有用
  • search_type:query_then_fetch为默认的搜索类型
    • count:当不需要结果,只需要数量时
    • query_and_fetch:查询并且取回
    • dfs_query_and_fetch,dfs_query_then_fetch
    • scan:扫描,和scroll一起使用。可高效取回大量数据。禁用排序实现

扫描和滚屏

scroll

类似传统数据库的游标,搜索的是查询时的索引快照,查询结束之前的修改不会感知到

scan

不排序,只要有结果就返回

四. 分片内部原理

1. 索引动态更新原理

1.1 倒排索引-保证文档可被搜索

1.2 倒排索引的内容是不可变的

1.3 不可变的同时动态添加段

查询的时候,所有段依次查询,然后聚合结果,通过这种方式,新文档以最小代价加入文档

  • 新的文档首先写入内存区的索引缓存
  • buffer中包括新的段包含的倒排索引,段名等
  • buffer被提交
  • 新段被打开,文档可被索引
  • 内存缓存被清除,等待新文档

1.4 删除和更新

因为段不可变,更新和删除操作并不是真的删除,是通过新增.del文件和新建段文件,查询返回前将标记为del的文件从结果中删除

1.5 近实时搜索

因为从buffer刷入磁盘代价很大。es允许一旦一个文件被缓存,就可以设置段打开,文件可以被搜索到

1.6 刷新

每个分片默认每秒打开一个新段,所以新的改动需要1s后才能看到。可以设置refresh_interval减少刷新的频率

1.7 持久化变更

添加缓冲buffer的同时,通过添加事务日志(默认512M),保证数据被完整持久化。每次flush(每30分钟,或事务日志过大)到磁盘时,段被全部提交,清空事务日志

1.8 合并段

通过每秒自动刷新段,不用多久段数据就剧增。每个段消耗计算机资源,且每次查询都要依次检查每个段,段越多查询越慢。es后台合并段解决该问题。 合并大的段会消耗io和cpu资源。

1.9 Optimize API

强制合并段。对于数据不再变动的索引很有效,对数据还在动态增长的索引不要使用。

2. 缓存

概述

  • 缓存针对过滤查询
  • 核心是一个字节集保存哪些文档符合过滤条件
  • 缓存的字节集是增量更新的
  • 每个过滤器都是独立缓存的,且可复用
  • 大部分枝叶过滤器(如term)会被缓存,而组合过滤器(如bool)不会被缓存

不可被缓存的情况

  • 脚本过滤器,脚本对es是不透明的
  • Geo(地址)过滤器,不太会被重用
  • 日期范围精确到毫秒不会被缓存,整数会被缓存

过滤时间范围的使用建议

  • 对于时间精确到毫秒的查询,可拆分为日期+日期时间两个过滤条件,前者会被缓存,且顺序不要改变

五. 全文检索

1. 全文检索包括两个方面

  • 相关度(Relevance):TF/IDF,地理位置相近度,模糊相似度或其他算法
  • 分析(Analysis):分词,创建倒排索引

2. 全文查询分类

  • 低级查询:term查询。没有分析阶段,会精确匹配特定短语
  • 全文检索:match,query_string等查询。有分析阶段。
    • date,integer类型:精确查询
    • not_analyzed的string类型:分析查询词语(比如转小写),执行单个短语查询
    • analyzed的string类型:先解析查询语句,生成短语列表。查询后再合并查询结果

六. 聚合

1. 基本概念

桶(buckets)

满足特定条件的文档的集合。类似于sql里面的group by

指标(metrics)

对桶内的文档进行统计计算。类似sql里面的count,sum,max等统计方法

2. 近似聚合

2.1 概述

  • 分布式算法三个因子模型同时只能选择满足两项:精确,实时,大数据
  • ea选择大数据和实时。会提供准确但不是100%精确的结果,以牺牲一点小的估算错误作为代价,换来告诉的执行效率和极小的内存消耗
  • 两个近似算法:cardinality, percentiles

2.2 cardinality 基数度量

  • 类似sql的distinct
  • 是一个近似算法。基于HyperLogLot++(HLL)算法的。HLL先对输入做哈希运算,根据hash运算的记过中的bits做概率估算得到基数。HLL 论文
  • 算法特性
    • 可配置精度:参数为precision_threshold (精度更高=跟多内存)
    • precision_threshold范围为0-4000,数据结构使用内存为:precision_threshold * 8
    • 设置为100时,可保证百万级别的数据量误差维持5%以内
    • 小的数据集精度非常高
    • 可配置使用的固定内存量
  • 优化:预先计算hash值,不过性能的瓶颈由聚合时转移到索引时(必须重新建索引,添加hash字段),需要根据业务场景来确定。

2.3 percentiles 百分位数度量

  • 展现了以某个具体百分比执行观察到的数值,通常用于找出异常。
  • 也是一个近似算法。使用TDigest算法
  • 算法特性
    • 极端百分比的情况下,数据更准确。比如1%或99%。这由数据结构决定。
    • 小数据集精度非常准确

3. significant_terms

  • sigterms和其他聚合不同,用于发现数据集中医学异常指标
  • 通过统计数据并对比正常数据找到可能有异常频次的指标

4. 聚合的数据结构

4.1 Doc Values

  • 聚合使用Doc Values的数据结构
  • 将文档映射到他们包含的词项
  • 在索引时和倒排索引同时生成。基于segment且不可变。
  • Doc values数据存放到磁盘中,不是由jvm管理。
  • 采用列式存储,数据整齐排布,便于压缩
  • 除了analyzed的字符串,默认所有字段都开启doc values。如果你永远不会对某些字段进行聚合,排序操作,可以禁用doc values。可以节省磁盘空间和索引速度

4.2 fielddata

  • anaylzed的字符串,使用fielddata这种数据结构支持聚合,fielddata存储在内存堆中,旧版本没有doc values时是用的fielddata
  • anaylzed的过程hi消耗极大内存,且生成大量token,对聚合很不友好
  • fieldata会一直存在内存中,直到被驱逐或节点崩溃。注意观察它的大小。
  • dielddata不会在建索引时存在,是查询时建立的
  • indices.fielddata.cache.size:百分比或实际大小。 控制为 fielddata 分配的堆空间大小。结果中 fielddata 大小超过了指定 大小 ,其他的值将会被回收从而获得空间。
  • 如果没有足够空间可以将 fielddata 保留在内存中,Elasticsearch 就会时刻从磁盘重载数据,并回收其他数据以获得更多空间。内存的回收机制会导致重度磁盘I/O,并且在内存中生成很多垃圾,这些垃圾必须在晚些时候被回收掉。
  • 监控filddata: GET /_stats/fielddata?fields=*

5. 聚合优化

  • 针对大量数据的嵌套聚合查询,效率极低。默认的查询方式为深度优先。
  • 可以使用广度优先处理聚合数量远远小于总组数的情况。参数为collect_mode: breadth_first

七. 地理位置

1. 设置字段类型为地理位置

地理坐标点不能被动态映射字段检测,需要显式申明对应字段类型(type参数)为geo_point

2. geo_point格式

  • 字符串: "40.715, -74.011", 维度在前,精度在后
  • 数组: [40.715, -74.011], 维度在前,精度在后
  • 对象: {"lat": 40.715, "lon": -74.011}

3. 过滤方式

  • geo_bounding_box :: 落在指定矩形框中的坐标点
  • geo_distance :: 给定距离内的点
  • geo_distance_range :: 距离范围内的点
  • geo_polygon :: 落在多边形中的点

4. 使用注意

  • 地理坐标过滤器使用代价很高,它会将所有文档的地理位置信息载入内存,然后计算。使用时谨慎,或放到过滤的最后
  • bool过滤器默认会将地理信息过滤排到最后
  • 默认是不被缓存的
  • 每个经纬度组合需要16自己的内存,可设置压缩格式,减少精度,减少内存
  • 合理设置精度:geohash_prefix和geohash_precision两个参数。再结合geohash过滤器可高效查询

5. geohash

  • 把世界分为4*8=32个单元的各自,每一个格子用一个字母或数字标识。这些单元有被继续分解成32个更小的单元,不断重复
  • 长度越长,精度越高
  • 有同一前缀的geohash,位置靠的近,共同前缀越长,距离越近
  • 刚好相邻的位置也有可能geohash完全不同

6. 地理位置聚合

  • geo_distance 距离聚合:将文档以指定中心店为圆心的圆环分组
  • geohash_grid网格聚合:将文档按geohash单元分组,以便在地图上呈现
  • geo_bounds: 边界聚合:包含坐标点的矩形框

7. 地理形状(geo_shape)

  • 地理形状是通过一个个geohash单元画出来的

八. 数据建模

1. 关联关系

关联关系的处理,使用扁平化的存储,将数据冗余到同一个索引,提高查询效率

2. 嵌套对象

设计

内部存储

普通对json含有数组时,内部存储会被扁平化,导致逻辑关系丢失。需改为nested关系,而不是默认的object。嵌套对象内部会被索引为分离的隐藏文档

查询

使用特殊的nested查询或nested过滤

排序

3. 父子关系

原理

  • 和nested差不多,区别是nested是存储在同一个文档中,而父子关系是完全不同的文档
  • 父子文档需存储在同一个分片中
  • 父子关系映射存储在doc-values的数据结构中,完全存在内存
  • 适合父文档少,子文档多的情况

优势

  • 更新父文档时,不用更新子文档索引
  • 创建删除修改子文档时,不影响父文档和其他文档

劣势

  • 查询速度比嵌套类型慢5-10倍
  • 不适合父文档多的情况

设计父子关系

  • 指定某一文档type为另一文档type的parent
  • 创建父文档时,和普通文档没区别
  • 创建子文档时,必须通过parent指定父文档id。作用是创建关联关系并保证分配到同一个分片(使用父文档id做hash计算)
  • 尽量少使用父子关系,仅父文档比较少的shi h

4. 扩容设计

扩容思路

  • 首先查看是否有低效率的查询可以优化
  • 是否缺少足够的内存
  • 是否开启了swap
  • 已经建立好的索引,不可修改分片数,可通过重新索引,将旧数据迁移到新索引中
  • 搜索性能取决于最慢节点的响应时间,合理设置分片使之负载均衡
  • 因为单索引和多索引没有区别,可通过设置多索引以扩容

分片数量设置

  • 基于现有的数据量和定期的增长量,预估数据总量
  • 基于现有的硬件信息,设置单个分片,0个副本,找到单个分片在当前硬件条件下能支持的最大文档数
  • 用总数量/单个分片的最大数,大致可估算出分片数

基于时间的数据流场景优化

  • 按时间切分索引
  • 旧数据不会被改变,使用optimize api进行段合并。
  • 大多数索引会有大概 50–150 个段,哪怕它们存有 TB 级别的数十亿条文档。段数量过大表明合并出现了问题(比如,合并速度跟不上段的创建)
  • 不过段合并消耗掉你节点上全部的I/O资源,从而有可能使集群失去响应。 如果你想要对索引执行 optimize,你需要先使用分片分配(查看 迁移旧索引)把索引移到一个安全的节点,再执行。
  • 为了不影响正常索引,段合并后台限制磁盘读写速率为20MB/s,可根据实际情况调整,比如SSD盘,参数为indices.store.throttle.max_bytes_per_sec。甚至在没有查询时,设置为none,即没有限制,合并完再改回去。
  • 并且,对还在写数据的索引进行优化(Optimize)操作将会是一个糟糕的想法, 因为优化操作将消耗节点上大量 I/O 并对现有索引造成冲击
  • 我们可以临时移除副本分片,进行优化,然后再恢复副本分片
  • 去除副本之前,可通过snapshot restore api备份数据
  • 更旧的不会被使用的数据,关闭索引。关闭后除了磁盘,不会占用其他资源。flush(清空事务日志)->close(关闭索引)
  • 数据归档:snapshot restore api将数据存储到hdfs或其他地方

基于用户的数据流场景

  • 指定路由:保证同类数据会分发到同一分片。查询时也传入路由参数,确保只查询特定的分片,多分片查询带来的性能损耗
  • 使用别名,指定特定的名字对应特定的路由值和过滤器。以达到多个名称共享一个索引的效果。看起来像多个索引一样。
  • 当某个分片数据量剧增到需要单独建索引时,使用_alias操作:指定action的remove和add参数,实现平滑迁移。

九. 管理,监控

1. 重要的参数配置

  • cluster.name
  • node.name
  • path.data
  • path.logs
  • path.plugins
  • discovery.zen.minum_master_nodes: 最小主节点数,防止脑裂(多个主节点)
  • discover.zen.ping.unicast.hosts: 集群单播列表
  • gateway.recover_after_nodes 至少多少个节点,集群才可用
  • gateway.expected_node 集群期待有多少个节点
  • gateway.recover_fater_time 等待多久才进行数据恢复
  • logger.discovery 日志级别
  • index.search.slowlog.threshold.query.warn : "10s" 查询慢与10s的输出warn日志
  • index.search.slowlog.threshold.fetch.debug: "500ms" 查询慢与500ms的输出debug日志
  • index.indexing.slowlog.threshold.index.info: "5s 查询慢与5s的输出info日志
  • index.unassigned.node_left.delayed_timeout 修改延时分片时间
  • cluster.routing.allocation.enable" : "none" 禁止分片分配

2. 不要修改的配置

  • 不要更改垃圾回收器,默认使用CMS。不要更换为新一代的G1
  • 线程数量,默认为cpu核数。IO操作是由Lucene线程完成,不是es。

3. 堆内存的配置

  • 默认为1G,实际生产环境必须修改
  • 保证Xms和Xmx一样,防止运行时改变堆内存大小,这非常消耗资源
  • 内存分片不要超过本机内存的一半。因为Lucene本身也会需要内存和缓存。
  • 如果不需要对分词做聚合运算,可降低堆内存。堆内存越小,Elasticsearch(更快的 GC)和 Lucene(更多的内存用于缓存)的性能越好。
  • 内存不要超过32G。每个对象的指针都变长了,就会使用更多的 CPU 内存带宽,也就是说你实际上失去了更多的内存。果你想保证其安全可靠,设置堆内存为 31 GB 是一个安全的选择
  • 如果内存很大,可以考虑给一个机器分屏多个es实例,但总的堆内存还是不要超过一半。同时配置cluster.routing.allocation.same_shard.host: true。防止同一个分片(主副)在一个机器上
  • 设置bootstrap.mlockall: true,锁住内存,不让发送内存swapping

4. 运维及优化

  • 日志文件默认存放在安装目录下的logs文件里,"logger.discovery" : "DEBUG"可设置日志级别
  • 可以设置输出慢查询日志
  • 如果不需要实时准确,把index.refresh_interval改到30s,做大批量倒入时,把这个值设为-1,倒入完毕后重新设置回来
  • 大批量倒入时,index.number_of_replicas设为0,关闭副本,提高效率
  • 尽量使用es自动生成的id,避免版本查找影响效率。如果使用自己的id,使用压缩性能良好的,避免使用太过随机的id
  • 延迟分片:防止节点掉线然后又重启导致的大量数据迁移问题。因为掉线的节点上的数据会因为失效而全部被删除。参数为index.unassigned.node_left.delayed_timeout

5. 滚动重启

  • 保证不停集群功能的情况下逐一对每个节点进行升级或维护
  • 先停止索引新的数据
  • 禁止分片分配。cluster.routing.allocation.enable" : "none"
  • 关闭单个节点,并执行升级维护
  • 启动节点,并等待加入集群
  • 重启分片分配。cluster.routing.allocation.enable" : "all"
  • 对其他节点重复以上步骤
  • 恢复索引更新数据

今天看啥 - 高品质阅读平台
本文地址:http://www.jintiankansha.me/t/apDdmrVtS2
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/23996
 
391 次点击