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