分布式实时搜索和分析引擎——Elasticsearch
一、概述
Elasticsearch 是一个基于 Lucene 的搜索引擎。它提供了具有 HTTP Web 界面和无架构 JSON 文档的分布式,多租户能力的全文搜索引擎。Elasticsearch 是用 Java 开发的,根据 Apache 许可条款作为开源发布。
二、节点类型 &作用
1)master 节点(主节点)
配置
【注意】node.master 和 node.data 默认都是 true, 但还是建议显式配置
作用
索引的创建或删除
跟踪哪些节点是集群的一部分
决定哪些分片分配给相关的节点
2)data 节点(数据节点)
配置
作用
存储索引数据
对文档进行增删改查,聚合操作
3)Coordinating 节点(协调节点/Client 节点)
每一个节点都隐式的是一个协调节点,Coordinating 节点是负责接收任何 Client 的请求,包括 REST Client 等。该节点将请求分发到合适的节点,最终把结果汇集到一起。一般来说,每个节点默认起到了 Coordinating 节点 的职责。配置
作用
处理路由请求
处理搜索
分发索引
4)Ingest 节点(预处理节点)
在索引数据之前可以先对数据做预处理操作,所有节点其实默认都是支持 Ingest 操作的,也可以专门将某个节点配置为 Ingest 节点。配置
作用
Ingest 节点和集群中的其他节点一样,但是它能够创建多个处理器管道,用以修改传入文档。类似 最常用的 Logstash 过滤器已被实现为处理器。
Ingest 节点 可用于执行常见的数据转换和丰富。 处理器配置为形成管道。 在写入时,Ingest Node 有 20 个内置处理器,例如 grok,date,gsub,小写/大写,删除和重命名
在批量请求或索引操作之前,Ingest 节点拦截请求,并对文档进行处理。
三、Elasticsearch 是如何实现 master 选举的
前提条件
只有候选主节点(master:true)的节点才能成为主节点。
最小主节点数(min_master_nodes)的目的是防止脑裂。
实现步骤
第一步:确认候选主节点数达标,elasticsearch.yml 设置的值 discovery.zen.minimum_master_nodes;
第二步:对所有候选主节点根据 nodeId 字典排序,每次选举每个节点都把自己所知道节点排一次序,然后选出第一个(第 0 位)节点,暂且认为它是 master 节点。
第三步:如果对某个节点的投票数达到一定的值(候选主节点数 n/2+1)并且该节点自己也选举自己,那这个节点就是 master。否则重新选举一直到满足上述条件。
【补充】master 节点的职责主要包括集群、节点和索引的管理,不负责文档级别的管理;data 节点可以关闭 http 功能。
四、如何解决 ES 集群的脑裂问题
【原因】
所谓集群脑裂,是指 Elasticsearch 集群中的节点(比如共 20 个),其中的 10 个选了一个 master,另外 10 个选了另一个 master 的情况。
【解决】
当集群 master 候选数量不小于 3 个时,可以通过设置最少投票通过数量(discovery.zen.minimum_master_nodes)超过所有候选节点一半以上来解决脑裂问题;
五、调优
1)部署时,对 Linux 的设置优化方法
关闭缓存 swap;
堆内存设置为:Min(节.点内存/2,理想是 32GB);
设置最大文件句柄数;
线程池+队列大小根据业务需要做调整;
磁盘存储 raid 方式——存储有条件使用 RAID10,增加单节点性能以及避免单节点存储故障。
2)写入调优
写入前副本数设置为 0;
写入前关闭 refresh_interval 设置为-1,禁用刷新机制;
写入过程中:采取 bulk 批量写入;
写入后恢复副本数和刷新间隔;
尽量使用自动生成的 id。
3)查询调优
禁用 wildcard(wildcard 检索可以定义为:支持通配符的模糊检索。类似于 mysql 的 like);
禁用批量 terms(成百上千的场景);
充分利用倒排索引机制,能 keyword 类型尽量 keyword;
据量大时候,可以先基于时间敲定索引再检索;
设置合理的路由机制。
六、Elasticsearch 索引文档的过程
这里的索引文档应该理解为文档写入 ES,创建索引的过程。文档写入包含:单文档写入和批量 bulk 写入,这里只解释一下:单文档写入流程。
第一步:客户写集群某节点写入数据,发送请求。(如果没有指定路由/协调节点,请求的节点扮演路由节点的角色。)
第二步:节点 1 接受到请求后,使用文档_id 来确定文档属于分片 0。请求会被转到另外的节点,假定节点 3。因此分片 0 的主分片分配到节点 3 上。
第三步:节点 3 在主分片上执行写操作,如果成功,则将请求并行转发到节点 1 和节点 2 的副本分片上,等待结果返回。所有的副本分片都报告成功,节点 3 将向协调节点(节点 1)报告成功,节点 1 向请求客户端报告写入成功。
七、索引模板
索引模板,简而言之,是一种复用机制,就像一些项目的开发框架如 Laravel 一样,省去了大量的重复,体力劳动。当新建一个 Elasticsearch 索引时,自动匹配模板,完成索引的基础部分搭建。
典型的如下所示:
上述模板定义,看似复杂,拆分来看,主要为如下几个部分:
1)模板优先级
一个模板可能绝大部分符合新建索引的需求,但是局部需要微调,此时,如果复制旧的模板,修改该模板后,成为一个新的索引模板即可达到我们的需求,但是这操作略显重复。此时,可以采用模板叠加与覆盖来操作。模板的优先级是通过模板中的 order 字段定义的,数字越大,优先级越高。
如下为定义所有以 te 开头的索引的模板:
索引模板是有序合并的。如何想单独修改某一小类索引的一两处单独设置,可以在累加一层模板:
上述第一个模板的 order 为 0,第二个模板的 order 为 1,优先级高于第一个模板,其会覆盖第一个模板中的相同项。所以对于所有以 tete 开头的索引模板效果如下:
两个模板叠加了,项目的字段,优先级高的覆盖了优先级低的,如分片数。
2)索引模板的匹配
索引模板中的 "template" 字段定义的是该索引模板所应用的索引情况。如 "template": "tete*" 所表示的含义是,当新建索引时,所有以 tete 开头的索引都会自动匹配到该索引模板。利用该模板进行相应的设置和字段添加等。
3)setting 部分
索引模板中的 setting 部分一般定义的是索引的主分片、拷贝分片、刷新时间、自定义分析器等。常见的 setting 部分结构如下:
八、冷热数据分离
ES 集群的索引写入及查询速度主要依赖于磁盘的 IO 速度,冷热数据分离的关键为使用 SSD 磁盘存储数据。若全部使用 SSD,成本过高,且存放冷数据较为浪费,因而使用普通 SATA 磁盘与 SSD 磁盘混搭,可做到资源充分利用,性能大幅提升的目标。为了解决控制成本的前提下读写性能问题,Elasticsearch 冷热分离架构应运而生。
冷数据索引:查询频率低,基本无写入,一般为当天或最近 2 天以前的数据索引
热数据索引:查询频率高,写入压力大,一般为当天数据索引
1)实现原理
Hot 节点设置:索引节点(写节点),同时保持近期频繁使用的索引。 属于 IO 和 CPU 密集型操作,建议使用 SSD 的磁盘类型,保持良好的写性能;节点的数量设置一般是大于等于 3 个。将节点设置为 hot 类型:
Warm 节点设置: 用于不经常访问的 read-only 索引。由于不经常访问,一般使用普通的磁盘即可。内存、CPU 的配置跟 Hot 节点保持一致即可;节点数量一般也是大于等于 3 个。将节点设置为 warm 类型:
es1:master 节点
es2、es3、es4 热数据节点
es5、es6 冷/温数据节点
九、分片不均衡原因 &解决方案
原因
可能存在的部分原因有以下几种:
Shard 设置不合理。
说明:大多数负载不均问题是由于 shard 设置不合理导致,建议优先排查。
Segment 大小不均。
存在典型的冷热数据需求场景。
说明:例如查询中添加了 routing 或查询频率较高的热点数据,则必然导致数据出现负载不均。
没有释放长连接,导致流量不均。
说明:该问题时常暴露于采用负载均衡及多可用区架构部署时。
解决方案
1)方案一:手动移动分片
例如移动 node-1 的分片 0 到 node-4
优点:操作简单,恢复时间短;不必修改 master node 的配置,master node 长期负载后高
缺点:索引大,移动时有很高的 IO,索引容易损坏,需要做备份,不能解决 master node 既是数据节点又是负载均衡转发器的问题
【注意】分片和副本无法移动到同一个节点
2)方案二:重建索引,从另外一个集群导入
删除原来的索引,重新建立索引,;利用 elasticsearch dump 等工具从另一个集群中把数据导入到新的索引中
优点:可以重新配置 master node 和 data node,主从负载均匀
缺点:费时间,容易数据丢失,需要验证数据的一致性
3)方案三:配置平衡参数
使用下面的命令恢复平衡
十、解决 Elasticsearch 分片未分配的问题
原因整体概述:
出现这个问题的原因是原有分片未正常关闭和清理,所以当分片要重新分配回出问题节点的时候没有办法获得分片锁。
这不会造成分片数据丢失,只需要重新触发一下分配。
unassigned 分片问题可能的原因如下:
INDEX_CREATED: 由于创建索引的 API 导致未分配。
CLUSTER_RECOVERED: 由于完全集群恢复导致未分配。
INDEX_REOPENED: 由于打开 open 或关闭 close 一个索引导致未分配。
DANGLING_INDEX_IMPORTED: 由于导入 dangling 索引的结果导致未分配。
NEW_INDEX_RESTORED: 由于恢复到新索引导致未分配。
EXISTING_INDEX_RESTORED: 由于恢复到已关闭的索引导致未分配。
REPLICA_ADDED: 由于显式添加副本分片导致未分配。
ALLOCATION_FAILED: 由于分片分配失败导致未分配。
NODE_LEFT: 由于承载该分片的节点离开集群导致未分配。
REINITIALIZED: 由于当分片从开始移动到初始化时导致未分配(例如,使用影子 shadow 副本分片)。
REROUTE_CANCELLED: 作为显式取消重新路由命令的结果取消分配。
REALLOCATED_REPLICA: 确定更好的副本位置被标定使用,导致现有的副本分配被取消,出现未分配。
解决方案如下:执行修复命令
十一、ES 读写数据过程
1)ES 写入数据的过程
客户端发送任何一个请求到任意一个 node,这个节点就成为协调节点(coordinate node)
协调节点对 document(可以手动设置 doc id,也可以由系统分配)进行 hash 路由,将请求转发给对应的 node
node 上的 primary shard 处理请求,然后将数据同步到 replica node
协调节点如果发现 primary shard 所在的 node 和所有的 replica shard 所对应的 node 都搞定之后,就会将请求返回给客户端
2)ES 读数据过程
可以通过 doc id 来查询,根据 doc id 进行 hash,判断当时写这个 document 时是分配到哪个 shard 上去了,然后就去那个 shard 上查询。
客户端发送任何一个请求到任意一个 node,这个节点就成为协调节点(coordinate node)
协调节点对 doc id 进行 hash 路由,将请求转发到对应的 node,此时会使用 round-robin 随机轮询算法,在 primary shard 以及所有的 replica shard 中随机选择一个,让读请求负载均衡
接受请求的 node,返回 document 给协调节点
协调节点再将数据返回给客户端
十二、在海量数据中提高效率的几个手段
filesystem cache:ES 的搜索引擎严重依赖底层的 filesystem cache,如果给 filesystem cache 更多的内存,尽量让内存可以容纳所有的 index segment file 索引数据文件
数据预热:对于那些你觉得比较热的数据,即经常会有人访问的数据,最好做一个专门的缓存预热子系统,对于热数据,每隔一段时间,系统本身就提前访问一下,让数据进入 filesystem cache 里面去,这样下次访问的时候,性能会更好一些。
冷热分离:冷数据索引:查询频率低,基本无写入,一般为当天或最近 2 天以前的数据索引,这种数据可以存储在机械硬盘 HDD 中热数据索引:查询频率高,写入压力大,一般为当天的数据索引,这种数据可以存储在 SSD 中
document 的模型设计:不要在搜索的时候去执行各种复杂的操作,尽量在 document 模型设计和数据写入的时候就将复杂操作处理掉
分页性能优化:翻页的时候,翻得越深,每个 shard 返回的数据越多,而且协调节点处理的时间越长,此时,要用 scroll,scroll 会一次性的生成所有数据的快照,然后每次翻页都是通过移动游标来完成
评论