网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化资料的朋友,可以戳这里获取
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
热门搜索词
热门搜索词主要来源用户搜索,目前场景比较简单,每天定时任务统计N天前的用户搜词词频,按搜索频次降序排序,存储到MySQL或者redis中。
但这种方法可能存在问题,热搜词没有时间权重衰减, 例如:一个关键词10天前搜索了101次,昨天搜索了100次,10天前的词还能继续排在昨天的热词前面吗? 因此需要设计一个热词衰减权重,搜索时间越长热度权重应该相应的衰减。
联想搜索词
联想搜索需要在用户输入关键词时,联想用户可能想要搜索的词,该功能需要解决2个问题:
- 关联词来源
- 关联词方式
关联词来源可以通过用户搜索关键词记录来提取。
技术选择可以根据业务和当前的系统环境来判断:
- 尽量不重复造轮子;
- 使用已有、成熟的、开源的技术栈;
- 能满足需求,成本低、技术可控。
搜索存储引擎目前最成熟活跃的方案非 莫属,我们的系统基于腾讯云框架搭建,业务数据存在在腾讯云的中,因此搜索业务全文检索计划使用腾讯云最新版本的。
es配置选择
文档转换工具选择
我们的需求里面需要将不同类型的文档转换为纯文本,这里有几个开源的实现方案:
我结合自身业务的情况,选了上面4种之外的方法,我们文档存储在,直接调用`腾讯云API转html 或者text文档:文档转 HTML
如果没有使用腾讯云我这边推荐使用`FsCrawler, 可参考我之前的博文。
数据传输选型
同步工具选型
同步工具开源方案目前最活跃的应该是阿里巴巴开源的canal ,可以看官网的原理介绍
- MySQL主备复制原理:
- MySQL master 将数据变更写入二进制日志( binary log, 其中记录叫做二进制日志- 事件binary log events,可以通过 show binlog events 进行查看)
- MySQL slave 将 master 的 binary log events 拷贝到它的中继日志(relay log)
- MySQL slave 重放 relay log 中事件,将数据变更反映它自己的数据
- canal 工作原理
- canal 模拟 MySQL slave 的交互协议,伪装自己为 MySQL slave ,向 MySQL master 发送dump 协议
- MySQL master 收到 dump 请求,开始推送 binary log 给 slave (即 canal )
- canal 解析 binary log 对象(原始为 byte 流)
#mermaid-svg-CDPtMmuPvv8JTgZj {font-family:“trebuchet ms”,verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-CDPtMmuPvv8JTgZj .error-icon{fill:#552222;}#mermaid-svg-CDPtMmuPvv8JTgZj .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-CDPtMmuPvv8JTgZj .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-CDPtMmuPvv8JTgZj .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-CDPtMmuPvv8JTgZj .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-CDPtMmuPvv8JTgZj .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-CDPtMmuPvv8JTgZj .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-CDPtMmuPvv8JTgZj .marker{fill:#333333;stroke:#333333;}#mermaid-svg-CDPtMmuPvv8JTgZj .marker.cross{stroke:#333333;}#mermaid-svg-CDPtMmuPvv8JTgZj svg{font-family:“trebuchet ms”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-CDPtMmuPvv8JTgZj .label{font-family:“trebuchet ms”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-CDPtMmuPvv8JTgZj .cluster-label text{fill:#333;}#mermaid-svg-CDPtMmuPvv8JTgZj .cluster-label span{color:#333;}#mermaid-svg-CDPtMmuPvv8JTgZj .label text,#mermaid-svg-CDPtMmuPvv8JTgZj span{fill:#333;color:#333;}#mermaid-svg-CDPtMmuPvv8JTgZj .node rect,#mermaid-svg-CDPtMmuPvv8JTgZj .node circle,#mermaid-svg-CDPtMmuPvv8JTgZj .node ellipse,#mermaid-svg-CDPtMmuPvv8JTgZj .node polygon,#mermaid-svg-CDPtMmuPvv8JTgZj .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-CDPtMmuPvv8JTgZj .node .label{text-align:center;}#mermaid-svg-CDPtMmuPvv8JTgZj .node.clickable{cursor:pointer;}#mermaid-svg-CDPtMmuPvv8JTgZj .arrowheadPath{fill:#333333;}#mermaid-svg-CDPtMmuPvv8JTgZj .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-CDPtMmuPvv8JTgZj .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-CDPtMmuPvv8JTgZj .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-CDPtMmuPvv8JTgZj .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-CDPtMmuPvv8JTgZj .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-CDPtMmuPvv8JTgZj .cluster text{fill:#333;}#mermaid-svg-CDPtMmuPvv8JTgZj .cluster span{color:#333;}#mermaid-svg-CDPtMmuPvv8JTgZj div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:“trebuchet ms”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-CDPtMmuPvv8JTgZj :root{–mermaid-font-family:“trebuchet ms”,verdana,arial,sans-serif;}
订阅binlog
读取kafka
写入kafka2
input来源于kafka2
输出到kafka1
腾讯云 DTS-kafka1
MySQL
dts适配
kafka2
logstash
Elasticsearch
架构图
搜索混排
注意:
- 可以配置不同数据源的评分权重(或者评分算法)以便优先要展示的结果;
- 需要记录不同数据源的偏移量和不同数据的查询结果,以便实现下次查询分页处理;
- 查询ES和查询私有云数据使用协程并行操作,等待2个结果共同返回处理。
另外你的第三方数据源没有存储在es数据库中,不能直接给出文档评分的,可以考虑以下混排方案:
翻页方案
由于要对2个数据源进行混排,要支持搜索跳页比较困难,因此在功能实现上目前只能支持上下翻页来实现
翻页计算公式
前端需要保存每一页es 和 api 两个数据源的偏移量:EsOffset 和 ApiOffset,可以使用对象数组保存 , 翻页计算公式如下:
- 当前页码计算公式:
- 上一页:将当前页码减1 : , 获取上一页页面缓存的上一页 EsOffset 和 ApiOffset
- 下一页: , , 获取下一页的EsOffset 和 ApiOffset
注意:查询到第一页时,可清空页面分页缓存数组对象,重新存储。
翻页举例说明
-
查询首页,假设没页显示20条数据
- 请求参数:EsOffset = 0,ApiOffset=0, PageSize=20
- 返回结果:
前端需要需要页面需要保存当前第一页页面的 和 , ,页面缓存数据:
-
继续查询下一页
- 请求参数:
- 返回结果:
- 前端继续缓存当前分页数据:
-
查询上一页
- 请求参数:当前页码减1
- 返回结果:与第一页一致
如果是查询第一数据,清空缓存数组,重新缓存当前分页数据。
权限处理
搜索权限需要满足根据用户权限过滤部分无权限的文档,以下是召回前处理和召回后处理权限的方案对比。
根据我的需求和场景,对性能要求较高,我们使用召回前过滤。如果希望简化查询过程,页可以考虑使用召回后过滤。
下面是在文档的权限格式,包含文档有权限的用户ID和部门ID
我们在设计索引mapping时
查询权限过滤参数:
搜索行为日志收集
需要满足用户搜索历史记录,首先需要收集用户搜索行为日志。
#mermaid-svg-RGDIHV3yG6IIeTHR {font-family:“trebuchet ms”,verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-RGDIHV3yG6IIeTHR .error-icon{fill:#552222;}#mermaid-svg-RGDIHV3yG6IIeTHR .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-RGDIHV3yG6IIeTHR .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-RGDIHV3yG6IIeTHR .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-RGDIHV3yG6IIeTHR .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-RGDIHV3yG6IIeTHR .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-RGDIHV3yG6IIeTHR .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-RGDIHV3yG6IIeTHR .marker{fill:#333333;stroke:#333333;}#mermaid-svg-RGDIHV3yG6IIeTHR .marker.cross{stroke:#333333;}#mermaid-svg-RGDIHV3yG6IIeTHR svg{font-family:“trebuchet ms”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-RGDIHV3yG6IIeTHR .label{font-family:“trebuchet ms”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-RGDIHV3yG6IIeTHR .cluster-label text{fill:#333;}#mermaid-svg-RGDIHV3yG6IIeTHR .cluster-label span{color:#333;}#mermaid-svg-RGDIHV3yG6IIeTHR .label text,#mermaid-svg-RGDIHV3yG6IIeTHR span{fill:#333;color:#333;}#mermaid-svg-RGDIHV3yG6IIeTHR .node rect,#mermaid-svg-RGDIHV3yG6IIeTHR .node circle,#mermaid-svg-RGDIHV3yG6IIeTHR .node ellipse,#mermaid-svg-RGDIHV3yG6IIeTHR .node polygon,#mermaid-svg-RGDIHV3yG6IIeTHR .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-RGDIHV3yG6IIeTHR .node .label{text-align:center;}#mermaid-svg-RGDIHV3yG6IIeTHR .node.clickable{cursor:pointer;}#mermaid-svg-RGDIHV3yG6IIeTHR .arrowheadPath{fill:#333333;}#mermaid-svg-RGDIHV3yG6IIeTHR .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-RGDIHV3yG6IIeTHR .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-RGDIHV3yG6IIeTHR .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-RGDIHV3yG6IIeTHR .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-RGDIHV3yG6IIeTHR .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-RGDIHV3yG6IIeTHR .cluster text{fill:#333;}#mermaid-svg-RGDIHV3yG6IIeTHR .cluster span{color:#333;}#mermaid-svg-RGDIHV3yG6IIeTHR div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:“trebuchet ms”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-RGDIHV3yG6IIeTHR :root{–mermaid-font-family:“trebuchet ms”,verdana,arial,sans-serif;}
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
需要这份系统化资料的朋友,可以戳这里获取
9%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-RGDIHV3yG6IIeTHR :root{–mermaid-font-family:“trebuchet ms”,verdana,arial,sans-serif;}
[外链图片转存中…(img-EfR5UhtP-1715615063586)]
[外链图片转存中…(img-SUe1qPHv-1715615063587)]
[外链图片转存中…(img-gJtfHxvM-1715615063587)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新