Elasticsearch核心原理与索引分析
Elasticsearch存储原理深入剖析
什么是ES?
Elasticsearch:基于Lucene的搜索服务器,分布式全文搜索引擎
ES核心概念:Index、Type、Document、Lucene
ES | MySQL |
---|---|
索引 Index | 数据库 Database |
类型 Type | 表 Table |
文档 Document | 数据行 Row |
字段 Field | Column |
Lucene 存储引擎 |
Lucene
开源全文检索引擎工具包,但不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的索引引擎和查询引擎,部分文本分析引擎
Lucene—分词器
1.字符过滤器
- 过滤特殊字符
2.分解器
3.词源过滤器
- 大小写转换
- 停用词过滤
Lucene—倒排
1.Document Frequencyl
- 文档词频
2.Frequencyl
- 词频率
Lucene—FST
Lucene的FST(Finite-State Transducers)是一种高效的数据结构,是Lucene用来构建和管理自动机的一部分。在FST中,任何字符串都可以看作一个有限状态机,每个状态代表着字符串的某个前缀。FST基于原理:序列化哈希值,通过将无序键序列化到字节数组中,强制所有的比较和排序在序列化字节上进行。
FST的实现主要有以下几个步骤:
- 建立有序键列表
在创建FST之前,需要将所有的键按照特定的规则排序,并且去重。这样就得到了一个有序的键列表,可以在FST中使用。
- 构建FST树
FST树的结构是由有序键列表构建而成的,每个节点代表着一个键前缀。FST树被划分为两个部分,即前缀区和后缀区。前缀区包含所有共享前缀的键,后缀区包含余下的键。前缀区采用自动机结构,可以高效地处理有限状态机。
- 优化FST
FST的性能取决于它的大小,因此需要对FST进行优化,以减小它的体积。这包括压缩指针和状态块,合并节点和压缩转换。
- 使用FST
完成FST的构建和优化后,可以使用FST进行各种操作,例如前缀搜索、完全匹配搜索、范围查询等等。这些操作都是基于FST的自动机结构实现的,可以快速高效地处理大量数据。
总之,Lucene的FST是一种高效的数据结构,可以用来构建和管理自动机,它具有高度的压缩性和空间效率,能够帮助Lucene提高搜索和排序的效率。
1.Finite State Transducerl
- 有限状态传感器
2.字典表的查找
3.TRIE树的优化
Lucene—FST
- 共享前缀
- 共享后缀
- 通过output定位Term
Lucene—SKIPList
Lucene的SKIPList(跳表)是一种基于多级索引的有序数据结构。在跳表中,每个节点包含了一个键和对应的值,通过多级索引的方式,可以高效地实现有序的遍历和搜索。与二叉搜索树相比,跳表可以保证O(log n)的时间复杂度,具有更高的效率和可扩展性。
以下是Lucene的SKIPList的构建过程:
- 初始化
在创建跳表之前,需要先初始化一个头部节点,该节点包含两个值:MAX_VALUE和null,其中MAX_VALUE代表正无穷,表示跳表的最大值。
- 插入新节点
当需要插入一个新的节点时,从头部节点开始遍历,通过比较当前节点和待插入节点的值,找到合适的插入位置。新节点需要随机生成一个层数,然后将其插入到每一层中对应的位置上。
- 删除节点
当需要删除一个节点时,同样从头部节点开始遍历,找到目标节点并删除该节点。同时,需要在每一层中将指向该节点的指针都删除。
- 查找节点
当需要查找一个节点时,同样从头部节点开始遍历,通过比较当前节点和目标值的大小,不断移动到下一个节点,直到找到目标节点或者到达最后一个节点。
总之,Lucene的SKIPList是一种高效的有序数据结构,它可以帮助Lucene实现快速而稳定的搜索和排序。SKIPList的精髓在于多级索引的设计,它可以缩小搜索范围,提高搜索效率,同时还能够支持高效的插入、删除和查找操作。
- 倒排中文档ID有序
- 跳跃间隔
- 层次
索引的写入效率如何保证?
保证索引的写入效率是Elasticsearch中至关重要的一点,以下是一些方法可以用来提高索引的写入效率:
-
批量写入:将多个文档合并成一个请求,减少网络传输和连接开销。在处理大批量数据时,可以考虑使用bulk API,这样可以在单次请求中批量索引、更新或删除多个文档。
-
禁止自动刷新:自动刷新意味着每次写入操作都会被实时刷新到磁盘中,这会增加IO操作和CPU负担。禁用自动刷新可以通过在写入之前设置"refresh_interval"或“refresh=false”来实现,然后在批量写入全部完成后再手动触发一次刷新。
-
配置内存缓存:Elasticsearch使用内存缓存来提高写入性能,可以通过配置缓存大小或者使用mlockall来减少交换内存导致的性能问题。同时,注意避免过度分片和副本,因为这会占用更多的内存资源。
-
使用异步刷新:在Elasticsearch的高版本中,支持异步刷新,即把刷新操作放到后台线程中执行,避免了每次刷新都需要消耗大量的CPU和IO资源。可以通过设置“index.refresh_interval=-1”和“index.translog.durability=async”来实现。
-
使用快速硬件:硬件环境对写入性能也有很大影响,使用更快的硬件如SSD和NVME SSD可以提高磁盘I/O的吞吐量和响应速度。同时,还可以考虑将数据和日志分开存储,以减轻存储设备的压力。
-
检查代码逻辑:最后,还需要检查代码逻辑,确保代码没有不必要的重试、死循环等问题,避免过于频繁的写入操作。
总之,要保证索引的写入性能,需要综合考虑各方面的因素,包括批量写入、禁用自动刷新、配置内存缓存、使用异步刷新、选择高速硬件等等。
Lucene数据组织
- 将倒排拆分成多个Segment
- commit point记录可用Segment
- 新文档在内存缓存,根据策略commit
Segment操作
- 文档更新/删除
del文件标记删除
结果聚合后过滤 - reflushl
内存数据写入Segmentl
打开Segment - flush
translog解决掉电丢数据问题
作用同Redolog、WAL - Sement合并
解决Segment过多问题
清理历史数据
1、实时刷盘性能低2、缓存文件可以打开(可以被搜索到)3、后台刷盘
ES数据存储过程
Elasticsearch系统架构深入剖析
ES整体架构
- Gateway(存储方式)
- Distributed Lucene Directory
Distributed Lucene Directory是一种Lucene扩展,它允许将Lucene索引存储在分布式的文件系统中,通过多个Lucene实例共享这些索引。 这种扩展在大规模应用程序中是非常有用的,因为它允许灵活地扩展Lucene索引并提供高可用性。
使用Distributed Lucene Directory可以将一个大的Lucene索引分散到多个机器上,以适应处理大量数据和并发查询的需要。这种分布式架构可以减少单个节点的压力和故障对整个系统的影响。
具体地说,Distributed Lucene Directory通过将Lucene索引划分成多个shard,并将这些shard分配到多台计算机上,来实现分布式的Lucene索引。每个Lucene实例都可以直接访问自己分配的shard,当需要查询所有索引时,可以将查询发送到所有分散的Lucene实例中。
在实现过程中,可以选择不同的分布式文件系统,如Hadoop HDFS、GlusterFS、NFS等,作为分布式的Lucene索引存储,以满足不同的应用场景需求。此外,Distributed Lucene Directory还可以通过多个Lucene实例集群来实现高可用性和负载均衡。
综上所述,Distributed Lucene Directory是一种强大的Lucene扩展,它可以帮助解决大规模应用程序中的高并发和高可用性问题,提高系统的稳定性和性能。
- Mapping 定义field
- Discovery集群节点发现
- Transport
内部节点和client交互协议 - JMX 监控
- Java(Netty) 开发框架
ES集群架构
- Clusterl
分布式架构,多个节点提供服务 - Node 节点
集群中的一个节点
节点对应的是ES实例,一个机器部署多个实例
Node 节点划分
- master
主要用于元数据(metadata)的处理。比如索引的新增、删除、分片分配等- data
保存了数据分片,负责数据相关操作。比如搜索、整合、分片crud- client
路由请求的作用,实际上可以看做负载均衡器
Shard 分片
将一个索引中的数据切分成多个shard
分布式下,shard 可以横向水平扩展
每个shard都是一个lucene索引结构Replication 副本
primary shard & replica shard
高可用方案
副本数据:强一致和最终一致
1.Node类型设置
node.master
node.data
node.ingest
2.Shard
分片数确定后不可变更l SSD
10G一个Shard
3. Replication
副本数可以调整
master节点:node.master: true node.data: false node.ingest:false
data节点:node.master: false node.data: true node.ingest:false
client:node.master: false node.data: false node.ingest:true
ES集群架构—关键技术
- 集群发现
单播/多播
种子节点列表+Gossip - 选主
发起时机:通过ping其他节点发现集群失去Master超过一段时间
选举策略:clusterStateVersion,集群状态数据越新优先级越高ID,节点ID越小优先级越高
选举结果:多数派原则
Elasticsearch应用场景分析
ES索引构建
索引构建:将其他数据源的数据,通过index模块在ES中生成倒排索引
需求分析
1.功能需求
多数据源的情况
多业务线的情况l使用的方便性
2. 性能需求
延迟要求
吞吐量需求
ES索引构建
索引构建:将其他数据源的数据,通过index模块在ES中生成倒排索引
- ES index的核心逻辑
Ø 倒排索引
Ø 对DB数据的映射 - transform 核心逻辑
Ø 数据获取
Ø 数据操作
1. 源数据获取
业务数据访问层
自行获取
Elasticsearch索引构建架构设计实践
ES索引构建—代码实现
-
解析配置
-
执行SQL构建Item
-
更多handle
-
ES批量写入
ES索引构建—高性能设计
-
线程模型
队列+线程
-
批量操作
相同的流程SQL
相同的处理过程
-
多业务流程
ES索引构建—高性能设计
代码实现—Deliver 实现
代码实现—process实现
整体流程
ElasticSearch之所以具有高性能,主要是因为以下几个方面:
- 基于倒排索引
ElasticSearch使用了Lucene的倒排索引机制,将存储数据的方式从按行存储改为按列存储,以使得搜索更加快捷。当我们要查询某个词语时,倒排索引可以通过查找该词在所有文档中的出现次数及其位置来快速定位匹配的文档。
- 分片和副本机制
ElasticSearch将索引拆分成多个分片,并且为每个分片创建多个副本,避免了单点故障。这种设计不仅提高了查询效率,同时还能够提高系统的可靠性和可用性。
- 自动并发控制
在多线程并发访问情况下,ElasticSearch自动控制并发请求,保证读写操作的正确性,同时避免了因竞争而导致的线程阻塞问题。
- 使用缓存
ElasticSearch使用了多种缓存技术,例如:近期使用的term、过滤器等信息都会缓存在内存中,以加速搜索。 此外,ElasticSearch还提供了一个可插拔的缓存接口,用户可以根据需要选择合适的缓存策略。
- 支持分布式计算
ElasticSearch支持分布式计算,可以将查询分发到各个节点上,然后由各个节点分别计算,最后将结果合并返回给客户端。这种方式既加快了计算速度,又保证了系统的可扩展性。
综上所述,ElasticSearch具有基于倒排索引、分片和副本机制、自动并发控制、使用缓存以及支持分布式计算等多重优势,使其具有很高的性能。
Elasticsearch搜索架构设计实践
ES搜索架构设计
-
Search
-
Proxy
-
ES Cluster
ES搜索架构设计—Proxy作用
-
屏蔽ES复杂度
-
对客户端请求进行限制和优化
-
屏蔽客户端危险操作(删除索引)
ES搜索架构设计—Proxy设计
-
多业务支持
配置化索引 -
对解析方法可插拔
索引字段解析
handler模块化
ES搜索架构设计—handler设计
ES搜索架构设计—业务逻辑层
-
请求解析
-
AB实验策略及管理
-
Query分析
-
召回计划(生成和发送)
-
召回后处理(模型排序、业务干预)
-
缓存处理(优化服务性能)
-
结果封装(AB信息等)
Elasticsearch应用调优
ES应用调优—脑裂
- Master节点负载过
- FullGC
Master节点数据分离
节点个数 N/2+1
ES应用调优—调大系统句柄数
-
查看:ulimit -a
-
设置:ulimit -n XXX/unlimited
操作系统中的句柄(handle)是用于管理应用程序资源的一种机制,如文件、套接字、进程等。在高负载的系统中,如果应用程序涉及到大量的资源管理操作,往往需要增加系统句柄数以避免资源瓶颈。以下是在Linux系统上调大句柄数的方法:
- 查看当前系统句柄数:
ulimit -a
- 编辑/etc/security/limits.conf文件增加以下两行:
* soft nofile 1024000
* hard nofile 1024000
其中soft表示软限制,hard表示硬限制,这里分别设置为1024000,即软限制和硬限制都为1024000。
- 编辑/etc/sysctl.conf文件并增加以下两行:
fs.file-max = 655350
vm.max_map_count = 262144
其中fs.file-max设置为655350,vm.max_map_count设置为262144。
- 执行以下命令使新配置生效:
sysctl -p
- 重新登录或重启服务器使新配置生效。
在以上步骤中,通过修改/etc/security/limits.conf和/etc/sysctl.conf文件来改变系统句柄的限制值,并使用sysctl命令使设置生效。重要的是要注意修改完毕后需要重新登录或重启服务器,才能让句柄数目真正生效。另外,系统句柄数需要根据系统负载和具体的应用程序需求进行适当调整,不要盲目提高句柄数目。
ES应用调优—锁定物理内存
-
memory_lock锁定物理内存
-
减少内外存交换
ES应用调优
-
合理设置分片数
分片不能修改
10G -
合理设置副本数
可以调整,
影响写入性能
影响磁盘空间
ES应用调优—定时合并索引
-
占用内存
-
占用文件句柄
ES应用调优—关闭不使用索引
- 释放不必要的内存空间
ES应用调优—合理数据导入
-
导入时不需要副本
-
索引创建完成后恢复副本
ES应用调优—去掉_all
-
去掉mapping中的_all域
-
减小索引尺寸