Elastic Search 学习笔记
Elastic Search 学习笔记
简介
是一个开源的搜索引擎。
它介于应用和数据之间,只要将数据写入 es,应用就可以通过一些关键词搜索到数据。效果就像某度搜索一样。
原理
基础概念
正排:依次遍历文本匹配是否含有关键词
倒排:遍历关键词去搜索对应原始数据的id
分词:对文本进行切分
词项term:分词后的每部分。词项非常多,时间复杂度为O(N),按字典序从小到大排序,二分查找O(lgN)
排好序的词项Term Dictionary:包括term(词项)和对应的文档id(其实还包括词频、偏移量等等)
数据量很大,放内存并不现实,因此必须放在磁盘中。但查询磁盘是个较慢的过程
==》提取词项相同的前缀,构成目录树term index
搜索出来的是文档id,获取文档内容本身==》Stored Fields(行式存储)存放文档id和对应的文档内容
根据某个字段排序文档,但是字段散落在文档中==》空间换时间的思路,再构造一个列式存储结构,将散落在各个文档的某个字段,集中存放
lucene总结
倒排索引用于搜索
Term Index 用于加速搜索【相同前缀,目录树】
Stored Fields 用于存放文档的原始信息
Doc Values 用于排序和聚合。
这些结构共同组成了一个复合文件segment,segment 一旦生成,则不能再被修改,所以旧的segment只负责读,新的segment 负责读和写;segment 一旦变多就有segment merging段合并
而多个segment组成lucene,一个单机的文本检索库
es的进步
es就是在lucene 的基础上实现了
高性能:对数据进行分类写入不同的lucene,把多操作分摊到多个分片shard 中去
高扩展:把shard 分散部署在多台机器
高可用:在不同node添加shard 的副本
涉及到集群部分:
Node角色分化:主节点负责管理集群;数据节点负责存储管理数据,协调节点负责接受客户端搜索查询请求
去中心化:选主,在 Node 间引入协调模块,用类似一致性算法 Raft 的方式,在节点间互相同步数据
实现过程
写入流程
- 当客户端应用发起数据写入请求,请求会先发到集群中协调节点。
- 协调节点根据 hash 路由,判断数据该写入到哪个分片(Shard),找到主分片并写入到 lucene 库里的 segment 内,将数据固化为倒排索引和 Stored Fields 以及 Doc Values 等多种结构。
- 主分片 写入成功后会将数据同步给 副本分片。
- 副本分片 写入完成后,主分片会响应协调节点 ACK
- 最后,协调节点响应客户端应用写入完成。
搜索过程
- 查询阶段
- 当客户端应用发起搜索请求,请求会先发到集群中的协调节点。
- 协调节点根据 index name 的信息,可以了解到 index name 被分为了几个 分片,以及这些分片 分散哪个数据节点上,将请求转发到这些数据节点的 分片 上面。
- 搜索请求到达分片后,分片 底层的 lucene 库会并发搜索多个 segment,利用每个 segment 内部的倒排索引获取到对应文档 id,并结合 doc values 获得排序信息。分片将结果聚合返回给协调节点。
- 协调节点排序聚合多个分片中拿到的数据,舍弃大部分不需要的数据。
- 获取阶段
- 协调节点再次拿着文档 id 请求数据节点里的 分片,分片 底层的 lucene 库会从 segment 内的 Stored Fields 中取出完整文档内容,并返回给协调节点。
- 协调节点最终将数据结果返回给客户端。完成整个搜索过程。
实践
中文分词
分词机制:字符过滤(移除特殊符号)、分词器、词项过滤器(转小写,停用词,同义,长度过滤)
中文分词的挑战:没有自然分隔、歧义词、词性多样
使用IK分词器
电子商务中的商品搜索:使用 同义词过滤器 和 拼音分词 来扩展用户查询,提高商品搜索的精度和召回率。
内容推荐和个性化搜索:通过 智能分词 提升语义理解能力,识别用户查询中的重要部分,增强推荐的相关性;结合 上下文分析 和 实体识别 技术,可以进一步理解用户的搜索意图,从而提供个性化的推荐。
社交媒体和评论分析:通过 分词器的定制化 和 同义词扩展,可以帮助解析出用户的真正意图,例如“赞”、“喜欢”等表达同一情感的词可以归为同一类;在分析社交数据时,还需要处理拼音输入带来的问题,尤其是年轻用户常用拼音代替汉字,利用拼音分词器优化这类搜索场景。
如何与mysql保持一致?
【IT老齐268】ElasticSearch与MySQL如何搭配,很多人都弄错了_哔哩哔哩_bilibili
- Binlog同步(如使用Canal)适合需要实时同步且能保证较高一致性的场景。
- 应用程序双写简单有效,但需要注意事务性和网络问题。
- 定时批量同步适合对实时性要求不高的业务。
- 消息队列同步提供异步处理,解耦MySQL和ES操作,但需要处理好消息丢失和幂等性问题。
使用Canal实现ES与MySQL保持一致性注意事项
- Binlog 格式设置:Canal 只能解析 ROW 格式的 Binlog 日志,而不是默认的 STATEMENT 或 MIXED。
- 初始化:Canal只能增量同步,所以要先进行全量数据导入
- 写入性能优化:使用批量写入(Bulk API)而不是每次变更都单独发送请求
- 幂等性处理:恢复、网络抖动或者重试时Canal 可能会重复接收到同一条 Binlog 记录 ==》MySQL
ID
作为文档的_id
字段 - 数据一致性:同步数据是异步操作,接受一定延迟,Canal要设置失败重试
- 监控:建立监控报警机制,当同步延迟或出现异常时,能够及时告警并采取修复措施。
面试问题
倒排索引,分词器(分词流程),分片机制(分布式集群),分段机制,一般考的就是倒排
es搜索引擎,高并发架构的一环,简单来讲是搜索功能的升级版(比通常数据库的like %效率更高,耗费性能更少),实习的话不算必须项,算加分项,工作以后看项目需求(如果你的项目很少用到搜索功能,就不太需要,比如说专门研究网络传输的部门,毕竟完全没有高并发,不是toC端的),不过实习的时候面试官应该都会本着试探你学习能力的目的稍微问问吧。
- 为什么用Elasticsearch(包含为什么快/和直接使用MySQL模糊查询比较有什么优势/为什么不用mysql)
- ES专为全文检索设计,能够处理复杂的分词、权重计算、相关性排序等需求
- 权重是一个比较重要的指标,会影响影响文档的相关性得分
- 搜索引擎:为不同的字段或文档设置权重,确保更重要的内容在搜索结果中排名靠前。
- 电商平台:提升用户更可能购买的商品,或者某些促销商品的排名。
- 内容推荐系统:根据用户历史浏览、点击、购买行为,动态调整内容的推荐权重。
- 倒排索引,查找速度远超MySQL的
LIKE
查询。尤其是当数据量巨大时,MySQL模糊查询会变得非常慢 - ES天生支持分布式存储和查询,能够轻松扩展处理大规模数据,适用于日志分析、数据搜索等场景。MySQL虽然也可以通过分库分表解决,但操作复杂且扩展性较差。
- 支持多种复杂查询,如地理位置查询、模糊匹配、聚合分析等,功能远超MySQL。
- 读写分离
- ES专为全文检索设计,能够处理复杂的分词、权重计算、相关性排序等需求
为什么不用mysql
单表有限、B+树不适合不适合全文检索
为什么不直接只用ES(Mysql的优势)
ES:非关系型数据库不适合,不支持事务
- ES 有哪些数据类型以及用了哪些
结构类型见【基础概念part】
数据类型:
- 核心类型:8种基本数据类型
- 怎样数据同步(为什么引入Elasticsearch canel)
性能优化
- 压力大怎么处理
增加节点:增加数据节点(Data Node)来水平扩展。
调整集群资源配置:
- 分片(Shard)数量:合理配置主分片和副本分片的数量。
- 资源隔离:通过角色分离不同节点,如数据节点、主节点和协调节点避免因资源争抢而导致瓶颈。
缓存机制:使用查询缓存和索引缓存来减少对磁盘的访问频率;针对常见查询结果,使用_search
API的request_cache
来缓存结果。
请求优化:
- 尽量使用分页查询(Scroll API)或批量操作(Bulk API)来减小单次请求的压力。
- 控制查询深度(限制深度分页)和返回数据量(减少字段选择)来降低查询负载。
- 数据倾斜:某些节点或分片承载了过多的查询或写入请求,导致这些节点或分片成为性能瓶颈。
自定义路由:使用_routing
参数进行自定义路由,确保数据根据业务逻辑被合理分配到不同分片,而不是所有写请求都集中到某个热点分片。
- 长尾:某些查询或写入操作花费时间过长,导致延迟累积,影响整体性能
- 慢查询分析:showlog
- 索引优化:doc_values
- 查询重构:将深度嵌套查询改为多次请求、适当使用过滤器而非
full-text
查询。 - 分片优化:防止某些查询集中在单一分片上造成长尾现象。分片过少会导致查询集中,分片过多会引入开销。
- 异步查询