it编程 > 数据库 > Mysql

一文详解为什么用ElasticSearch以及和传统数据库MySQL有什么区别

17人参与 2025-07-17 Mysql

elasticsearch 深度解析:从原理到实践

一、为什么选择 elasticsearch?

数据模型
elasticsearch 是基于文档的搜索引擎,它使用 json 文档来存储数据。在 elasticsearch 中,相关的数据通常存储在同一个文档中,而不是分散在多个表中。

mysql 是一个关系型数据库管理系统,它使用表、行和列的结构来组织数据。数据通过外键关系分散在多个表中。

查询语言
elasticsearch 使用 query dsl(domain specific language),这是一种非常灵活的查询语言,基于 json,支持全文搜索、复合查询、过滤以及聚合等。

mysql 使用 sql(structured query language),这是一种强类型和非常成熟的语言,专门用于查询和管理关系数据库。

全文搜索
elasticsearch 的核心功能是全文搜索。
它对数据进行索引时会自动建立全文搜索索引,使其在搜索大量文本数据时表现优异。

mysql 虽然也提供了基本的全文搜索功能,但其主要设计目标是处理结构化数据的存储和查询,对全文搜索的支持不如 elasticsearch 那样强大。

事务支持
elasticsearch 不支持传统的 acid(原子性、一致性、隔离性、持久性)事务。虽然它确保了单个文档操作的原子性,但不适用于跨多个文档的复杂事务。虽然 elasticsearch 不支持传统的事务,但是他是可以确保单个文档的更改(如创建、更新、删除)是原子性的。这意味着任何文档级的操作都完整地成功或完整地失败,但不保证跨多个文档或操作的一致性。

mysql 支持 acid 事务,这使得它非常适合需要严格数据一致性的应用,如金融服务和其他商业数据处理。

支持乐观锁:

elasticsearch 支持通过使用文档版本控制来实现乐观锁。

6.7之前。在 es 中,每个文档存储时都有一个 _version 字段,这个版本号在每次文档更新时自动增加。当我们执行更新、删除或者使用脚本处理文档时,可以指定这个版本号来确保正在操作的文档是预期中的版本。如果操作中的版本号与存储在索引中的文档版本号不一致,说明文档已被其他操作更改,当前操作将会失败。(cas)

为什么_version在后续版本被抛弃

_version 机制是基于单一递增整数,它主要适用于简单的冲突检测,但在复杂的分布式系统中,仅依靠版本号可能无法准确地反映数据的历史和复制状态。尤其是在发生网络分区或节点故障时,仅凭 _version 可能导致数据丢失或过时的数据被错误地写入。

主要还是高并发和高可用的环境下,单一的-version不足以处理因节点故障网络问题导致的多个副本之间的数据不一致问题。

然而if_seq_no 和 if_primary_term这两个参数可以更准确地确定操作是否应当被执行,可以跟踪每个文档变更的序列号主分片的期限。这种机制帮助确保即使在集群状态发生变化(如分片重新分配到新的节点)的情况下,也不会应用基于过时副本的更新。它有效地防止了脑裂问题

6.7之后,使用 _version 关键字进行乐观锁已经被废弃了,替代方法是使用

if_seq_no (是一个递增的序列号,表示文档的每次修改)和

if_primary_term(表示主分片的当前任期,每当主分片发生变化时,这个值会增加。) 

来指定版本。

1. 核心优势()

维度elasticsearchmysql
数据模型文档型(json),动态映射关系型(严格schema)
搜索能力全文检索、模糊匹配、语义分析仅支持精确查询和简单like
扩展性分布式架构,自动分片/副本分库分表复杂
吞吐量单集群支持每秒10万+查询高并发写入更优
一致性最终一致性(近实时)强一致性(acid)

elasticsearch是一个开源的分布式搜索和分析引擎,主要适用于以下场景:

1:搜索引擎:用于快速检索文档、商品、新闻等。

2:日志分析:通过分析日志数据,帮助企业了解其业务的性能情况。

3:数据分析:帮助数据科学家和数据分析师进行数据分析,以获取有价值的信息。

4:商业智能:帮助企业制定数据驱动的决策,以实现商业上的成功。

5:实时监控:帮助企业实时监测系统性能、监控数据变化,以保证系统正常运行。

6:安全性:帮助企业保证数据的安全性,保证数据不被非法窃取。

7:应用程序开发:帮助开发人员开发基于搜索的应用程序,以增加用户体验。

elasticsearch具有以下几个优势:

1:高性能:elasticsearch具有高性能的搜索和分析能力,其中涵盖了多种查询语言和数据结构。

2:可扩展性:elasticsearch是分布式的,可以通过增加节点数量扩展搜索和分析能力。

3:灵活性:elasticsearch支持多种数据类型,支持多种语言,支持动态映射,允许快速地调整模型以适应不同的需求。

4:实时分析:elasticsearch支持实时分析,可以对数据进行实时查询,这对于快速检索数据非常有用。

5:可靠性:elasticsearch具有可靠性和高可用性,支持数据备份和恢复。

es为什么块:

1:分布式存储:elasticsearch使用分布式存储技术,将数据存储在多个节点上,从而减少单个节点的压力,提高整体性能。

2:索引分片:elasticsearch把每个索引划分成多个分片,这样可以让查询操作并行化,从而提高查询速度。

3:全文索引:elasticsearch使用了高效的全文索引技术,把文档转化成可搜索的结构化数据,使得搜索操作快速高效。

4:倒排索引:elasticsearch支持倒排索引这种数据结构,倒排索引将文档中的每个词与该词出现在哪些文档中进行映射,并存储这些信息。当搜索请求发生时,es可以快速查找包含所有搜索词的文档,从而返回结果。

5:索引优化:elasticsearch通过索引优化技术,可以使查询速度更快。例如,它支持索引覆盖、索引下推等优化技术,使得查询速度更快。

6:预存储结果:elasticsearch在插入数据时,对数据进行预处理,把结果预存储到索引中,从而在查询时不需要再重新计算,提高查询速度。

7:高效的查询引擎:elasticsearch使用了高效的查询引擎,支持各种类型的查询,并对复杂查询提供了优化策略,从而提高查询速度。

8:异步请求处理:es使用了异步请求处理机制,能够在请求到达时立即返回,避免长时间的等待,提高用户体验。

9:内存存储:es使用了内存存储技术,能够在读写数据时大大减少磁盘访问次数,提高数据存储和查询效率。

我觉得最重要就是倒排索引了:它 用于快速搜索文档中的某个词汇。

假设我们有一个原始文档:

文档id文档内容
doc1"elasticsearch is fast"
doc2"redis is fast too"
doc3

"elasticsearch and redis"

主要分为俩个过程:

分词(tokenization)

  • doc1 → ["elasticsearch", "is", "fast"]

  • doc2 → ["redis", "is", "fast", "too"]

  • doc3 → ["elasticsearch", "and", "redis"]

生成词项-文档映射

term            docids (postings list)
─────────────────────────────────────
"and"           → [doc3]
"elasticsearch" → [doc1, doc3]
"fast"          → [doc1, doc2]
"is"            → [doc1, doc2]
"redis"         → [doc2, doc3]
"too"           → [doc2]

2. 倒排索引的核心组件

组件作用示例
词项字典(term dictionary)存储所有唯一词项,通常用 fst(有限状态转换器) 压缩存储"elasticsearch", "redis"
倒排列表(postings list)记录包含该词项的文档id及位置信息(支持快速跳表skiplist优化遍历)doc1:[pos1,pos2], doc3:[pos1]
词频(tf)词项在文档中的出现次数(用于相关性评分)"fast"在doc1中tf=1
文档频率(df)包含该词项的文档数(用于idf计算)"elasti

倒排索引的优化技术

  1. 压缩存储

    • fst:压缩词项字典,减少内存占用。

    • delta encoding:对文档id差值编码(如[100, 102, 105]→[100, +2, +3])。

  2. 跳表(skiplist)

    • 加速倒排列表的合并操作(如and查询)。

  3. 多级索引

    • 内存中保留热点词项,磁盘存全量数据。

二、elasticsearch 核心技术细节

1. 分词器(analyzer)

分词器类型功能说明示例
standard默认分词器,按空格/标点切分"elasticsearch" → ["elasticsearch"]
ik analyzer中文分词(社区版+扩展词典)

ik分词器有几种模式?

  • ik_smart:智能切分,粗粒度
  • ik_max_word:最细切分,细粒度

ik分词器如何拓展词条?如何停用词条?

  • 利用config目录的ikanalyzer.cfg.xml文件添加拓展词典和停用词典
  • 在词典中添加拓展词条或者停用词条
"华为手机" → ["华为", "手机"]
pinyin中文转拼音搜索"北京" → ["beijing", "bj"]
whitespace仅按空格切分"hello world" → ["hello", "world"]
keyword不分词,整体作为term"2023-08-15" → ["2023-08-15"]

自定义分词器

put /my_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_ik": {
          "type": "custom",
          "tokenizer": "ik_max_word",
          "filter": ["lowercase"]
        }
      }
    }
  }
}

2. 底层原理

3. 查询高效的原因

4. 增删改操作

三、关键问题解决方案

1. 深度分页优化

2. 数据一致性

第一种方法:双写一致性

对mysql和es进行双写,先更新数据库,再更新es,放在一个事务里面,需要保证事务的一致性。有数据不一致的风险,比如mysql写入成功,但是es发生了写入成功但因为超时抛异常了就会出现数据不一致的情况。

第二种方法:使用消息队列mq进行处理

在更新数据库时,发送一个消息到mq中,然后数据库和es各设置一个监听者,监听消息之后各自去做数据变更,如果失败了就基于消息的重试在重新执行。

好处是进行了异步解耦,性能稍后,但是有延迟

第三种方法:定时扫描mysql

如果es中的数据变更的实时性要求不高,可以考虑定时任务扫表来批量更新es。

这个方案优点是没有侵入性,数据库的写操作处不需要改代码。

缺点是实时性很差,并且轮询可能存在性能问题、效率问题以及给数据库带来压力。

第四种方法:监听binlog日志(基于canal做数据同步的方案)

对业务代码完全没有侵入性,业务也非常解耦,不需要关心这个es的更新操作。

缺点就是需要基于binlog监听,需要引入第三方框架。存在一定的延迟。

一致性级别实现方案优缺点
强一致性写入后立即refresh(性能差)数据最新,吞吐量下降
最终一致性默认1秒刷新 + 手动_refresh(平衡选择)性能高,短暂延迟

与canal集成:主要的过程

  1. mysql binlog → canal server 解析变更。

  2. canal client → kafka 发送变更事件。

  3. logstash/自定义consumer → 写入es

关于logstash和自定义consumer

. logstash 是什么?

canal → es 场景中的用途

将 canal 发送到 kafka 的 mysql binlog 数据转换为 es 所需的格式,并写入 es。

 自定义 consumer 是什么?

整体架构流程:

3. es支持的数据结构

五种方法:

一:使用字符串类型(比较好用)

完全保留数字的精度。简单易于实现,数据迁移时不需特别处理。但是作为字符串存储的数字不能直接用于数值比较或数学运算,需要在应用层处理转换。但也不是什么大毛病。

二:扩大浮点类型的精度

就是直接使用 double 类型,在理论上可能会有精度损失,但实际上 double 类型提供的精度对于许多业务需求已经足够使用。需要接受减小精度损失。

三:使用scaled_float(推荐)

elasticsearch 的 scaled_float 类型是一种数值数据类型,专门用于存储浮点数。其特点是通过一个缩放因子(scaling factor)将浮点数转换为整数来存储,从而在一定范围内提高存储和计算的效率。他使用一个缩放因子将浮点数转换为整数存储。例如,如果缩放因子是 100,那么值 123.45 会存储为 12345。这样可以避免浮点数存储和计算中的精度问题。

四:使用多个字段

在某些情况下,可以将 decimal 数值拆分为两个字段存储:一个为整数部分,另一个为小数部分。这样做可以在不丢失精度的情况下,将数值分开处理。可以保持数值精确,同时可进行部分数学运算。但是增加了数据处理的复杂性,需要在应用层重建数值。

五:使用自定义脚本

用 elasticsearch 的脚本功能(如 painless 脚本)来处理数值计算,确保在处理过程中控制精度。优点:灵活控制数据处理逻辑。缺点:可能影响查询性能,增加系统复杂性。

四、实际应用场景

1. 电商搜索

{
  "query": {
    "bool": {
      "must": [
        { "term": { "brand": "华为" } },
        { "range": { "price": { "gte": 1000, "lte": 2000 } } }
      ],
      "filter": { "term": { "color": "红色" } }
    }
  },
  "aggs": {
    "price_stats": { "stats": { "field": "price" } }
  }
}

2. 日志告警

3. 数据同步容灾

五、性能调优

集群和硬件优化

负载均衡: 确保查询负载在集群中均衡分配。

硬件资源: 根据需要增加 cpu、内存或改善 i/o 性能(例如使用 ssd)。

配置 jvm: 优化 jvm 设置,如堆大小,以提高性能。

总结

到此这篇关于为什么用elasticsearch以及和传统数据库mysql有什么区别的文章就介绍到这了,更多相关es和mysql对比内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

您想发表意见!!点此发布评论

推荐阅读

MYSQL中慢SQL原因与优化方法详解

07-17

虚拟机Centos7安装MySQL数据库实践

07-17

MySQL中比较运算符的具体使用

07-17

MySQL中WITH ROLLUP的具体使用

07-17

Zabbix在MySQL性能监控方面的运用及最佳实践记录

07-16

MySQL 的ANALYZE与 OPTIMIZE命令(最佳实践指南)

07-16

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论