mysql 和 es 的一致性方案,你知道几个呢?

 

世上无难事只要肯放弃
 
面试的时候,经常会被问到:如何保证mysql  和  es 数据的一致性?
 
当然,也有其他的类似的问题,比如:
  • 如何保证 Mysql 和 es 数据一致性问题及方案?
  • 如果保证 Mysql 和 redis 数据一致性问题及方案?
  • 如果保证 Mysql 和 HBase 数据一致性?
  • 等等等等?

 

问题场景:生产需求上,为了便于商品的聚合搜索,高速搜索,采用两大优化方案:
  1. 把商品数据冗余存储在Elasticsearch中,实现高速搜索
  2. 把商品数据冗余存储在redis 中,实现高速缓存

 

很多时候,要求保持很高的数据一致性

  • 要求 mysql 与 es 做到秒级别的数据同步。
  • 要求 mysql 与 redis 做到秒级别的数据同步。

 

那要如何做呢?

 

方案一:同步双写

  同步双写是一种最为简单的方式,在将数据写到 MySQL 时,同时将数据写到 ES

优点:简单粗暴,实时写入能做到秒级。
缺点:

  • 业务耦合,这种方式代码侵入性强,商品的管理中耦合大量数据同步代码,要在之前写 mysql 的地方加写 es 的代码。以后写 mysql 的地方也要加写 es 的代码。
  • 影响性能,写入两个存储,响应时间变长,本来 MySQL 的性能不是很高,再加一个 ES,系统的性能必然会下降。
  • 不便扩展:搜索可能有一些个性化需求,需要对数据进行聚合,这种方式不便实现
  • 高风险:存在双写失败丢数据风险

 

方案二:异步双写

  同步操作性能低,异步性能高

异步双写分两种:

  • 使用内存队列(如阻塞队列)异步
  • 使用消息队列进行异步

 

使用内存队列(如阻塞队列)异步:

  先把商品数据写入DB后,然后把 数据写入 BlockingQueue 阻塞队列,消费线程异步从 drain 数据,batch 写入 ElasticSearch,保证数据一致性

 

使用消息队列进行异步:

 

异步双写优点:

  • 性能高;
  • 不易出现数据丢失问题,主要基于 MQ 消息的消费保障机制,比如 ES 宕机或者写入失败,还能重新消费 MQ 消息;
  • 多源写入之间相互隔离,便于扩展更多的数据源写入。

异步双写缺点:

  • 硬编码问题,接入新的数据源需要实现新的消费者代码;
  • 系统复杂度增加,引入了消息中间件;
  • MQ是异步消费模型,用户写入的数据不一定可以马上看到,造成延时。

 

方案三:定期同步

为了保证 DB和ES数据一致性,包括两个方面

  • 增量数据一致性
  • 全量数据一致性

 

优点:

  实现比较简单

缺点:

  • 实时性难以保证
  • 对存储压力较大

 

方案四:数据订阅

  如果要提高实时性,又要低入侵, 可以利用 MySQL 的 Binlog 来进行同步

  MySQL通过binlog订阅实现主从同步,canal Server 是一个伪装的slave节点,接收到binlog日志后,发送到MQ, 其他的 存储消费 MQ里边 的binlog日志,实现数据订阅。

这种方式和异步双写比较像,但是有两个优点

  • 第一降低了商品服务的入侵性
  • 第二数据的实时性更好

数据订阅框架的选型,主流的大体上是有:Canal、Maxwell、Python-Mysql-Rplication

具体的操作可以私下查阅

 

方案五:elt工具

  MySQL同步到Redis、MySQL同步到hbase、MySQL同步到es、或机房同步、主从同步等,都可以考虑使用elt工具

 

什么是elt工具?

  ETL,是英文 Extract-Transform-Load 的缩写,用来描述将数据从来源端经过抽取(extract)、转换(transform)、加载(load)至目的端的过程。ETL一词较常用在数据仓库,但其对象并不限于数据仓库。

  ETL是构建数据仓库的重要一环,用户从数据源抽取出所需的数据,经过数据清洗,最终按照预先定义好的数据仓库模型,将数据加载到数据仓库中去。

常用的etl工具有: databus、canal (方案四用了这个组件,有etl 的部分功能)、otter 、kettle 等

 

 

 

posted @ 2023-08-31 09:32  方达达  阅读(362)  评论(0编辑  收藏  举报