132

干货 |《深入理解Elasticsearch》读书笔记

 6 years ago
source link: http://mp.weixin.qq.com/s/nZqgWl81Iu3IrIn1Q1ZdBA
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Image

题记

由于之前已经梳理过Elasticsearch基础概念且在项目中实战过Elasticsearch的增删改查、聚类、排序等相关操作,对ES算是有了一定的认知。

但是,仍然对于一些底层的原理认知模糊,特买来《深入理解Elasticsearch》过了一遍,将书中一些细节知识点结合官网文档梳理如下。

1——4章偏应用,跟着敲一遍代码基本就能理解原理。 
5——9章偏理论一些。 

Image

第5章 分布式索引架构

1、如何选择合适的分片和副本数?

目的:规划索引及配置,适应应用的变化。

正确认知:分片数索引创建后不可以修改,副本数索引创建后可以通过API随时修改。

多副本的缺点:额外副本占据了额外的存储空间,构建索引副本的开销也随之增大。

同时要注意:如果不创建副本,当主分片发生问题时,可能会造成数据的丢失。

配置参考:最理想的分片数量应该依赖于节点的数量。

参考公式:所需的最大节点数 = 分片数 *(副本数+1) 

举例:你计划5个分片和1个副本,那么所需要的最大的节点数为:5*(1+1)=10个节点。

2、可不可以基于时间构建索引?

目的:选择感兴趣的索引上进行查询,历史索引(时间比较久)的定期删除。 
正确操作方法:通过名称为logs_2017_01, logs_2017_02,…..logs_2017_12来构建索引。

第6章 底层索引控制

1、什么是段?

Elasticsearch中的每个分片包含多个segment(段),每一个segment都是一个倒排索引;在查询的时,会把所有的segment查询结果汇总归并为最终的分片查询结果返回。

在创建索引的时候,ES会把文档信息写到内存bugffer中(为了安全,也一起写到translog),定时(可配置)把数据写到segment缓存小文件中,然后刷新查询,使刚写入的segment可查。

虽然写入的segment可查询,但是还没有持久化到磁盘上。因此,还是会存在丢失的可能性的。所以,ES会执行flush操作,把segment持久化到磁盘上并清除translog的数据(因为这个时候,数据已经写到磁盘上,不再需要了)。 

参考:http://t.cn/RjKOMv1

2、什么是段合并?

由于自动刷新流程每秒会创建一个新的段,这样会导致短时间内的段数量暴增。而段数目太多会带来较大的麻烦。

1)消耗资源:每一个段都会消耗文件句柄、内存和cpu运行周期; 
2)搜索变慢:每个搜索请求都必须轮流检查每个段;所以段越多,搜索也就越慢。

ES通过在后台进行段合并来解决这个问题。小的段被合并到大的段,然后这些大的段再被合并到更大的段。

3、段合并做了什么?

段合并的时候会将那些旧的已删除文档从文件系统中清除。 
被删除的文档(或被更新文档的旧版本)不会被拷贝到新的大段中。

启动段合并不需要你做任何事。进行索引和搜索时会自动进行。 
1)当索引的时候,刷新(refresh)操作会创建新的段并将段打开以供搜索使用。 
2) 合并进程选择一小部分大小相似的段,并且在后台将它们合并到更大的段中。这并不会中断索引和搜索。

4、为什么要进行段合并?

1)索引段的个数越多,搜索性能越低并且消耗更多的内存; 
2)索引段是不可变的,你并不能物理上从中删除信息。(可以物理上删除document,但只是做了删除标记,物理上并没有删除) 
3)当段合并时,这些被标记为删除的文档并没有被拷贝至新的索引段中,这样,减少了最终的索引段中的document数目。

5、段合并的好处是什么?

1)减少索引段的数量并提高检索速度; 
2)减少索引的容量(文档数)——段合并会移除被标记为已删除的那些文档。

6、段合并可能带来的问题?

1)磁盘IO操作的代价; 
2)速度慢的系统中,段合并会显著影响性能。

第7章 管理Elasticsearch

1、有了副本机制为什么还需要集群备份?

Elasticsearch 副本提供了高可靠性;它们让你可以容忍零星的节点丢失而不会中断服务。 
但是,副本并不提供对灾难性故障的保护。对这种情况,你需要的是对集群真正的备份——在某些东西确实出问题的时候有一个完整的拷贝。

2、集群如何备份?

使用 snapshot API备份你的集群。 
它会拿到你集群里当前的状态和数据然后保存到一个共享仓库里。这个备份过程是”智能”的。 

ES5.6集群备份官网参考: http://t.cn/RjKEH9G

3、集群备份分类?

完整备份——你的第一个快照会是一个数据的完整拷贝。 
增量备份——所有后续的快照会保留的是已存快照和新数据之间的差异。随着你不时的对数据进行快照,备份也在增量的添加和删除。这意味着后续备份会相当快速,因为它们只传输很小的数据量。

4、集群可以备份到哪里?

要使用这个功能,你必须首先创建一个保存数据的仓库。有多个仓库类型可以供你选择:

  • 共享文件系统,比如 NAS

  • Amazon S3:亚马逊Web云服务

  • HDFS (Hadoop集群分布式文件系统)

  • Azure Cloud:微软云平台

5、备份操作API?

PUT _snapshot/my_backup 

    "type": "fs", 

    "settings": {

        "location": "/mount/backups/my_backup" 

注意:共享文件系统路径必须确保集群所有节点都可以访问到。

第8章 提高性能

1、什么情况下会出现堆内存泄漏?

如果没有足够的堆内存来供你的应用在堆上创建新对象,JVM会抛出一个OutOfMemeory异常,这是一个内存出了问题的迹象,要么是没有足够的内存给它,要么是有内存泄漏,导致没有释放不再使用的对象。

2、推荐的性能测试工具?

1)JMeter 
2)ab(Apache基准测试工具)

3、ES需要优化的原因?

1)硬件问题——如机械硬盘和固态硬盘; 
2)不良的数据结构; 
3)糟糕的查询设计——如wildcard模糊匹配很长的字符串。

4、后台什么在运行导致CPU飙升?如何排查?

热点线程APi能向你提供查找问题根源所必需的信息。 

GET /_nodes/hot_threads?pretty

5、如何扩展集群?

1)垂直扩展 
向Elasticsearch集群添加更多的资源。 
制约因素——如:JVM最大支持31GB物理内存。

2)水平扩展 
索引多分片、多副本,集群中分散处理之。

优点:降低运行集群的成本。 
版本升级后(如5.X升级到6.0),确保服务仍然可用。

6、集群架构设计考虑因素?

当你在设计架构、决定节点数量、有多少个索引以及每个索引的分片数量时,你需要把能接受的出现故障的节点数量考虑进去。

当然了,你还需要考虑性能,只不过冗余和高可用应该是进行扩展时的一个因子。

7、大规模集群节点角色如何设定?

为了有一个完全容错和高可用的集群,我们应该区分节点,为每个节点一个设计好的角色,角色分类如下: 

1)路由节点或查询聚合节点;

发送子查询到其他节点,收集和合并结果,以及响应发出查询的客户端。

node.master: false

node.data: false

2)数据节点;

node.master: false

node.data: true

3)候选主节点。

node.master: true

node.data: false

http.enabled: false

候选主节点禁用Http协议是为了避免意外地在这些节点上进行查询。这样候选主节点相比于数据节点和路由节点可以使用更少的资源,可以确保它们仅仅被用来处理和主节点相关的工作。

8、高负载场景Elasticsearch优化的常规建议?

这里是建议,不是准则。 
(1)选择正确的存储 
如:选择默认的default存储类型。

(2)按需设定刷新频率 
索引刷新频率定义:文档需要多长时间才能出现在搜索结果中。 
正确认知: 
1)刷新频率越短,查询越慢,且索引文档的吞吐率越低。 
2)默认刷新频率:1s刷新一次。 
3)无限的增加刷新时间是没有意义的,因为超过一定的值(取决于你的数据负载和数据量)之后,性能提升变得微乎其微。

(3)线程池优化 
线程池优化的必要场景:你看到节点正在填充队列并且仍然有计算能力剩余,且这些计算能力可以被指定用于处理待处理的任务。

(4)调整合并过程 
index.merge.policy.mery_factory低于默认值10,会导致更少的段,更低的RAM消耗,更快的查询速度和更慢的索引速度; 
若大于10,导致索引由更多的分段组成,更高的RAM消耗,更慢的查询速度和更快的索引速度。

(5)合理数据分布 
高索引量的使用场景:把索引分散到多个分片上来降低服务器CPU和I/O子系统的压力。

如果你的节点无法处理查询带来的负载,你可以增加更多的ES节点,并增加副本的数量,于是主分片的物理拷贝会部署到新增节点上。这样会使得文档索引慢一些,但是会给你同时处理更多查询的能力。

9.高负载、高查询频率场景的建议

(1)启动过滤器缓存和分片查询缓存 
过滤器缓存配置:indices.cache.filter.size 
分片查询缓存配置:indices.cache.query.enable

(2)优化查询语句结构 
书本中的过滤器已不再使用5.X以及更高版本。 
但,依然可以优化查询语句,返回核对查询同样语句返回时间,进行权衡优化。

(3)使用路由 
有着相同路由值的数据都会保存到相同的分片上。

(4)并行查询 
建议数据平均分配,多个节点可以有相同的负载。

(5)字段数据缓存和断路 
当使用聚合和排序等字段数据缓存相关操作时,遇到了内存相关的问题(内存泄漏或者GC停顿),可以考虑使用 doc value。

(6)控制size和shard_size 
主要针对聚合操作。 
增加size和shard_size能使得聚合结果更准确,代价是:更多的网络开销和内存使用; 
减少size和shard_size能使得聚合不那么精确,代价是:网络开销小和内存使用率低。

10、高负载、高索引吞吐量场景

(1)批量索引 
批量索引代替逐个索引文档。

(2)doc values和索引速度的取舍 
一方面:我们只关心更高的索引速度和更大的索引吞吐量,可以考虑不适用doc values。 
另一方面:如果有大量的数据,为了使用聚合和排序功能而不产生内存相关问题,唯一选择——使用 doc values。

(3)控制文档字段 
方式一:_source 控制字段输出; 
方式二:禁用_all。 
减少文档的大小和其内文本字段的数量会让索引稍快一些。

(4)索引的结构和副本 
1)主分片部署到所有的节点上,以便:并行的索引文档,加快索引的速度。 
2)过多的副本导致索引速度下降。

(5)调整预写日志。

(6)存储优化 
1)资金充足,建议购买SSD——原因:速度优势明显; 
2)资金不足,考虑ES使用多个数据路径。 
3)不要使用共享或者远程的文件系统保存索引——原因:速度慢,整体性能下降。

(7)索引期间的内存缓存 
建议给每个索引期间生效的分片分配512MB内存。 
indices.memeory.index_buffer_size是设置节点的,而不是分片。

小结

书中基于ES1.X版本的一些优化细节,可能在5.X、6.X甚至更高版本中有所不同,需要根据实战需要、并结合最新官网文档更新相关知识。 
ES仍然有很长的路要走,坚持、加油!

Image

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK