ElasticSearch 原理详解 (详解在注释里面,图片加载需要时间)
2023-07-04 08:50:17 0 举报
AI智能生成
知识要点和原理解析,详细信息和图片均在黄色图标的注释中,鼠标移动到黄色图标上即会显示,图片加载有时较慢。
作者其他创作
大纲/内容
主要功能
海量数据的分布式存储以及集群管理,达到了服务与数据的高可用以及水平扩展
近实时搜索,性能卓越。对结构化、全文、地理位置等类型数据的处理
海量数据的近实时分析(聚合功能)
基础概念
整体架构图
Near Realtime(NRT)
Cluster - 集群
两个特性
高可用性
可扩展性
集群健康值
green:所有主要分片和复制分片都可用
yellow:所有主要分片可用,但不是所有复制分片都可用
red:不是所有的主要分片都可用
Node - 节点
节点角色
master 主节点
data 数据节点
一个节点可以既为Master节点,又为Data节点,但是为什么不推荐?
data_content 内容数据节点
voting_only 仅投票节点
coordinating 仅协调节点
data_hot 热点数据节点
data_warm 暖数据节点
data_cold 冷数据节点
data_frozen 冻结数据节点
ingest 摄取节点
注意
如果你设置了 node.roles,则节点只会分配你指定的角色。 如果不设置 node.roles,节点将被分配以上所有角色(除了voting_only 和coordinating角色例外)。
节点不等同于服务器,一个服务器上可以部署多个节点。
集群中的每个节点都可以处理 HTTP 和传输流量。
所有节点都知道集群中的所有其他节点,并且可以将客户端请求转发到适当的节点。
分片
Shard - 分片(重点理解)
Primary Shard(主分片)
ES中的shard用来解决节点的容量上限问题,,通过主分片,可以将数据分布到集群内的所有节点之上。
Replication- 副本
作用
1、服务高可用(容灾)
2、扩展性能
对于一个索引,除非重建索引否则不能调整主分片的数目(主分片数, number_of_shards),但可以随时调整replica数(number_of_replicas)。
读取时主副分片使用轮询实现负载均衡
分片的设定
分片数设置过小
分片数设置过大
Index - 索引
Type - 类型
从6.0.0 版本起已废弃,一个索引中只存放一类数据
Document - 文档
文档的源数据
_index:文档所属索引名称
_type:文档所属类型名
index、type的初衷
为什么现在要移除type?
_id :Doc的主键。在写入的时候,可以指定该Doc的ID值,如果不指定,则系统自动生成一个唯一的UUID值
生成方式
_version:文档的版本信息。Elasticsearch通过使用version来保证对文档的变更能以正确的顺序执行,避免乱序造成的数据丢失。
_seq_no:严格递增的顺序号,每个文档一个,Shard级别严格递增,保证后写入的Doc的_seq_no大于先写入的Doc的_seq_no
primary_term:primary_term也和_seq_no一样是一个整数,每当Primary Shard发生重新分配时,比如重启,Primary选举等,_primary_term会递增1
found:查询的ID正确那么ture, 如果 Id 不正确,就查不到数据,found字段就是false
_source:文档的原始JSON数据
ES和数据库的对比
lucene
结构图
lucene文件内容
术语
Field域
最基本常用属性
边界值限制
单个索引的字段数量上限
映射字段最大嵌套深度
字段名称最大长度
分页查询最大文档查询数量
文档查询的最大召回数量
组合查询(bool query)最大子句限制
聚合查询最大分桶数量
单次查询最大词项数量
单个分片最大文档数量上限(shard max doc count)
单个文档最大容量上限
分段存储-segment
每个段都是一个独立的可被搜索的数据集,并且段具有不变性,一旦索引的数据被写入硬盘,就不可修改。
为了提升写的性能,Lucene 并没有每新增一条数据就增加一个段,而是采用延迟写的策略,每当有新增的数据时,就将其先写入内存中,然后批量写入磁盘中。
ES Segment Memory
本质上就是segment中加到内存的FST数据,因此segment越多,该内存越大
分段思想下对数据写操作过程
新增
删除
更新
段不可变性的优点
不需要锁
可以常驻内存
缓存友好
增量创建
段不可变性的缺点
删除
更新
新增
过滤
提交点
segment的数据结构
Inverted Index
Stored Fields
哪些情形下需要显式的指定store属性呢?
Document Values
Cache
Lucene为什么要加Segment概念
Lucene索引
倒排索引
数据结构
posting list的ID范围
索引结构
索引过程
全文索引
全文数据库
全文检索
正向文件-原始文档
结构
正排索引DocValues 列式存储
保存位置
倒排&正排
对比
倒排
正排
区别
倒排索引+正排索引结合的优势
为什么需要doc values 剖析
查询分析
有 3 个方法
方法一
缺点
方法二
缺点
方法三
Doc values 深入认识
特性
生成时机
数据结构
存储位置
在什么粒度上会生成 doc values
默认开启
使用方式
不适应 text 类型字段
text类型如何建索引
fielddata
语法
特点
内存管理和生成,常驻内存
更占内存
懒加载
全加载
与 doc values,倒排索引一样基于 segment 建立而不是基于整个索引建立。
默认关闭
存在问题
生成慢
解决
占空间
解决
Fielddata过滤
fielddata和doc value对比
问题
读取 doc values 的数据放置在内存,这个内存是应用内存还是系统内存呢?
Aggregations—聚合功能
示例
单点聚合,结果可能不准确
倒排表压缩方案
Frame Of Reference
增量编码
流程步骤
例子
编码排序整数的方法比较
Integer array
bitmap
bitmap缺点
那为什么用4096来区分采用数组还是bitmap的阀值呢?
roaring bitmaps
为什么是以65535为界限?
Roaring Bitmaps设计思路
每个桶都有对应的 Container,不同的 Container 存储方式不同
1、Array Container
示例
2、Bitmap Container
示例
3、RunContainer
ArrayContainer转换为BitmapContainer的阈值
与bitmap性能的对比
空间节省
更高效的做交、并操作
Roaring bitmaps 和 Frame Of Reference 的关系
多个SHOULD的Query的文档号合并
文档号合并
1、处理包含关键字“a”的文档
2、处理包含关键字“b”的文档
3、处理包含关键字“c”的文档
4、处理包含关键字“e”的文档
5、统计文档号
FixedBitSet
构造函数
void set(int index)方法
例子
添加 3
添加 67
添加 120
添加179、195、313
通过上面的例子可以看到,如果我们存储的是连续的值,那么压缩率是很高的。当然同时可以看出无法处理有相同值的问题。
boolean get(int index)方法
get()方法可以实现随机访问,来确定index的值是否在bit[]数组中
FixedBitSet类中还有一些其他的方法
Spark之BloomFilter有趣的bitwise运算
BitArray巧妙的核心设计
比较有意思的是set方法的实现
>>>和>>
那么index >>> 6又是什么?
1L << index
index大于64位呢
Java内部自动 % 64
1L << index按Java内部的处理拆解
BitArray的set方法
一些常用的bitwise运算实例
判断int型变量a是奇数还是偶数
取模运算转化成位运算 (在不产生溢出的情况下)
乘法运算转化成位运算 (在不产生溢出的情况下)
除法运算转化成位运算 (在不产生溢出的情况下)
取相反数
其他
lucenen索引层面的写入、更新、删除、合并
写入过程
过程分解
首先,document会被写入in-memory buffer和translog日志文件
每隔1秒,执行一次refresh操作
refresh操作完成后,buffer会被清空
图解
为什么说Elasticsearch是准实时(NRT,near real-time)?
实时查询 - GetById
Translog 事务日志
写入机制
图解
Translog的同步控制参数
flush过程
触发flush操作
第一步,将buffer中的现有数据refresh到os cache中生成segment,清空buffer
把之前所有没有落盘的 segment 强制刷盘,确保写入物理文件。
创建一个提交点,记录这次提交对应的所有 segment,写入 commit point 文件。
清空 Translog,因为 Segment 都已经踏实落地了,之前的 Translog 就不需要了。
触发清理动作的2个条件
大小触发设定的阈值;
30分钟
删除和更新
update流程(部分更新)
versionMap
主要用途在数据变更时的校验
_id与_uid的联系
segment 合并
定期合并
合并完成时的活动
合并也是在内存中完成的,此时数据还没有写到磁盘中
整体流程图
图1
图2
memory buffer的倒排索引,则必须等Segment内所有文档全部写入完毕后,会先对Term进行一个全排序,之后才能构建索引,所以必须要有一个memory-buffer先缓存所有文档。
Elasticsearch的写入流程特性
可靠性
一致性
原子性
实时性
隔离性
ES层面写流程
整体的索引流程
路由规则
目标分片接收数据并refresh
flush
一主多副架构
Primary、Replica 副本同步
索引更新机制
ES层面读流程
文档查询步骤顺序
单个文档
多个文档
文档读取过程
query_then_fetch
准备fetch doc源码
ElasticSearch读取文档的实现机制
Lucene的读
Elasticsearch的读
分布式查询
查询主要分为两类
Get请求:通过ID查询特定Doc
Search请求:通过Query查询匹配Doc
交并集方案比较
二重for循环法
拉链法,时间复杂度O(n)
水平分桶,多线程并行
bitmap,大大提高运算并行度,时间复杂度O(n)
跳表,时间复杂度为O(log(n))
倒排合并
一致性(Consistency)
三种设置来判断是否允许写操作
One
All
Quorum(k-wu-wo/reng,法定人数)
ES内存结构与使用
内存结构
On Heap内存占用
Indexing Buffer
缓存时机
失效或者回收
配置
Node Query Cache (Filter Cache)
缓存的构建过程
示例
缓存时机
失效或回收
Shard Request Cache
主要作用
缓存时机
失效或回收
Field Data Cache
Segment Cache(Segment FST Cache)
内存回收与释放
拿什么来防止 ES OOM ?
Parent circuit breaker 总断路器
Field data circuit breaker 字段数据断路器
Request circuit breaker 请求数据断路器
Off Heap内存占用
如何提高查询性能?
1、性能优化的杀手锏——filesystem cache
2、数据预热
3、 冷热分离
4、document模型设计
5、分页性能优化
Zen Discovery机制
es p2p机制
master node
cluster.name(默认值是elasticsearch)
节点发现方式
单播(unicast)
配置
ping
unicast
通俗理解
主要步骤
基于文件
配置
基于文件的发现插件会增强单播主机列表 elasticsearch.yml
示例
选举原理之Bully算法
触发选举的两种情况
当master-eligible(候选master)节点数量小于法定票数
当主节点宕机
选举流程
选举时间点
集群启动初始化
集群的Master崩溃的时候
任何一个节点发现当前集群中的Master节点没有得到n/2 + 1节点认可的时候,触发选举
选举流程图
1、筛选activeMasters列表
从activeMasters列表选举Master节点
2、筛选masterCandidates列表
从masterCandidates列表选举Master节点
选举流程
示例
Elasticsearch编号比较
Master假死
Elasticsearch是如何解决这个问题的呢?
脑裂问题
Elasticsearch脑裂解决方案-Quorum算法
Master更新集群状态时的防护
Master降级
异常检测
1、Master
NodesFaultDetection事件处理
2、非Master
MasterFaultDetection事件处理
ping参数
ES相关命令及操作
mapping
分片管理
基本概念
主分片(primary shard)
副本分片(replica shard
部署
分片管理官方建议
1、分片大小在 10GB 到 50GB 之间
大分片需要更长的恢复时间
小分片会带来更多的开销并且搜索效率较低
2、每 GB 堆内存 20 个或更少的分片
3. 分配管理小结
避免使用非常大的分片
分片数不是越多越好
分片最大容量限制
当数据量可以合理预测并且变化缓慢时,具有固定时间间隔的基于时间的索引很有效。
跨索引查询
为什么需要跨索引查询
技术限制
技术便利
ES提供两个维度的拆分方式
ES查询示意图:多索引+多分片
跨索引查询应用场景
示例1:实时数据与历史数据业务场景
示例2:大数据平台写数据到Elastic平台
日志
跨索引查询应用方式
直接型
模糊型
计算型
跨索引查询技术原理
索引分片
查询过程
跨索引查询注意事项
索引与分片等价关系
协调节点分离
路由机制
ES分页
三种分页技术
From+Size
介绍
query 和 fetch 阶段
Query阶段
coordinating node 计算好自己的优先级队列后,query 阶段结束,进入 fetch 阶段。
Fetch阶段
From + size 查询优点
支持随机翻页
From + size 查询缺点
受制于 max_result_window 设置,不能无限制翻页
超出max_result_window
两个解决方案
方案一:大数据集召回数据使用:scroll api。
方案二:调大 index.max_result_window 默认值。
存在深度翻页问题,越往后翻页越慢
From + size 查询适用场景
深度翻页不推荐使用 From + size
Search After(指定排序字段+游标)
使用 search_after 机制需要注意点
用法举例
基本原理
search_after 优点
不严格受制于 max_result_window
无状态查询
不需要维护scroll_id
search_after 缺点
search_after 适用场景
Scroll
实时性
scroll可以分为初始化和遍历两部分
使用例子
实现原理
分三种情况
带 query,不带 sort
不带 query,不带 sort
带 sort
scroll 查询优点
支持全量遍历
适用于非实时处理大量数据的情况,比如要进行数据迁移或者索引变更之类的
scroll 查询缺点
scroll_id会占用大量的资源(特别是排序的请求)
是生成的历史快照,对于数据的变更不会反映到快照上
scroll后接超时时间,频繁的发起scroll请求,会出现一些列问题
scroll 查询适用场景
全量或数据量很大时遍历结果数据,而非分页查询
Scroll Scan
基本使用
Scroll Scan与Scroll的区别
Sliced Scroll
小结
并发控制及乐观锁实现原理
常用的锁方案
悲观并发控制
乐观并发控制
Elasticsearch默认使用乐观锁
ES的乐观锁方案
案例
乐观锁方案
使用内置_version实战乐观锁控制效果
使用外部_version实战乐观锁控制效果
内置_version/外部_version的区别
内置_version
外部_version
Replica Shard数据同步并发控制
Shard的数据同步也是基于内置的_version进行乐观锁并发控制的
示例
那Elasticsearch内部是如何做的呢?
相关性评分
性能优化
造成磁盘被打爆有以下几种原因
实践经验
Elasticsearch集群写入变慢
实践经验
开发规范
日志类应用
非日志类应用
优化索引性能
优化2
0 条评论
下一页