微服务—ES数据同步

目录

数据同步

问题分析

方案1. 同步调用

方案2. 异步通知

方案3. 监听binlog​编辑 

各方案对比

案例——利用MQ实现数据同步

步骤1. 导入hotel-admin项目

步骤2. 声明交换机、队列

步骤3. 发送MQ消息

步骤4. 接收MQ消息

步骤5. 测试同步功能


数据同步

        elasticsearch中的数据是由我们通过mysql数据进行导入的,因此mysql数据发生改变时,elasticsearch中的数据也必须跟着改变,这就是elasticsearch与mysql之间的数据同步


问题分析

        在微服务中,负责酒店管理(操作mysql)的业务与负责酒店搜索(操作elasticsearch)的业务可能在两个不同的微服务上,那么数据同步该如何实现呢?

方案1. 同步调用

基本步骤:
hotel-demo对外提供接口,用来修改elasticsearch中的数据,酒店管理服务在完成数据库操作后,直接调用hotel-demo提供的接口。  


方案2. 异步通知

 

基本步骤:
hotel-admin对mysql数据库数据完成增、删、改后,发送MQ消息,hotel-demo监听MQ,接收到消息后完成elasticsearch数据修改。


方案3. 监听binlog

基本步骤:
给mysql开启binlog功能,mysql完成增、删、改操作都会记录在binlog中,hotel-demo基于canal监听binlog变化,实时更新elasticsearch中的内容。


各方案对比

方案一:同步调用
优点:实现简单,粗暴
缺点:业务耦合度高

方案二:异步通知
优点:低耦合,实现难度一般
缺点:依赖mq的可靠性

方案三:监听binlog
优点:完全解除服务间耦合
缺点:开启binlog增加数据库负担、实现复杂度高


案例——利用MQ实现数据同步

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


步骤1. 导入hotel-admin项目

导入课前资料提供的hotel-admin项目,注意修改数据库配置为本地数据库,运行并访问http://localhost:8099进入管理界面。

项目中包含了酒店的CRUD功能: 


步骤2. 声明交换机、队列

MQ结构如图:

在hotel-admin、hotel-demo项目中做以下4步

1. 引入rabbitmq的依赖:  

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

2. 设置rabbitmq配置:

3. 设置队列与交换机名称常量:

package cn.itcast.hotel.constants;

public class MqConstants {
    /**
     * 交换机
     */
    public final static String HOTEL_EXCHANGE = "hotel.topic";
    /**
     * 监听新增和修改的队列
     */
    public final static String HOTEL_INSERT_QUEUE = "hotel.insert.queue";
    /**
     * 监听删除的队列
     */
    public final static String HOTEL_DELETE_QUEUE = "hotel.delete.queue";
    /**
     * 新增或修改的RoutingKey
     */
    public final static String HOTEL_INSERT_KEY = "hotel.insert";
    /**
     * 删除的RoutingKey
     */
    public final static String HOTEL_DELETE_KEY = "hotel.delete";
}

4. 声明队列与交换机名称:
队列与交换机的声明可以采用注解或者bean的方式,这里采用bean的方式进行声明。

package cn.itcast.hotel.config;

import cn.itcast.hotel.constants.MqConstants;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MqConfig {
    @Bean
    public TopicExchange topicExchange(){
        return new TopicExchange(MqConstants.HOTEL_EXCHANGE, true, false);
    }

    @Bean
    public Queue insertQueue(){
        return new Queue(MqConstants.HOTEL_INSERT_QUEUE, true);
    }

    @Bean
    public Queue deleteQueue(){
        return new Queue(MqConstants.HOTEL_DELETE_QUEUE, true);
    }

    @Bean
    public Binding insertQueueBinding(){
        return BindingBuilder.bind(insertQueue()).to(topicExchange()).with(MqConstants.HOTEL_INSERT_KEY);
    }

    @Bean
    public Binding deleteQueueBinding(){
        return BindingBuilder.bind(deleteQueue()).to(topicExchange()).with(MqConstants.HOTEL_DELETE_KEY);
    }
}

步骤3. 发送MQ消息

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


步骤4. 接收MQ消息

hotel-demo接收到MQ消息要做的事情包括:
新增消息:根据传递的hotel的id查询hotel信息,然后新增一条数据到索引库
删除消息:根据传递的hotel的id删除索引库中的一条数据

1. 首先在hotel-demo的cn.itcast.hotel.service包下的IHotelService中新增新增、删除业务

void deleteById(Long id);

void insertById(Long id);

2. 给hotel-demo中的cn.itcast.hotel.service.impl包下的HotelService中实现业务

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

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

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

3. 编写监听器,在hotel-demo中的cn.itcast.hotel.mq包新增一个类

package cn.itcast.hotel.mq;

import cn.itcast.hotel.constants.MqConstants;
import cn.itcast.hotel.service.IHotelService;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class HotelListener {

    @Autowired
    private IHotelService hotelService;

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

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

步骤5. 测试同步功能

1. 重启消息接收方和消息发送方

(记录一个小bug:在mq消息监听类上忘记添加注解@Component,导致一开始没有监听到消息)

2.在旅游页面可以发现上海希尔顿酒店价格为2680

3.在酒店管理页面将该酒店的价格重新设置为3000

4.重新回到旅游页面搜索该酒店,可以发现价格发生变化,证明数据同步成功。(删除功能同理)

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

八、键盘响应

之前博文格式已经固定&#xff0c;这里就不在赘述了&#xff0c;直接把核心代码进行解释一下即可&#xff0c;仅作为小笔记而已 项目实现功能&#xff1a; 按下键盘0&#xff0c;显示原始图像 按下键盘1&#xff0c;显示原始图像的灰度图 按下键盘2&#xff0c;显示原始图像的…

Python-To-Do-List

今天跟着油管学习创建了简单的代办事项列表应用程序&#xff0c;使用了python的tkinter库来制作图形用户界面&#xff08;GUI&#xff09; 1. 导入tkinter库 python Copy code import tkinter from tkinter import * 这两行导入了tkinter模块&#xff0c;它是Python的标准GUI库…

六、Redis之数据持久化及高频面试题

6.1 数据持久化 官网文档地址&#xff1a;https://redis.io/docs/manual/persistence/ Redis提供了主要提供了 2 种不同形式的持久化方式&#xff1a; RDB&#xff08;Redis数据库&#xff09;&#xff1a;RDB 持久性以指定的时间间隔执行数据集的时间点快照。AOF&#xff0…

django CBV 与 DRF APIView源码分析

django CBV源码分析 在django框架中&#xff0c;视图层中的逻辑即可以使用函数处理也可以使用类进行处理&#xff0c;如果在视图层中使用函数处理请求&#xff0c;就是FBV(function base views)&#xff0c;如果在视图层中使用类处理请求&#xff0c;就是CBV(class base views…

微信,支付宝在线换钱平台系统源码

探索全新、全开源的在线换钱系统源码&#xff0c;它将以前所未有的方式改变您的支付体验。我们为您精心打造了一个集简单易用与安全高效于一身的优质产品&#xff0c;它采用最新的技术开发&#xff0c;为您带来前所未有的便捷与安心。 这款在线换钱系统源码设计直观&#xff0…

【大数据Hive】hive 表设计常用优化策略

目录 一、前言 二、hive 普通表查询原理 2.1 操作演示说明 2.1.1 创建一张表&#xff0c;并加载数据 2.1.2 统计3月24号的登录人数 2.1.3 查询原理过程总结 2.2 普通表结构带来的问题 三、hive分区表设计 3.1 区表结构 - 分区设计思想 3.2 操作演示 3.2.1 创建分区表…

每日一题(数字颠倒,单词倒排)

数字颠倒_牛客题霸_牛客网 (nowcoder.com) #include <stdio.h>int main() {char arr[100];gets(arr);int lenstrlen(arr);for(int ilen-1;i>0;i--){printf("%c",arr[i]);}return 0; } 单词倒排_牛客题霸_牛客网 (nowcoder.com) #include <stdio.h> #…

《Java 简易速速上手小册》第4章:Java 中的异常处理(2024 最新版)

文章目录 4.1 异常类型和错误 - 遇见你的小怪兽4.1.1 基础知识4.1.2 重点案例&#xff1a;文件读取处理4.1.3 拓展案例 1&#xff1a;处理空指针异常4.1.4 拓展案例 2&#xff1a;捕获多个异常 4.2 异常处理机制 - 穿上你的超级英雄斗篷4.2.1 基础知识4.2.2 重点案例&#xff1…

Vuex 模块的详解

Vuex 模块是将 store 分割成多个模块的一种方式&#xff0c;每个模块都有自己的状态、mutations、actions 和 getters。这有助于更好地组织和管理应用程序的状态。 创建模块&#xff1a; 首先&#xff0c;需要创建一个模块。可以在 store 中定义一个新的模块对象&#xff0c…

python小项目----多重剪切板

代码&#xff1a; import shelve,pyperclip,sysimport mcbmcbShelfshelve.open(mcb)# 保存剪切板内容 if len(sys.argv)3 and sys.argv[1].lower()save:#剪切板的内容保存到第三个参数中mcbShelf[sys.argv[2]]pyperclip.paste()print("你的剪切板中的内容将被保存到mcbSh…

今日早报 每日精选15条新闻简报 每天一分钟 知晓天下事 2月14日,星期三

每天一分钟&#xff0c;知晓天下事&#xff01; 2024年2月14日 星期三 农历正月初五 1、 第十四届全国冬季运动会将于17日开幕&#xff0c;部分赛事今天起陆续开赛。 2、 2024年购房政策将进一步宽松&#xff0c;专家称今年买房性价比更高。 3、 春节档票房突破45亿元&#…

算法学习——LeetCode力扣回溯篇2

算法学习——LeetCode力扣回溯篇2 40. 组合总和 II 40. 组合总和 II - 力扣&#xff08;LeetCode&#xff09; 描述 给定一个候选人编号的集合 candidates 和一个目标数 target &#xff0c;找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的每个数字…

(二)【Jmeter】专栏实战项目靶场drupal部署

该专栏后续实战示例&#xff0c;都以该篇部署的项目展开操作。 前置条件 参考“&#xff08;一&#xff09;【Jmeter】JDK及Jmeter的安装部署及简单配置” 安装部署Jmeter&#xff0c;从文章最后下载“Postman、Rancher.ova、VirtualBox-7.0.12-159484-Win.exe、Xshell-7.0.01…

CMU和ETH联合研发了一个名为 「敏捷但安全」的新框架,为四足机器人在复杂环境中实现高速运动提供了解决方案

在高速机器人运动领域&#xff0c;实现同时兼顾速度和安全一直是一大挑战。但现在&#xff0c;卡内基梅隆大学&#xff08;CMU&#xff09;和苏黎世联邦理工学院&#xff08;ETH&#xff09;的研究团队带来了突破性进展。他们开发的新型四足机器人算法&#xff0c;不仅能在复杂…

Leetcode 452. 用最少数量的箭引爆气球435. 无重叠区间

class Solution {public int findMinArrowShots(int[][] points) {Arrays.sort(points,(o1,o2)->Integer.compare(o1[0], o2[0]));int count1;//箭的数量for(int i1;i<points.length;i) {if(points[i][0]>points[i-1][1]) {count;//边界没重合&#xff0c;又需要一支箭…

如何重新安装 macOS

你可以使用电脑的内建恢复系统“macOS 恢复”来重新安装 Mac 操作系统。不但简单快捷&#xff0c;而且重新安装后不会移除你的个人数据。 将 Mac 关机 选取苹果菜单  >“关机”&#xff0c;然后等待 Mac 关机。如果你无法将 Mac 关机&#xff0c;请按住它的电源按钮最长 …

第六篇:MySQL图形化管理工具

经过前五篇的学习&#xff0c;对于数据库这门技术的理解&#xff0c;我们已经在心中建立了一个城堡大致的雏形&#xff0c;通过命令行窗口&#xff08;cmd&#xff09;快速上手了【SQL语法-DDL-数据定义语言】等相关命令 道阻且长&#xff0c;数据库技术这一宝藏中还有数不清的…

猫头虎分享: 探索软件系统架构的革新之路

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

Swift Combine 网络受限时从备用 URL 请求数据 从入门到精通十四

Combine 系列 Swift Combine 从入门到精通一Swift Combine 发布者订阅者操作者 从入门到精通二Swift Combine 管道 从入门到精通三Swift Combine 发布者publisher的生命周期 从入门到精通四Swift Combine 操作符operations和Subjects发布者的生命周期 从入门到精通五Swift Com…

python 基础知识点(蓝桥杯python科目个人复习计划40)

今日复习内容&#xff1a;矩阵乘法&#xff0c;高斯消元 哈哈&#xff0c;我来干回老本行&#xff0c;复习点儿数学类专业学的东西 因为电脑上制作费时间&#xff0c;所以我直接用我的《高等代数》和《数值分析》笔记。 一.矩阵乘法 例题1&#xff1a;矩阵相乘 题目描述&am…