当前位置: 首页 > news >正文

【Elasticsearch】es初识,在项目架构中的用途,与mysql和kafka的配合使用,

ES是一个开源的高扩展的分布式全文检索引擎

在项目已有mysql增删改查的情况下,新增kafka,es流程

用户新增/修改商家(写MySQL)
↓
Kafka 生产者发送商家数据消息
↓
Kafka 消费者监听消息 → 写入 Elasticsearch
↓
前端搜索商家时 → 查询 Elasticsearch(不是 MySQL)

这个 Kafka + Elasticsearch 的写入同步 + 搜索解耦架构 是目前绝大多数中大型互联网企业的标准做法


一、为什么不能只查 MySQL而引入es查询?

传统做法的问题:

比如你在前端搜索商家名称“李大壮”,如果查的是 MySQL:

SELECT * FROM merchant WHERE name LIKE '%李大壮%' OR description LIKE '%李大壮%' LIMIT 10;

问题:

  • :LIKE + 多字段模糊查询在数据量大时性能非常差;
  • 不智能:MySQL 的模糊匹配不支持分词、不支持排序打分;
  • 不灵活:无法实现“相关度排序”“拼音搜索”“短语匹配”等搜索场景。

所以,企业通常引入 Elasticsearch(简称 ES)来替代 MySQL 作为 搜索引擎


二、为什么 MySQL 改动不直接同步到 Elasticsearch,而是先发 Kafka?

这是你最关键的问题:为什么加一层 Kafka?

原因一:解耦系统,避免写 ES 出错影响主业务

  • 如果你直接在写 MySQL 后同时写 ES,那么:

    • 如果 ES 挂了、网络抖动、接口异常等,会导致整个商家创建流程失败;
    • Kafka 相当于消息缓冲器 + 解耦层,即便 ES 挂了,Kafka 消息还能继续收集,等恢复后继续消费。

原因二:可支持异步、并发、大吞吐处理

  • Kafka 是高吞吐分布式系统,支持水平扩展(通过分区);
  • 消费者可以并行处理,批量写入 ES,系统更加稳定、可扩展。

原因三:可拓展更多下游系统,不只是 Elasticsearch

未来你可能还需要这些:

  • 同步商家数据到 Redis 缓存(做秒级展示);
  • 触发推送服务(比如新商家上线通知);
  • 同步用户画像系统、数据仓库。

如果有 Kafka,你只需要新增一个消费者;
如果没有 Kafka,你要改源代码、逻辑复杂,非常不利于维护。


三、流程总结:企业为什么这样做?

阶段系统作用
1MySQL业务主库,负责存储真实、结构化的数据
2Kafka消息中间件,做异步解耦、缓冲和流式处理
3Elasticsearch专用于搜索,支持全文检索、相关度评分等搜索功能
4前端直接查 ES,提升搜索速度、支持搜索功能增强

四、图示结构(简化):

      用户操作前端↓后端写 MySQL(商家表)↓┌────→ Kafka ←────┐│                 │Kafka Consumer     │(可以多个系统消费)↓                 ↓
ElasticSearch     Redis/OLAP等其他系统↓
前端搜索

es查询使用案例

query := map[string]interface{}{// DSL 查询主体"query": map[string]interface{}{"bool": map[string]interface{}{ // bool 组合查询(企业中常用)"must": []interface{}{ // must 表示“必须匹配”的条件,全部满足才返回map[string]interface{}{"multi_match": map[string]interface{}{ // 多字段模糊匹配"query":  in.Keyword, // 用户输入的搜索关键词(如“口腔”)"fields": []string{"name", "business", "address"},"type":   "most_fields", // type: most_fields → 各字段各自打分后相加,适合字段内容差异大;另一个选项 cross_fields 更适合字段语义接近。},},},"filter": filters, // 精准过滤器(如按省市区筛选,不能容忍模糊匹配)"should": []interface{}{ // 加分项,提升命中相关性map[string]interface{}{"match_phrase": map[string]interface{}{ "name": in.Keyword, // 要求关键词“完整连续地”出现在 name 中才能加分(如“牙科诊所”)},},map[string]interface{}{"match_phrase": map[string]interface{}{"business": in.Keyword, // business 完整短语匹配},},},// 注:should 不设置 minimum_should_match 时,不满足不会过滤掉,只是不加分},},// 分页设置"from": (in.Page - 1) * in.PerPage, // 从第几条开始取数据(起始位置)"size": in.PerPage,                // 每页返回多少条// 排序设置"sort": []interface{}{map[string]interface{}{"order_score": "desc", // 业务字段排序:order_score 是你在 merchant 映射里定义的字段,值越大代表权重越高。// 通常用于控制:优质商家排前面(如人工打分、运营配置)},},
}// -----------------
// 构造查询DSL// DSL:Domain-Specific Language(领域特定语言)// 这里表示一段用于构建或解析 Elasticsearch 查询语句的逻辑query := map[string]interface{}{"query": map[string]interface{}{"bool": map[string]interface{}{"must": []interface{}{map[string]interface{}{"multi_match": map[string]interface{}{ // multi_match 该字段使得查询支持不同类型的匹配模式// type 参数控制多字段匹配的方式,主要有两种:"query":  in.Keyword,"fields": []string{"name", "business", "address"},"type":   "most_fields", // 1.most_fields:把多个字段匹配结果 分开 算分,最后相加// 2.cross_fields:把多个字段 和在一起 匹配(适合同一个词,可能出现在name和business这种的情况)// 分数(score):Elasticsearch内部计算的相关度分值,用于衡量文档与查询的匹配程度,// 数值越大说明匹配越好,搜索结果排序默认会根据这个分数降序排列。},},},"filter": filters,// 其中should字段,主要作用是在满足上述条件下,增加相关度,缩小搜索范围。"should": []interface{}{ // should:表示“或”关系,满足should中条件的文档会被加分,提高其相关度排序,// 但文档不一定非要满足should中的条件才能匹配整个查询(除非设置minimum_should_match)。// 下面2map的效果:如果传入的name和business是能完全匹配的,则会获得更高的相关度评分。map[string]interface{}{"match_phrase": map[string]interface{}{ // match_phrase 是短语匹配,要求查询词,是顺序的不拆分的,否则匹配失败。"name": in.Keyword,},},map[string]interface{}{"match_phrase": map[string]interface{}{"business": in.Keyword,},},},},},"from": (in.Page - 1) * in.PerPage,"size": in.PerPage,"sort": []interface{}{ // 按照评分排序map[string]interface{}{"order_score": "desc"}, // 降序},}

https://github.com/0voice

http://www.xdnf.cn/news/1068463.html

相关文章:

  • linux安装docker
  • LE AUDIO---Chapter 2. The Bluetooth® LE Audio architecture
  • 记一次AWS 中RDS优化费用使用的案例
  • 【学习笔记】3.3 Decoder-Only PLM
  • 【目标检测】平均精度(AP)与均值平均精度(mAP)计算详解
  • 从数据到决策:UI前端如何利用数字孪生技术提升管理效率?
  • list的使用和模拟实现
  • 探索解析C++ STL中的 list:双向链表的高效实现与迭代器
  • Flutter MobX 响应式原理与实战详解
  • OpenLayers 上传Shapefile文件
  • docker start mysql失败,解决方案
  • 【猜你需要】使用了Git LFS还是无法上传文件?文件过大?
  • 打造丝滑的Android应用:LiveData完全教程
  • 【启发式算法】RRT*算法详细介绍(Python)
  • Oracle 数据库查询:多表查询
  • 测试平台ui自动化demo说明
  • [论文阅读] 人工智能 + 软件工程 | 探秘LLM软件代理:从黑箱决策到透明轨迹分析
  • 创客匠人 AI 赋能:创始人 IP 打造的效率革命与信任重构
  • 数的范围(连续数字边界)
  • 以太网基础②RGMII 与 GMII 转换电路设计
  • Spring Boot 系统开发:打造高效、稳定、可扩展的企业级应用
  • 学习日记-spring-day37-6.25
  • SpringCloud系列(35)--使用HystrixDashboard进行服务监控
  • OSS跨区域复制灾备方案:华东1到华南1的数据同步与故障切换演练
  • 数智时代如何构建人才培养生态?生成式人工智能(GAI)认证,引领数智时代人才培养新方向
  • Kafka如何保证消息可靠?
  • 计算机网络期末复习
  • Linux操作系统Nginx Web服务
  • JVM(12)——详解G1垃圾回收器
  • 多模态大模型(从0到1)