ELK
E 代表 ElasticSearch,L代表 LogStash,K 代表 Kibana
什么是Elasticsearch
由 Java语言开发基于 Lucene 的 Restful 的分布式实时全文搜索引擎,也可以称作是一种非关系型文档数据库
应用场景:搜索和数据分析
基本概念
- index 索引:类似于mysql 中的数据库,用于存放数据
- type 类型:在 7.0.0中的API中弃用,并在8.0.0中完全删除
- Field 字段:一个document里面有多个field
- document 文档:类似于 MySQL 中的一行
- shard 分片:es可以将一个索引中的数据切分为多个shard,分布在多台服务器上存储
- replica 副本:可以在shard故障时提供备用服务,保证数据不丢失
- Cluster 集群:包含多个节点,每个节点属于哪个集群是通过一个配置(集群名称)来决定的
近实时(NRT)
从写入数据到数据可以被搜索到有一个小延迟
用于快速查找文档中的词语。它将每个词映射到包含该词的文档列表,以加速搜索。它的优点包括高效的全文搜索、支持复杂的查询和高性能。
mapping有点类似与RDB中“表结构”的概念,比如字段名称、类型、字段使用的分词器、是否评分、是否创建索引等属性
doc_values
在构建倒排索引的同时,构建了正排索引,从而实现根据指定字段进行排序和聚合的功能
text 和 keyword类型的区别
keyword 类型是不会分词的,直接根据字符串内容建立倒排索引,所以可以通过精确值搜索到
Text 类型在存入 Elasticsearch 的时候,会先分词,然后根据分词后的内容建立倒排索引
query 和 filter 的区别
query:查询操作不仅仅会进行查询,还会计算分值,用于确定相关度;
filter:查询操作仅判断是否满足查询条件,不会计算任何分值,也不会关心返回的排序问题,同时,filter 查询的结果可以被缓存,提高性能。
节点角色
主节点:负责集群本身的管理;比如创建索引;投票节点:只参与主从选举
候选主节点:可以被选举为主节点的节点
协调节点:协调请求的处理过程,一个请求发送到该协调节点会确定数据节点,数据节点执行查询,协调节点将结果集返回
数据节点
master 节点选举
使用一种称为 “Zen Discovery” 的分布式一致性算法来管理集群状态和实现 master 节点选举;过程如下:
- 节点发现:集群中的节点通过广播(Multicast)或单播(Unicast)方式互相发现。单播是在 elasticsearch.yml 配置文件中指定其他节点的 IP 和端口。从 Elasticsearch 7.0 开始,广播已被废弃,只支持单播。
- 主节点选举:当发现一台或多台节点丢失 master 节点时,集群中的节点会开始主节点选举。每个节点首先会检查自己是否具备成为主节点的资格(主节点资格由配置文件中的 “node.master” 参数决定,该参数默认为 true)。然后,节点将与其他具备主节点资格的节点通信,共同进行选举。
- 选举过程:Elasticsearch 使用了一种基于版本号的选举算法。每个节点都有一个集群状态版本号。在选举过程中,具备主节点资格的节点会分享它们的集群状态版本号。具有最高版本号的节点将被选为新的主节点。如果有多个节点具有相同的最高版本号,节点 ID 将作为决定因素,ID 最小的节点将被选为主节点。
- 选举结果传播:一旦新的主节点被选举出来,它将通知集群中的其他节点。然后,集群中的所有节点将接受新主节点的指导,并开始执行由主节点分配的集群级任务。
脑裂
当主节点无法工作时,会从备选节点选出一个作为新的主节点。由于网络抖动等原因,主节点未及时响应,集群认为主节点挂了,选举出一个新的主节点,导致出现两个主节点,其他节点不知道听谁调度。
深度分页其实就是搜索的深浅度。搜索得太深,就会造成性能问题,会耗费内存和占用cpu。而且es为了性能,他不支持超过一万条数据以上的分页查询。
写入数据流程
1. 文档写入es 的 buffer,同时记录 translog 到 page cache,默认 5 秒刷新到磁盘
2. 文档 buffer 定时刷新到 page cache,默认 1 秒执行一次
包含多个段,每个段包含多个文档
文档写入这里才能被搜索到
每个段都消耗 cpu,内存,文件句柄
3. 刷新磁盘,同时记录一个 commit point
索引和分片
索引有多个分片,每个分片有主从结构
索引机制
倒排索引
写入文档时,根据文档每个字段,使用分词器,将字段值分割为 term;
es 会统计每个 term 频率,构建 term 到文档 id,出现频率,偏移位置的映射(posting list)
FST
类似前缀树,它将前缀和后缀一并压缩
如何保证高可用
核心是分片,通过主从分片,即使主分片崩溃,也基本可用
写入数据时,额外写了 translog,类似 mysql redolog,即使 es 崩溃,也可以恢复数据
高可用方案
限流:
- 通过插件机制实现自定义限流(通过 cpu 和内存使用率判断)
- 在 es 前增加网关
- 在业务测限制查询频率
消息队列消峰:监听 mysql binlog,生成消息到 kafka
保护协调节点:防止遇到大请求情况崩溃,解决办法是设置专门的协调节点
双集群:可以采用消息队列双写 es,查询时判断集群 a 是否有问题,出现问题切换到集群 b
如何优化性能
- 优化分页查询:通过 scroll 或者 search after
- 批量提交
- 优化索引字段:只存必要字段
- 增大刷新间隔:index.refresh_interval 为 30
- 冷热分离:冷数据放到性能差的服务器
- 优化垃圾回收:G1 算法
- 优化 swap:将操作系统 vm.swappness 修改为小值;将 es bootstrap.memory_lock=true
- 文件描述符
- 硬件优化
- 分片和副本优化
数据一致性(并发冲突)