仓库链接:https://gitee.com/setekh/search-engine
介绍 📖
Linux平台下使用C++实现的简单搜索引擎 Spark Search

Spark Search 在 2核 4G 华为云 Flexus L实例 上进行部署和测试,能够在资源受限的环境中高效运行。
功能特性 ✨
Spark Search 是一个高效、智能、易用的搜索引擎,能够满足各种搜索需求,同时具备高性能和高可靠性,具有以下主要特性:
关键词推荐
- 智能推荐:用户输入关键词后,系统会根据离线词典生成相应的推荐词。目前使用最小编辑距离算法实现关键词推荐,帮助用户快速找到相关内容。
- 大模型推荐:引入大模型(KeyBert)进行关键词推荐,通过上下文理解生成更为精准和相关的推荐词,进一步提升用户体验。
高效网页查询
- 真实搜索引擎功能:支持类似于真实搜索引擎的网页查询功能。用户可以进行页面跳转,根据查询关键词生成动态摘要,高亮关键词,并可直接点击链接跳转到文章来源站点。
数据库与缓存
- MySQL 持久化存储:服务端数据库模块使用 MySQL 持久化存储倒排索引库和网页内容库,确保数据的长期保存和管理。
- Redis 缓存:使用 Redis 对查询时所需的倒排索引库和文章内容信息进行定期缓存,并设计了一定时间范围内随机设置有效期以避免缓存雪崩,提高查询效率。
查询优化
- 数据库连接池和线程局部存储:引入了数据库连接池和线程局部存储(Thread-Local Storage,TLS),在提高查询效率的同时简化了代码,实现高并发环境下的高效查询。
网络通信
- Reactor 模型:服务端 Tcp 网络通信模块使用 Reactor 模型,实现高效的 I/O 多路复用,支持高并发连接。
- 自定义通信协议:通信协议使用 json 封装的自定义格式,确保数据传输的高效和可靠。
用户体验
- 动态摘要生成:根据用户查询的关键词,动态生成摘要内容,并高亮显示关键词,提升用户的搜索体验。
- 页面跳转:搜索结果提供直接的链接跳转功能,用户可以方便地访问原始文章内容。
架构概览 🏛️
高层次介绍项目的架构,包括主要组件及其交互方式。
项目文件夹结构 📂
本节将简单介绍 Spark Search 项目的文件夹结构及各文件夹的用途,帮助您快速了解本项目组织方式。
.
├── bin # 可执行文件目录
├── build # CMake
├── code # 源代码目录
│ ├── include # 公共头文件目录
│ │ ├── helper # 辅助类
│ │ ├── splittool # 分词工具
│ │ └── utils # 通用工具
│ ├── lib # 静态和动态库目录
│ ├── project # 项目模块代码
│ │ ├── offline_database # 离线数据库相关代码
│ │ ├── offline_dict # 离线词典相关代码
│ │ ├── offline_page # 离线页面处理相关代码
│ │ ├── online_search # 在线搜索相关代码
│ │ └── reactor # Reactor 模型相关代码
│ └── third-party # 第三方库
├── config # 配置文件目录
├── docs # 项目文档目录
├── logs # 日志文件目录
├── resources # 资源文件目录
│ ├── corpus # 语料库
│ │ ├── cn_art # 中文文章语料库
│ │ └── en_art # 英文文章语料库
│ ├── data # 数据文件
│ ├── dict # 词典文件
│ │ ├── pos_dict # 词性词典
│ │ └── stop_words # 停用词列表
│ └── pages # 页面语料文件
│ ├── large # 大型网页语料
│ └── small # 小型网页语料
├── test # 测试代码和测试用例目录
└── tools # 工具目录
├── FlameGraph # FlameGraph 工具
└── perf # perf 工具
Qt 客户端 💻
Qt 实现的简单通信客户端:
- 原版设计来自组员 海纳百川 👉 https://gitee.com/hatomugi/search-engine
- 高分辨率电脑优化 👉 https://gitee.com/setekh/search-engine-qtcp-client




使用说明 📜
项目涉及到的第三方库 📦
- 部分第三方库已经存放在
code/third-party
文件夹内tinyxml2
xml文件解析库,已编译成静态库spdlog
日志库,已编译成静态库cppjieba
中文分词库nlohmann/json
json解析库simhash
google用于进行文本去重的算法,使用jenkins
作为hash函数fmt
文本格式化输出库头文件,spdlog
库中也有内置的该库
- Redis 数据库相关
redis
sudo apt-get install redis-server
hiredis
sudo apt-get install libhiredis-dev
redis++
git clone https://github.com/sewenew/redis-plus-plus.git cd redis-plus-plus mkdir build cd build cmake .. -DCMAKE_BUILD_TYPE=Release make sudo make install
- MySQL 数据库相关
mysql
sudo apt-get install mysql-server
MySQL Connector/C++
sudo apt-get install libmysqlcppconn-dev
- 编译速度优化
ccache
bash sudo apt-get install ccache
安装步骤 🚀
- 克隆项目
git clone https://gitee.com/setekh/search-engine cd search-engine
- 安装依赖
确保你已经安装了所有必要的第三方库(参考上面的安装指令)。 - 编译项目
mkdir build cd build cmake .. make
- 根据环境修改配置文件
所有项目配置文件中的相对路径都是相对于bin文件夹下- logger_config.json 日志系统设置
- split_tool_config.json 分词工具设置
- dict_config.json 离线词典生成设置
- pagelib_config.json 网页库生成设置
- online_config.json 在线搜索引擎设置
- 运行项目
bash cd ../bin ./SparkSearch
火焰图生成教程 🔥
为了分析程序性能并发现瓶颈,可以生成火焰图。以下是生成火焰图的步骤:
- 安装 perf 和 FlameGraph 工具 🛠️
sudo apt-get install linux-tools-common linux-tools-generic
git clone https://github.com/brendangregg/FlameGraph.git
- 自动化脚本使用教程 🚀
为了简化火焰图的生成过程,已经提供了一个自动化生成火焰图的脚本,位置在tools/perf/generate_flamegraph.sh
,使用前请修改目录:
# 定义目录
BIN_DIR="/home/setekh/code/search-engine/bin"
PERF_DIR="/home/setekh/code/search-engine/tools/perf"
FLAMEGRAPH_DIR="/home/setekh/code/search-engine/tools/FlameGraph"
- 火焰图将生成在 flamegraph.svg 文件中,可以使用浏览器打开查看。
Doxygen文档生成 📊
- 下载自定义主题 doxygen-awesome-css 🥰 https://github.com/jothepro/doxygen-awesome-css
- 生成引用关系图、函数调用关系图等需要额外安装 graphviz
sudo apt-get install doxygen graphviz
- 执行
doxygen
指令生成文档,文章存储在docs
文件夹内cd ./tools doxygen Doxyfile
数据库设计 🗄️
本项目使用 Redis 和 MySQL 作为数据存储,以支持高效的搜索和内容管理。以下是数据库的设计和相关说明。
Redis 缓存设计
Redis 用于缓存倒排索引和文章内容信息,以加快搜索速度。
- 倒排索引缓存:
- 键:
invert_index:<关键词>
- 值:格式为
文章id,tfidf,文章id,tfidf,...
,例如:52,0.030392
缓存时间设置为10~15min 示例:
invert_index:中国 -> 52,0.030392
- 文章内容缓存:
- 文章内容:
- 键:
doc:<docid>:content
- 值:
文章内容
- 键:
- 文章链接:
- 键:
doc:<docid>:url
- 值:
文章链接
- 键:
- 文章标题:
- 键:
doc:<docid>:title
- 值:
文章标题
- 键:
doc:38:content -> 文章内容
doc:38:url -> 文章链接
doc:38:title -> 文章标题
MySQL 数据库设计
MySQL 用于持久化存储倒排索引和文章内容信息,以确保数据的完整性和可管理性。
- 倒排索引表:
- 表名:
inverted_index
- 字段:
word
:关键词docids
:包含关键词的文章 ID 列表tfidfs
:对应文章的 tf-idf 值列表
- 文章内容表:
- 表名:
pages
- 字段:
docid
:文章 IDtitle
:文章标题url
:文章链接content
:文章内容
通信协议 📡
本项目的通信协议使用 JSON 封装自定义格式,主要用于关键词推荐和网页查询功能。以下是具体的通信协议说明。
网页查询格式
请求格式
query_id
:1 表示关键词推荐, 2 表示网页查询pageNum
:当前请求查询的页数,点击上一页或下一页的时候会发送新请求itemsPerPage
:客户端每页所请求的网页数量
请求示例:
{
"query_id": 2,
"msg": "人性化CNNIC",
"pageNum": 10,
"itemsPerPage": 5
}
响应格式
msgID
:与query_id
对应,1 表示关键词推荐, 2 表示网页查询maxPage
:用于设置客户端查询页码上限queryWords
:返回查询消息的分词结果,用于客户端高亮关键词files
:存储文章标题、动态摘要和 URL 信息
响应示例:
{
"msgID" : 2,
"maxPage": 3,
"queryWords" : [
"人性化",
"CNNIC"
],
"files": [
{
"title": "404, not found",
"summary": "未找到你搜索的内容",
"url": ""
}
]
}
关键词推荐格式
请求格式
请求示例:
{
"query_id": 1,
"msg": "keyWord"
}
响应格式
响应示例:
{
"msgID" : 1,
"msg": [
"keyWord1",
"keyWord2",
"keyWord3"
]
}
项目目前存在的问题 🛠
- 编译速度:引入
spdlog
库后,代码编译速度大幅降低。这可能是由于该库的复杂性和模板使用所导致的。 - 关键词推荐:在线关键词推荐使用简单的最小编辑距离算法,推荐的关键词之间并无语义关联,导致推荐的相关性较低。
- 代码冗余:在线网页查询模块涉及数据库操作部分的代码逻辑存在冗余,增加了维护和扩展的难度。
- 日志打印:部分关键模块缺少日志打印功能。由于
spdlog
的编译速度慢,当前尽可能避开了该库的使用。 - 词典不足:用于生成词典的语料可能过少,尤其是英文相关的检索和推荐性能不佳,影响了系统的整体效果。
- 性能测试:缺少压测过程来明确服务端性能瓶颈,无法准确评估系统在高并发情况下的表现。
- 字符串操作:涉及大量字符串操作,从火焰图中可以看到大量 CPU 消耗在创建和复制
string
上,可能需要优化不必要的复制操作。
未来计划与改进 🌟
- 编译优化🚀:
- 优化
spdlog
的使用,研究使用更高效的编译选项或替代方案,减少编译时间。 - 引入预编译头文件以加速编译过程。
- 改进关键词推荐🔍:
- 引入更先进的算法,如基于 Word2Vec 或 BERT 的语义关联推荐,提升推荐的相关性和智能性。
- 增加语料库的数量和多样性,特别是英文语料,提升推荐效果。
- 重构代码结构🛠:
- 优化在线网页查询模块的数据库操作代码逻辑,消除冗余,提升代码可维护性和性能。
- 增加代码模块化程度,简化代码结构。
- 加强日志管理📑:
- 重新评估日志框架,选择性能和编译速度均衡的日志库。
- 增加关键模块的日志打印,提升系统的可监控性和可调试性。
- 增强词典构建📚:
- 扩展用于生成词典的语料库,增加多语言支持,提升搜索引擎在多语言环境下的表现。
- 使用爬虫技术定期更新语料库,保持词典的时效性和准确性。
- 性能测试与优化⚙️:
- 开展系统的压测,找出性能瓶颈,并针对性地进行优化。
- 采用性能分析工具,进一步优化 CPU 和内存的使用。
- 优化字符串操作🔧:
- 减少不必要的字符串复制和创建,使用更高效的数据结构和算法。
- 研究使用
std::string_view
等现代 C++ 技术,减少内存分配和拷贝。
感谢 🙏
特别感谢以下组员在项目开发过程中所做的贡献:
感谢大家的共同努力,使 Spark Search 成为一个高效、智能、易用的搜索引擎!
许可证 📄
该项目使用 MIT 许可证。详情请参阅 LICENSE。
联系方式 ✉️
如果你有任何问题或建议,请通过以下方式联系我们:
- 邮箱:756435658@qq.com
- 个站:https://blog.setekh.fun/
- Gitee:https://gitee.com/setekh
感谢你对 Spark Search 的支持! 🎉
Comments NOTHING