Elasticsearch:基于Lucene的搜索服务器,分布式全文搜索引擎
ES核心概念:Index、Type、Document、Lucene
ES | MySQL |
---|---|
索引 Index | 数据库 Database |
类型 Type | 表 Table |
文档 Document | 数据行 Row |
字段 Field | Column |
Lucene 存储引擎 |
开源全文检索引擎工具包,但不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的索引引擎和查询引擎,部分文本分析引擎
1.字符过滤器
2.分解器
3.词源过滤器
1.Document Frequencyl
2.Frequencyl
Lucene的FST(Finite-State Transducers)是一种高效的数据结构,是Lucene用来构建和管理自动机的一部分。在FST中,任何字符串都可以看作一个有限状态机,每个状态代表着字符串的某个前缀。FST基于原理:序列化哈希值,通过将无序键序列化到字节数组中,强制所有的比较和排序在序列化字节上进行。
FST的实现主要有以下几个步骤:
在创建FST之前,需要将所有的键按照特定的规则排序,并且去重。这样就得到了一个有序的键列表,可以在FST中使用。
FST树的结构是由有序键列表构建而成的,每个节点代表着一个键前缀。FST树被划分为两个部分,即前缀区和后缀区。前缀区包含所有共享前缀的键,后缀区包含余下的键。前缀区采用自动机结构,可以高效地处理有限状态机。
FST的性能取决于它的大小,因此需要对FST进行优化,以减小它的体积。这包括压缩指针和状态块,合并节点和压缩转换。
完成FST的构建和优化后,可以使用FST进行各种操作,例如前缀搜索、完全匹配搜索、范围查询等等。这些操作都是基于FST的自动机结构实现的,可以快速高效地处理大量数据。
总之,Lucene的FST是一种高效的数据结构,可以用来构建和管理自动机,它具有高度的压缩性和空间效率,能够帮助Lucene提高搜索和排序的效率。
1.Finite State Transducerl
Lucene的SKIPList(跳表)是一种基于多级索引的有序数据结构。在跳表中,每个节点包含了一个键和对应的值,通过多级索引的方式,可以高效地实现有序的遍历和搜索。与二叉搜索树相比,跳表可以保证O(log n)的时间复杂度,具有更高的效率和可扩展性。
以下是Lucene的SKIPList的构建过程:
在创建跳表之前,需要先初始化一个头部节点,该节点包含两个值:MAX_VALUE和null,其中MAX_VALUE代表正无穷,表示跳表的最大值。
当需要插入一个新的节点时,从头部节点开始遍历,通过比较当前节点和待插入节点的值,找到合适的插入位置。新节点需要随机生成一个层数,然后将其插入到每一层中对应的位置上。
当需要删除一个节点时,同样从头部节点开始遍历,找到目标节点并删除该节点。同时,需要在每一层中将指向该节点的指针都删除。
当需要查找一个节点时,同样从头部节点开始遍历,通过比较当前节点和目标值的大小,不断移动到下一个节点,直到找到目标节点或者到达最后一个节点。
总之,Lucene的SKIPList是一种高效的有序数据结构,它可以帮助Lucene实现快速而稳定的搜索和排序。SKIPList的精髓在于多级索引的设计,它可以缩小搜索范围,提高搜索效率,同时还能够支持高效的插入、删除和查找操作。
保证索引的写入效率是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的吞吐量和响应速度。同时,还可以考虑将数据和日志分开存储,以减轻存储设备的压力。
检查代码逻辑:最后,还需要检查代码逻辑,确保代码没有不必要的重试、死循环等问题,避免过于频繁的写入操作。
总之,要保证索引的写入性能,需要综合考虑各方面的因素,包括批量写入、禁用自动刷新、配置内存缓存、使用异步刷新、选择高速硬件等等。
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扩展,它可以帮助解决大规模应用程序中的高并发和高可用性问题,提高系统的稳定性和性能。
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
索引构建:将其他数据源的数据,通过index模块在ES中生成倒排索引
需求分析
1.功能需求
多数据源的情况
多业务线的情况l使用的方便性
2. 性能需求
延迟要求
吞吐量需求
索引构建:将其他数据源的数据,通过index模块在ES中生成倒排索引
代码实现—Deliver 实现
代码实现—process实现
ElasticSearch之所以具有高性能,主要是因为以下几个方面:
ElasticSearch使用了Lucene的倒排索引机制,将存储数据的方式从按行存储改为按列存储,以使得搜索更加快捷。当我们要查询某个词语时,倒排索引可以通过查找该词在所有文档中的出现次数及其位置来快速定位匹配的文档。
ElasticSearch将索引拆分成多个分片,并且为每个分片创建多个副本,避免了单点故障。这种设计不仅提高了查询效率,同时还能够提高系统的可靠性和可用性。
在多线程并发访问情况下,ElasticSearch自动控制并发请求,保证读写操作的正确性,同时避免了因竞争而导致的线程阻塞问题。
ElasticSearch使用了多种缓存技术,例如:近期使用的term、过滤器等信息都会缓存在内存中,以加速搜索。 此外,ElasticSearch还提供了一个可插拔的缓存接口,用户可以根据需要选择合适的缓存策略。
ElasticSearch支持分布式计算,可以将查询分发到各个节点上,然后由各个节点分别计算,最后将结果合并返回给客户端。这种方式既加快了计算速度,又保证了系统的可扩展性。
综上所述,ElasticSearch具有基于倒排索引、分片和副本机制、自动并发控制、使用缓存以及支持分布式计算等多重优势,使其具有很高的性能。
屏蔽ES复杂度
对客户端请求进行限制和优化
屏蔽客户端危险操作(删除索引)
查看:ulimit -a
设置:ulimit -n XXX/unlimited
操作系统中的句柄(handle)是用于管理应用程序资源的一种机制,如文件、套接字、进程等。在高负载的系统中,如果应用程序涉及到大量的资源管理操作,往往需要增加系统句柄数以避免资源瓶颈。以下是在Linux系统上调大句柄数的方法:
ulimit -a
* soft nofile 1024000
* hard nofile 1024000
其中soft表示软限制,hard表示硬限制,这里分别设置为1024000,即软限制和硬限制都为1024000。
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命令使设置生效。重要的是要注意修改完毕后需要重新登录或重启服务器,才能让句柄数目真正生效。另外,系统句柄数需要根据系统负载和具体的应用程序需求进行适当调整,不要盲目提高句柄数目。
memory_lock锁定物理内存
减少内外存交换
合理设置分片数
分片不能修改
10G
合理设置副本数
可以调整,
影响写入性能
影响磁盘空间
占用内存
占用文件句柄
导入时不需要副本
索引创建完成后恢复副本
去掉mapping中的_all域
减小索引尺寸