elasticsearch MySQL 数据同步。

news2024/11/16 12:02:55

elasticsearch & MySQL 数据同步。


文章目录

    • elasticsearch & MySQL 数据同步。
      • 3. 数据同步。
          • 3.1. 思路分析。
            • 3.1.1. 同步调用。
            • 3.1.2. 异步通知。
            • 3.1.3. 监听 binlog。
            • 3.1.4. 选择。
          • 3.2. 实现数据同步。
            • 3.2.1. 思路。
            • 3.2.2. 导入 demo。
            • 3.2.3. 声明交换机、队列。
            • 1)引入依赖。
            • 2)声明队列交换机名称。
            • 3)声明队列交换机。
            • 3.2.4. 发送 MQ 消息。
            • 3.2.5. 接收 MQ 消息。


3. 数据同步。

elasticsearch 中的酒店数据来自于 mysql 数据库,因此 mysql 数据发生改变时,elasticsearch 也必须跟着改变,这个就是 elasticsearch 与 mysql 之间的数据同步

在微服务中,负责酒店管理(操作 MySQL)的业务与负责酒店搜索(操作 elasticsearch)的业务可能在两个不同的微服务上,两者数据该如克如何保持同步?



3.1. 思路分析。

常见的数据同步方案有三种。

  • 同步调用。

  • 异步通知。

  • 监听 binlog。



3.1.1. 同步调用。

方案一:同步调用。

在这里插入图片描述
基本步骤如下。

  • hotel-demo 对外提供接口,用来修改 elasticsearch 中的数据。

  • 酒店管理服务在完成数据库操作后,直接调用 hotel-demo 提供的接口,



3.1.2. 异步通知。

方案二:异步通知。

在这里插入图片描述
流程如下。

  • hotel-admin 对 mysql 数据库数据完成增、删、改后,发送 MQ 消息。

  • hotel-demo 监听 MQ,接收到消息后完成 elasticsearch 数据修改。



3.1.3. 监听 binlog。

方案三:监听 binlog。

在这里插入图片描述
流程如下。

  • 给 mysql 开启 binlog 功能。

  • mysql 完成增、删、改操作都会记录在 binlog 中。

  • hotel-demo 基于 canal 监听 binlog 变化,实时更新 elasticsearch 中的内容。



3.1.4. 选择。

方式一:同步调用。

  • 优点:实现简单,粗暴。

  • 缺点:业务耦合度高。

方式二:异步通知。

  • 优点:低耦合,实现难度一般。

  • 缺点:依赖 mq 的可靠性。

方式三:监听 binlog。

  • 优点:完全解除服务间耦合。

  • 缺点:开启 binlog 增加数据库负担、实现复杂度高。



3.2. 实现数据同步。
3.2.1. 思路。

开发 hotel-admin 项目作为酒店管理的微服务。当酒店数据发生增、删、改时,要求对 elasticsearch 中数据也要完成相同操作。

步骤。

  • 导入 hotel-admin 项目,启动并测试酒店数据的 CRUD。

  • 声明 exchange、queue、routingKey。

  • 在 hotel-admin 中的增、删、改业务中完成消息发送。

  • 在 hotel-demo 中完成消息监听,并更新 elasticsearch 中数据。

  • 启动并测试数据同步功能。



3.2.2. 导入 demo。

导入 hotel-admin 项目。

运行后,访问 http://localhost:8099。

其中包含了酒店的 CRUD 功能。



3.2.3. 声明交换机、队列。

MQ 结构如图。

在这里插入图片描述



1)引入依赖。

在 hotel-admin、hotel-demo 中引入 rabbitmq 的依赖。

<!-- amqp。-->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>


2)声明队列交换机名称。

在 hotel-admin 和 hotel-demo 中的 com.geek.elasticsearchgeek.hotel.constatnts 包下新建一个类 MqConstants

package com.geek.elasticsearchgeek.hotel.constant;

/**
 * @author geek
 */
public interface IMqConstants {

    /**
     * 交换机。
     */
    String TOPIC_EXCHANGE_HOTEL = "topic.exchange.hotel";
    /**
     * 监听新增和修改的队列。
     */
    String QUEUE_HOTEL_INSERT = "queue.hotel.insert";
    /**
     * 监听删除的队列。
     */
    String QUEUE_HOTEL_DELETE = "queue.hotel.delete";
    /**
     * 新增或修改的 RoutingKey。
     */
    String ROUTING_KEY_HOTEL_INSERT = "routing.key.hotel.insert";
    /**
     * 删除的 RoutingKey。
     */
    String ROUTING_KEY_HOTEL_DELETE =  "routing.key.hotel.delete";

}



3)声明队列交换机。

在 hotel-demo 中,定义配置类,声明队列、交换机。

package com.geek.elasticsearchgeek.hotel.config;

import com.geek.elasticsearchgeek.hotel.constant.IMqConstants;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author geek
 */
@Configuration
public class MqConfig {

    @Bean
    public TopicExchange topicExchange() {
        return new TopicExchange(IMqConstants.TOPIC_EXCHANGE_HOTEL, true, false);
    }

    @Bean
    public Queue queueHotelInsert() {
        return new Queue(IMqConstants.QUEUE_HOTEL_INSERT, true);
    }

    @Bean
    public Queue queueHotelDelete() {
        return new Queue(IMqConstants.QUEUE_HOTEL_DELETE, true);
    }

    @Bean
    public Binding hotelInsertQueueRoutingKeyBinding() {
        return BindingBuilder.bind(queueHotelInsert())
                .to(topicExchange())
                .with(IMqConstants.ROUTING_KEY_HOTEL_INSERT);
    }

    @Bean
    public Binding hotelDeleteQueueRoutingKeyBinding() {
        return BindingBuilder.bind(queueHotelDelete())
                .to(topicExchange())
                .with(IMqConstants.ROUTING_KEY_HOTEL_DELETE);
    }

}



3.2.4. 发送 MQ 消息。

在 hotel-admin 中的增、删、改业务中分别发送 MQ 消息。

package com.geek.elasticsearch.hotel.admin.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.geek.elasticsearch.hotel.admin.constant.IMqConstants;
import com.geek.elasticsearch.hotel.admin.dataobject.Hotel;
import com.geek.elasticsearch.hotel.admin.dto.PageResult;
import com.geek.elasticsearch.hotel.admin.service.IHotelService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.security.InvalidParameterException;

/**
 * @author geek
 */
@Slf4j
@RestController
@RequestMapping("/hotel")
public class HotelController {

    @Autowired
    private IHotelService hotelService;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @GetMapping("/{id}")
    public Hotel queryById(@PathVariable("id") Long id) {
        return this.hotelService.getById(id);
    }

    @GetMapping("/list")
    public PageResult hotelList(
            @RequestParam(value = "page", defaultValue = "1") Integer page,
            @RequestParam(value = "size", defaultValue = "1") Integer size) {
        Page<Hotel> result = this.hotelService.page(new Page<>(page, size));

        return new PageResult(result.getTotal(), result.getRecords());
    }

    @PostMapping
    public void saveHotel(@RequestBody Hotel hotel) {
        this.hotelService.save(hotel);
        this.rabbitTemplate.convertAndSend(IMqConstants.TOPIC_EXCHANGE_HOTEL,
                IMqConstants.ROUTING_KEY_HOTEL_INSERT,
                hotel.getId());
    }

    @DeleteMapping("/{id}")
    public void deleteById(@PathVariable("id") Long id) {
        this.hotelService.removeById(id);
        this.rabbitTemplate.convertAndSend(IMqConstants.TOPIC_EXCHANGE_HOTEL,
                IMqConstants.ROUTING_KEY_HOTEL_DELETE,
                id);
    }

    @PutMapping
    public void updateById(@RequestBody Hotel hotel) {
        if (hotel.getId() == null) {
            throw new InvalidParameterException("id 不能为空。");
        }
        this.hotelService.updateById(hotel);
        this.rabbitTemplate.convertAndSend(IMqConstants.TOPIC_EXCHANGE_HOTEL,
                IMqConstants.ROUTING_KEY_HOTEL_INSERT,
                hotel.getId());
    }

}



3.2.5. 接收 MQ 消息。

hotel-demo 接收到 MQ 消息要做的事情包括。

  • 新增消息:根据传递的 hotel 的 id 查询 hotel 信息,然后新增一条数据到索引库。

  • 删除消息:根据传递的 hotel 的 id 删除索引库中的一条数据。

1)首先在 hotel-demo 的 com.geek.elasticsearchgeek.hotel.service 包下的 IHotelService 中新增新增、删除业务。

void deleteById(Long id);

        void insertById(Long id);

2)给 hotel-demo 中的 com.geek.elasticsearchgeek.hotel.service.impl 包下的 HotelService 中实现业务。


    @Override
    public void insertById(Long id) {
        // 根据 id 查询酒店数据。
        Hotel hotel = getById(id);
        // 转换为文档类型。
        HotelDoc hotelDoc = new HotelDoc(hotel);

        // 准备 Request 对象。
        IndexRequest indexRequest = new IndexRequest("hotel").id(hotel.getId().toString());
        // 准备 Json 文档。
        indexRequest.source(JSON.toJSONString(hotelDoc), XContentType.JSON);
        // 发送请求。
        try {
            this.restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void deleteById(Long id) {
        // 准备 Request。
        DeleteRequest deleteRequest = new DeleteRequest("hotel", id.toString());
        // 发送请求。
        try {
            this.restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

3)编写监听器。

在 hotel-demo 中的com.geek.elasticsearchgeek.hotel.mq包新增一个类。

package com.geek.elasticsearchgeek.hotel.mq;

import com.geek.elasticsearchgeek.hotel.constant.IMqConstants;
import com.geek.elasticsearchgeek.hotel.service.IHotelService;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @author geek
 */
@Component
public class HotelMqListener {

    @Autowired
    private IHotelService hotelService;

    /**
     * 监听酒店新增或修改的业务。
     *
     * @param id 酒店 id。
     */
    @RabbitListener(queues = IMqConstants.QUEUE_HOTEL_INSERT)
    public void listenHotelInsertOrUpdate(Long id) {
        this.hotelService.insertById(id);
    }

    /**
     * 监听酒店删除的业务。
     *
     * @param id 酒店 id。
     */
    @RabbitListener(queues = IMqConstants.QUEUE_HOTEL_DELETE)
    public void listenHotelDelete(Long id) {
        this.hotelService.deleteById(id);
    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/410597.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Ansys Zemax | 模拟 AR 系统中的全息光波导:第二部分

AR 系统通常使用全息图将光耦合到波导中。本文展示了如何继续改进 本系列文章的第一部分 &#xff08;点击查看&#xff09;中建模的初步设计。&#xff08;联系我们获取文章附件&#xff09; 简介 AR 是一种允许屏幕上的虚拟世界与现实场景结合并交互的技术。 本文演示了如何…

如何学习计算机视觉?

AI的专业领域知识是指AI与具体应用领域相结合时所需要的该应用领域的知识。AI的应用领域非常广泛&#xff0c;例如计算机视觉、智能交通、智能制造、智慧金融、智慧教育、智慧农业、智慧能源、智能通信、智能芯片等。本文主要介绍计算机视觉的基本概念、发展历程、主要研究内容…

HMM-读书笔记

信息提取基础 MM 马卡洛夫链(Markov chain)是处理一类随机过程&#xff0c;这些过程包含最少量的内存&#xff0c;但实际上并不是无记忆的。下面&#xff0c;我们将处理离散随机变量和有限马尔可夫链。令 X1, X2, … , Xn, … 为随机变量序列&#xff0c;它们的值为同样有限字…

LeetCode 654 最大二叉树

题目&#xff1a; 给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建: 创建一个根节点&#xff0c;其值为nums中的最大值。 递归地在最大值左边的子数组前缀上构建左子树。 递归地在最大值右边的子数组后缀上构建右子树。 返回 nums 构建的最大…

VMware ESXi 8.0c Unlocker OEM BIOS 集成网卡驱动和 NVMe 驱动 (集成驱动版)

发布 ESXi 8.0 集成驱动版&#xff0c;在个人电脑上运行企业级工作负载 请访问原文链接&#xff1a;https://sysin.org/blog/vmware-esxi-8-sysin/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org 发布 ESXi 8.0 集成驱动版&am…

在 Python 中计算两个数字之间的百分比

要计算两个数字之间的百分比&#xff0c;请将一个数字除以另一个数字&#xff0c;然后将结果乘以 100&#xff0c;例如 (30 / 75) * 100。这显示第一个数字占第二个数字的百分比。 在示例中&#xff0c;30 是 75 的 40%。 def is_what_percent_of(num_a, num_b):return (num_a…

论Sort()方法在 Python 和 Javascript 中应用的区别

Sort()方法相信大家都熟悉&#xff0c;用于排序&#xff0c;那就是数字从低到高&#xff08;默认&#xff09; 和 从高到低。以下对这个排序方法在Python 和 Java Script 中应用的区别作详细的举例说明。 在 Python中&#xff0c;例如有 lst1 : [1,5,8,6,2] &#xff0c;要对这…

html制作好看的个人简历(附源码)

文章目录1.设计来源1.1 主界面1.2 基本资料页面1.3 个人名言页面1.4 教育经历页面1.5 联系方式页面1.6 自我评价页面1.7 工作经历页面1.8 兴趣爱好页面1.9 沟通交流页面2.效果和源码2.1 动态效果2.2 源代码2.3 相关个人简历源码源码下载作者&#xff1a;xcLeigh 文章地址&#…

java课程设计(学生信息管理系统设计)+数据库

&#x1f50d; &#x1f50e; 本期带领大家一起来学习java课程设计&#xff08;学生信息管理系统设计&#xff09;数据库的实现思路 &#x1f50d; &#x1f50e; 文章目录题目要求数据库&#x1f30d;一 、环境搭建&#x1f30d;二 、功能实现 &#x1f30e; &#x1f30d;1.学…

重磅!阿里版本【ChatGPT】开放测评!

前两天突然爆出惊人消息&#xff1a;阿里版ChatGPT开放测评了&#xff01; 在本月初&#xff0c;已经有诸多关于阿里巴巴即将推出类似ChatGPT产品的传闻。 数日前&#xff0c;首批曝光的天猫精灵“鸟鸟分鸟”脱口秀版GPT基于大型模型的“精简版”&#xff0c;凭借其出色的表现吸…

2023-4-11-chrono库用法学习

&#x1f37f;*★,*:.☆(&#xffe3;▽&#xffe3;)/$:*.★* &#x1f37f;&#x1f4a5;&#x1f4a5;&#x1f4a5;欢迎来到&#x1f91e;汤姆&#x1f91e;的csdn博文&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f49f;&#x1f49f;喜欢的朋友可以关注一下&#xff0…

4.9、字节序

4.9、字节序1.简介2.字节序举例3.判断电脑存储方式代码1.简介 现代 CPU 的累加器一次都能装载&#xff08;至少&#xff09;4 字节&#xff08;这里考虑 32 位机&#xff09;&#xff0c;即一个整数。那么这 4字节在内存中排列的顺序将影响它被累加器装载成的整数的值&#xff…

vue element-ui 暗黑主题应用到若依框架

问题描述 基于若依框架的element-ui&#xff0c;将主题更换为暗黑主题。 问题分析 现有的element-ui框架提供的主题不满足自定义需求&#xff0c;大多数框架&#xff0c;包括若依提供了更换主题色的功能&#xff0c;但也只是更换的primary-color&#xff0c;其他组件的主题还…

算法小课堂(五)贪心算法

一、概述 贪心算法是一种常见的算法思想&#xff0c;用于解决优化问题。其基本思想是在每一步选择中都采取当前状态下最优的选择&#xff0c;从而希望能够获得全局最优解。 具体来说&#xff0c;贪心算法通常分为以下步骤&#xff1a; 定义问题的最优解&#xff0c;通常需要将…

【人生历程】我的创作纪念日

目录 与编程不得不说的爱恨情仇 在csdn的收获&#xff1a; 与csdn的日常 在平凡的日子偶然的成就感&#xff1a; 对未来的憧憬&#xff1a; 今天是2023.4.8号&#xff0c;早上的刚刚参加完蓝桥杯&#xff0c;下午看到csdn官方的活动&#xff0c;心血来潮写下以下内容&…

家政服务小程序实战开发教程018-用户注册

我们在教程的一开始的时候就讲解了用户注册的功能。当初的规划是一进来就让用户自主的选择角色&#xff0c;然后提交用户信息&#xff0c;如果未注册就跳转到注册界面。 随着教程的深入&#xff0c;又参考了很多线上的小程序&#xff0c;发现这种模式也有一定的缺点。因为作为…

Linux网络虚拟化2

Linux网络虚拟化2 今天我们接着上节课介绍的 Linux 网络知识&#xff0c;继续来学习它们在虚拟化网络方面的应用&#xff0c;从而为后续学习容器编排系统、理解各个容器是如何通过虚拟化网络来协同工作打好基础。 这一篇内容较多&#xff0c;可以重点看标红部分和标粗部分​。…

Ubuntu环境下minicom使用

1、minicom的安装 sudo apt-get install minicom2、minicom的配置 sudo minicom -s # 打开minicom配置界面3、配置serial port setup串口信息 使用上下箭头选择&#xff0c;enter进入。 按A修改Serial Device&#xff0c;修改之前可以用命令ls -la /dev/ttyUSB或者ls -la …

java 一文讲透集合框架(10万字博文)

目录 一、前言 二、集合简介 1.定义 : 2.集合与数组的区别 : 3.集合的好处 : 三、集合框架 1.单列集合 2.双列集合 Δ体系图&#xff08;重要&#xff09; 四、List集合详解&#xff08;三万余字&#xff09; 五、Set集合详解&#xff08;三万余字&#xff09; 六、增…

学习实践-Whisper语音识别模型实战(部署+运行)

1、Whisper内容简单介绍 OpenAI的语音识别模型Whisper&#xff0c;Whisper 是一个自动语音识别&#xff08;ASR&#xff0c;Automatic Speech Recognition&#xff09;系统&#xff0c;OpenAI 通过从网络上收集了 68 万小时的多语言&#xff08;98 种语言&#xff09;和多任务…