【云岚到家】-day04-1-数据同步方案-Canal-MQ

【云岚到家】-day04-1-数据同步方案-Canal-MQ

  • 1 服务搜索
    • 1.1 服务搜索技术方案
      • 1.1.1 需求分析
      • 1.1.2 技术方案
        • 1.1.2.1 使用Elasticsearch进行全文检索
        • 1.1.2.2 索引同步方案
      • 1.1.3 Canal+MQ
        • 1.1.3.1 MySQL主从数据同步
        • 1.1.3.2 Canal工作流程
        • 1.1.3.3 具体实现方案
    • 1.2 MQ技术方案
      • 1.2.1 保证生产消息可靠性
        • 1.2.1.1 生产消息及重试方法
        • 1.2.1.2 生产者确认机制
      • 1.2.2 保证消费消息可靠性
        • 1.2.2.1 三种持久化及确认机制
      • 1.2.3 保证消息的幂等性
      • 1.2.4 小结
    • 1.3 配置数据同步环境
      • 1.3.1 Canal+MQ同步流程
      • 1.3.2 配置Canal+MQ数据同步环境
        • 1.3.2.1 配置Canal+RabbitMQ
        • 1.3.2.2 测试
        • 1.3.2.3 数据不同步解决方法


1 服务搜索

1.1 服务搜索技术方案

1.1.1 需求分析

服务搜索的入口有两处:

1.在门户最上端的搜索入口对服务信息进行搜索。

如下图:

在这里插入图片描述

第2部分触发搜索框进入搜索页面,输入关键字进行搜索,如下图:

在这里插入图片描述

2.在门户最下方点击“全部服务”进入全部服务界面。

如下图:

点击服务分类查询分类下的服务。

在这里插入图片描述

1.1.2 技术方案

1.1.2.1 使用Elasticsearch进行全文检索

要实现服务搜索使用什么技术呢?

根据需求分析,对服务进行搜索除了根据服务类型查询其下的服务以外还需要根据关键字去搜索与关键字匹配的服务。

通过关键字去匹配服务的哪些信息呢?比如:输入关键字“家庭保洁”,它会去匹配服务相关的信息,比如:服务类型的名称、服务项的名称,甚至根据需要也可能去匹配服务介绍的信息,只要与“家庭保洁”相关的服务都会展示出来。如下效果:

要实现服务搜索使用什么技术呢?

根据需求分析,对服务进行搜索除了根据服务类型查询其下的服务以外还需要根据关键字去搜索与关键字匹配的服务。

通过关键字去匹配服务的哪些信息呢?比如:输入关键字“家庭保洁”,它会去匹配服务相关的信息,比如:服务类型的名称、服务项的名称,甚至根据需要也可能去匹配服务介绍的信息,只要与“家庭保洁”相关的服务都会展示出来。如下效果:

在这里插入图片描述

这里最关键的是根据关键字去匹配,使用数据库的like搜索能否实现呢?

上图的搜索效果是一种全文检索方式,在搜索“家庭保洁”关键字时会对关键字先分词,分为“家庭”和“保洁”,再根据分好的词去匹配索引库中的服务类型的名称、服务项的名称、服务项的描述等字段。Like搜索不具有分词功能,它不是一种全文检索的方式。

虽然MySQL也支持全文检索,但是考虑搜索接口具有高性能需求,并且它面向的是C端用户,如果C端用户直接访问数据库在高并发时就会对数据库造成很大的压力,影响接口的性能,同时也会对其它业务使用数据库造成影响,所以一般C端用户的高性能接口不会直接访问数据库。

如果要实现全文检索且对接口性能有一定的要求,最常用的是Elasticsearch,本项目使用ES完成服务搜索功能的开发。

Elasticsearch是基于倒排索引的原理,正排索引是从文章中找词,倒排索引是根据词去找文章,原理如下:

在这里插入图片描述

1.1.2.2 索引同步方案

如果要使用ES去搜索服务信息需要提前对服务信息在ES中创建索引,运营端在管理服务时是将服务信息保存在数据库,如何对数据库中的服务信息去创建索引,保证数据库中的信息与ES的索引信息同步呢,本节对索引同步的方案进行分析与确定。

在这里插入图片描述

方案1: 添加服务信息维护索引

在服务项的增删改查Service方法中添加维护ES索引的代码。

在区域服务的增删改查Service方法中添加维护ES索引的代码。

例如下边的代码:

public Serve onSale(Long id){
    //操作serve表
    //添加向ES创建索引的代码
}

首先上边的代码是在原有业务方式的基础上添加索引同步的代码,增加代码的复杂度不方便维护,扩展性差。

其次上边的代码存在分布式事务,操作serve表会访问数据库,添加索引会访问ES,使用数据库本地事务是无法控制整个方法的一致性的,比如:向ES写成功了由于网络问题抛出网络超时异常,最终数据库操作回滚了ES操作没有回滚,数据库的数据和ES中的索引不一致。

方案1通常在生产中不会使用。

方案2:使用Canal+MQ

Canal是什么?

canal [kə’næl],译意为水道/管道/沟渠,主要用途是基于 MySQL 数据库增量日志解析,对数据进行同步,如下图:

Canal可与很多数据源进行对接,将数据由MySQL同步到ES、MQ、DB等各个数据源。

Canal的意思是水道/管道/沟渠,它相当于一个数据管道,通过解析MySQL的binlog日志完成数据同步工作。

官方文档:https://github.com/alibaba/canal/wiki

1.1.3 Canal+MQ

在这里插入图片描述

1.1.3.1 MySQL主从数据同步

要理解上图中Canal的工作原理需要首先要知道MySQL主从数据同步的原理,如下图:

在这里插入图片描述

MySQL主从集群由MySQL主服务器(master)和MySQL从服务器(slave)组成,MySQL主从数据同步是一种数据库复制技术,进行写数据会先向主服务器写,写成功后将数据同步到从服务器,流程如下:

1、主服务器将所有写操作(INSERT、UPDATE、DELETE)以二进制日志(binlog)的形式记录下来。

2、从服务器连接到主服务器,发送dump 协议,请求获取主服务器上的binlog日志。MySQL的dump协议是MySQL复制协议中的一部分。

3、MySQL master 收到 dump 请求,开始推送 binary log 给 slave

4、从服务器解析日志,根据日志内容更新从服务器的数据库,完成从服务器的数据保持与主服务器同步。

1.1.3.2 Canal工作流程

理解了MySQL主从同步的原理,Canal在整个过程充当什么角色呢?

如下图:

在这里插入图片描述

工作流程如下:

1、Canal模拟 MySQL slave 的交互协议,伪装自己为 MySQL slave ,向 MySQL master 发送dump 协议,MySQL的dump协议是MySQL复制协议中的一部分。

2、MySQL master 收到 dump 请求,开始推送 binary log 给 slave (即 canal )。一旦连接建立成功,Canal会一直等待并监听来自MySQL主服务器的binlog事件流,当有新的数据库变更发生时MySQL master主服务器发送binlog事件流给Canal。

3、Canal会及时接收并解析这些变更事件并解析 binary log

通过以上流程可知Canal和MySQL master主服务器之间建立了长连接。

1.1.3.3 具体实现方案

本方案需要借助Canal和消息队列,具体实现方案如下:

通过上边的技术分析下边对本项目服务搜索方案进行总结。

本项目使用Elasticsearch实现服务的搜索功能,使用Canal+MQ完成服务信息与ES索引同步。

如下图:

在这里插入图片描述

流程如下:

运营人员对服务信息进行增删改操作,MySQL记录binlog日志。

Canal定时读取binlog 解析出增加、修改、删除数据的记录。

Canal将修改记录发送到MQ。

同步程序监听MQ,收到增加、修改、删除数据的记录,请求ES创建、修改、删除索引。

C端用户请求服务搜索接口从ES中搜索服务信息。

1.2 MQ技术方案

1.2.1 保证生产消息可靠性

上述技术方案中有一个关键点,首先数据增删改的信息是保证写入binlog的,Canal解析出增删改的信息后写入MQ,同步程序从MQ去读取消息,如果MQ中的消息丢失了数据将无法进行同步。

如何保证MQ消息的可靠性?

保证MQ消息的可靠性分两个方面:保证生产消息的可靠性、保证消费消息的可靠性。

保证生产消息的可靠性:

RabbitMQ提供生产者确认机制保证生产消息的可靠性,技术方案如下 :

在这里插入图片描述

1.2.1.1 生产消息及重试方法

在com.jzo2o.rabbitmq.client.RabbitClient中,首先发送消息的方法如果执行失败会进行重试,重试次数耗尽记录失败消息,项目中抽取了发送消息的工具方法,代码 在jzo2o-rabbitmq中,如下图:

在这里插入图片描述

@Retryable注解可实现方法执行失败进行重试,如下:

@Retryable(value = MqException.class, maxAttempts = 3, backoff = @Backoff(value = 3000, multiplier = 1.5), recover = "saveFailMag")

说明如下:

value:抛出指定异常才会重试

include:和value一样,默认为空,当exclude也为空时,默认所有异常

exclude:指定不处理的异常

maxAttempts:最大重试次数,默认3次

backoff:重试等待策略,默认使用@Backoff,@Backoff的value默认为1000L,我们设置为3000L;表示第一次失败后等待3秒后重试,multiplier(指定延迟倍数)默认为0,如果把multiplier设置为1.5表示每次等待重试时间是上一次的1.5倍,则第一次重试为3秒,第二次为4.5秒,第三次为6.75秒。

Recover: 设置回调方法名,当重试耗尽时,通过recover属性设置回调的方法名。通过@Recover注解定义重试失败后的处理方法,在Recover方法中记录失败消息到数据库。

下边的方法表示将失败消息存储到失败表中

/**
 * @param mqException mq异常消息
 * @param exchange    交换机
 * @param routingKey  路由key
 * @param msg         mq消息
 * @param delay       延迟消息
 * @param msgId       消息id
 */
@Recover
public void saveFailMag(MqException mqException, String exchange, String routingKey, Object msg, Integer delay, String msgId) {
    //发送消息失败,需要将消息持久化到数据库,通过任务调度的方式处理失败的消息
    failMsgDao.save(mqException.getMqId(), exchange, routingKey, JsonUtils.toJsonStr(msg), delay, DateUtils.getCurrentTime() + 10,  ExceptionUtil.getMessage(mqException));
}
1.2.1.2 生产者确认机制

通过MQ的提供的生产者确认机制保证生产消息的可靠性,使用生产者确认机制需要给每个消息指定一个唯一ID,生产者确认机制通过异步回调的方式进行,包括ConfirmCallback和Return回调。

**ConfirmCallback:**消息发送到Broker会有一个结果返回给发送者表示消息是否处理成功:

1)消息成功投递到交换机,返回ack

2)消息未投递到交换机,返回nack

源代码如下:

在com.jzo2o.rabbitmq.client.RabbitClient#sendMsg(java.lang.String, java.lang.String, java.lang.Object, java.lang.Integer, java.lang.Long, boolean)中,在发送消息时指定回调对象

在这里插入图片描述

回调类中回调方法源代码:

如果没有返回ack则将消息记录到失败消息表,如果经过重试后返回了ack说明消息发送成功,此时将消息从失败消息表删除。

在com.jzo2o.rabbitmq.plugins.RabbitMqListenableFutureCallback中

@Override
public void onSuccess(CorrelationData.Confirm result) {
    if(failMsgDao == null){
        return;
    }
    if(!result.isAck()){
        // 执行失败保存失败信息,如果已经存在保存信息,如果不在信息信息
        failMsgDao.save(msgId, exchange, routingKey, msg, delay,DateUtils.getCurrentTime() + 10, "MQ回复nack");
    }else if(isFailMsg && msgId != null){
        // 如果发送的是失败消息,当收到ack需要从fail_msg删除该消息
        failMsgDao.removeById(msgId);
    }
}

Return回调:如果消息发送到交换机成功了但是并没有到达队列,此时会调用ReturnCallback回调方法,在回调方法中我们可以收到失败的消息存入失败消息表以便进行补偿。confirmcallback是针对发消息时的,而returncallback是针对全局。

要使用Return回调需要开启设置:

首先在shared-rabbitmq.yaml中配置rabbitMQ参数,如下:

spring:
  rabbitmq:
    publisher-confirm-type: correlated
    publisher-returns: true
    template:
      mandatory: true
   
说明:
publish-confirm-type:开启publisher-confirm,这里支持两种类型:
simple:同步等待confirm结果,直到超时
correlated:异步回调,定义ConfirmCallback,MQ返回结果时会回调这个ConfirmCallback
publish-returns:开启publish-return功能,同样是基于callback机制,不过是定义ReturnCallback
template.mandatory:定义消息路由失败时的策略。true,则调用ReturnCallback;false:则直接丢弃消息

在com.jzo2o.rabbitmq.config.RabbitMqConfiguration#setApplicationContext中,阅读下边的代码理解写入失败消息表的逻辑。

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    // 获取RabbitTemplate
    RabbitTemplate rabbitTemplate = applicationContext.getBean(RabbitTemplate.class);
    //定义returnCallback回调方法
    rabbitTemplate.setReturnsCallback(
            new RabbitTemplate.ReturnsCallback() {
                @Override
                public void returnedMessage(ReturnedMessage returnedMessage) {
                    byte[] body = returnedMessage.getMessage().getBody();
                    //消息id
                    String messageId = returnedMessage.getMessage().getMessageProperties().getMessageId();
                    String content = new String(body, Charset.defaultCharset());
                    log.info("消息发送失败,应答码{},原因{},交换机{},路由键{},消息id{},消息内容{}",
                            returnedMessage.getReplyCode(),
                            returnedMessage.getReplyText(),
                            returnedMessage.getExchange(),
                            returnedMessage.getRoutingKey(),
                            messageId,
                            content);
                    if (failMsgDao != null) {
                        failMsgDao.save(NumberUtils.parseLong(messageId), returnedMessage.getExchange(), returnedMessage.getRoutingKey(), content, null, DateUtils.getCurrentTime(), "returnCallback");
                    }
                }
            }
    );
}

1.2.2 保证消费消息可靠性

1.2.2.1 三种持久化及确认机制

首先设置消息持久化,保证消息发送到MQ消息不丢失。具体需要设置交换机队列支持持久化,发送消息设置deliveryMode=2

RabbitMQ是通过消费者回执来确认消费者是否成功处理消息的:消费者获取消息后,应该向RabbitMQ发送ACK回执,表明自己已经处理完成消息,RabbitMQ收到ACK后删除消息。

在这里插入图片描述

消费消息失败重试3次,仍失败则将消费失败的消息入库。

通过任务调度扫描失败消息表重新发送,达到一定的次数还未成功则由人工处理。

RabbitMQ提供三个确认模式:

  • manual:手动ack,需要在业务代码结束后,调用api发送ack。

  • auto:自动ack,由spring监测listener代码是否出现异常,没有异常则返回ack;抛出异常则返回nack

  • none:关闭ack,MQ假定消费者获取消息后会成功处理,因此消息投递后立即被删除

由此可知:

  • none模式下,消息投递是不可靠的,可能丢失
  • auto模式类似事务机制,出现异常时返回nack,消息回滚到mq;没有异常,返回ack
  • manual:自己根据业务情况,判断什么时候该ack

一般,我们都是使用默认的auto即可。

在shared-rabbitmq.yaml中配置:

spring:
    rabbitmq:
       ....
        listener:
            simple:
                acknowledge-mode: auto #,出现异常时返回nack,消息回滚到mq;没有异常,返回ack
                retry:
                    enabled: true # 开启消费者失败重试
                    initial-interval: 1000 # 初识的失败等待时长为1秒
                    multiplier: 10 # 失败的等待时长倍数,下次等待时长 = multiplier * last-interval
                    max-attempts: 3 # 最大重试次数
                    stateless: true # true无状态;false有状态。如果业务中包含事务,这里改为false

本项目使用自动ack模式,当消费消息失败会重试,重试3次如果还失败会将消息投递到失败消息队列,由定时任务程序定时读取队列的消息,达到一定的次数还未成功则由人工处理。

1.2.3 保证消息的幂等性

消费者在消费消息时难免出现重复消费的情况,比如:消费者没有向MQ返回ack导致重复消费,所以消费者需要保证消费消息幂等性。

什么是幂等性?幂等性是指不论执行多少次其结果是一致的。

举例:

收到消息需要向数据新增一条记录,如果重复消费则会出现重复添加记录的问题。

下边根据场景分析解决方案:

1、查询操作

本身具有幂等性。

2、添加操作

如果主键是自增则可能重复添加记录。

保证幂等性可以设置数据库的唯一约束,比如:添加学生信息,将学号字段设置为唯一索引,即使重复添加相同的学生同一个学号只会添加一条记录。

3、更新操作

如果是更新一个固定的值,比如: update users set status =1 where id=?,本身具有幂等性。

如果只允许更新成功一次则可以使用token机制,发送消息前生成一个token写入redis,收到消息后解析出token从redis查询token如果成功则说明没有消费,此时更新成功将token从redis删除,当重复消费相同 的消息时由于token已经从redis删除不会再执行更新操作。

4、删除操作

与更新操作类似,如果是删除某个具体的记录,比如:delete from users where id=?,本身具有幂等性。

如果只允许删除成功一次可以采用更新操作相同的方法。

通过以上分析进行总结:

1、使用数据库的唯一约束去控制。

2、使用token机制,如下:

消息具有唯一的ID

发送消息时将消息ID写入Redis

消费时根据消息ID查询Redis判断是否已经消费,如果已经消费则不再消费。

在这里插入图片描述

1.2.4 小结

可以百分百保证MQ的消息可靠性吗?

保证消息可靠性分两个方面:保证生产消息可靠性和保证消费消息可靠性。

保证生产消息可靠性:

生产消息可靠性是通过判断MQ是否发送ack回执,如果发nack表示发送消息失败,此时会进行重发或记录到失败消息表,通过定时任务进行补偿发送。如果Java程序并没有收到回执(如jvm进程异常结束了,或断电等因素),此时将无法保证生产消息的可靠性。

保证消费消息可靠性:

保证消费消息可靠性方案首先保证发送消息设置为持久化,其次通过MQ的消费确认机制保证消费者消费成功消息后再将消息删除。

虽然设置了消息持久化,消息进入MQ首先是在缓存存在,MQ会根据一定的规则进行刷盘,比如:每隔几毫秒进行刷盘,如果在消息还没有保存到磁盘时MQ进程终止,此时将会丢失消息。虽然可以使用镜像队列(用于在 RabbitMQ 集群中复制队列的消息,这样做的目的是提高队列的可用性和容错性,以防止在单个节点故障时导致消息的丢失。)但也不能百分百保证消息不丢失。

虽然我们加了很多保证可靠性的机制,这样也只是去提高消息的可靠性,不能百分百做的可靠,所以使用MQ的场景要考虑这种问题的存在,做好补偿处理任务。

1.3 配置数据同步环境

1.3.1 Canal+MQ同步流程

下边回顾Canal的工作原理,如下图:

1、Canal模拟 MySQL slave 的交互协议,伪装自己为 MySQL slave ,向 MySQL master 发送dump 协议,MySQL的dump协议是MySQL复制协议中的一部分。

2、MySQL master 收到 dump 请求,开始推送 binary log 给 slave (即 canal )。一旦连接建立成功,Canal会一直等待并监听来自MySQL主服务器的binlog事件流,当有新的数据库变更发生时MySQL master主服务器发送binlog事件流给Canal。

3、Canal会及时接收并解析这些变更事件并解析 binary log

通过以上流程可知Canal和MySQL master主服务器之间建立了长连接。

在这里插入图片描述

基于Canal+MQ数据同步流程:

在这里插入图片描述

  1. 服务管理不仅向serve、serve_item、serve_type表写数据,同时也向serve_sync表写数据,serve_sync用于Canal同步数据使用。
  2. 向serve_sync写数据产生binlog
  3. Canal请求读取binlog,并解析出serve_sync表的数据更新日志,并发送至MQ的数据同步队列。
  4. 异步同步程序监听MQ的数据同步队列,收到消息后解析出serve_sync表的更新日志。
  5. 异步同步程序根据serve_sync表的更新日志请求Elasticsearch添加、更新、删除索引文档。

最终实现了将MySQL中的serve_sync表的数据同步至Elasticsearch

本节实现将MySQL的变更数据通过Canal写入MQ。

1.3.2 配置Canal+MQ数据同步环境

根据Canal+MQ同步流程,下边进行如下配置:

  1. 配置Mysql主从同步,开启MySQL主服务器的binlog
  2. 安装Canal并配置,保证Canal连接MySQL主服务器成功
  3. 安装RabbitMQ,并配置同步队列。
  4. 在Canal中配置RabbitMQ的连接信息,保证Canal收到binlog消息写入MQ

对于异步程序监听MQ通过Java程序中实现。

  • 清理docker容器日志
cd /data/soft/
sh clean_docker_log.sh 
  • 启动canal和mq
docker restart rabbitmq canal 
  • 使用命令查看是否打开binlog模式:

  • SHOW VARIABLES LIKE 'log_bin'
    

在这里插入图片描述

1.3.2.1 配置Canal+RabbitMQ

下边通过配置Canal与RabbitMQ,保证Canal收到binlog消息将数据发送至MQ。

最终我们要实现的是:

修改jzo2o-foundations数据库下的serve_sync表的数据后通过canal将修改信息发送到MQ。

1、在Canal中配置RabbitMQ的连接信息

修改/data/soft/canal/canal.properties

# tcp, kafka, rocketMQ, rabbitMQ
canal.serverMode = rabbitMQ

##################################################
#########                     RabbitMQ             #############
##################################################
rabbitmq.host = 192.168.101.68
rabbitmq.virtual.host = /xzb
rabbitmq.exchange = exchange.canal-jzo2o
rabbitmq.username = xzb
rabbitmq.password = xzb
rabbitmq.deliveryMode = 2

本项目用于数据同步的MQ交换机:exchange.canal-jzo2o

虚拟主机地址:/xzb

账号和密码:xzb/xzb

rabbitmq.deliveryMode = 2 设置消息持久化

2、设置需要监听的mysql库和表

修改/data/soft/canal/instance.properties

  • canal.instance.filter.regex 需要监听的mysql库和表
    • 全库: .*\\..*
    • 指定库下的所有表: canal\\..*
    • 指定库下的指定表: canal\\.canal,test\\.test
      • 库名\\.表名:转义需要用\,使用逗号分隔多个库

这里配置监听 jzo2o-foundations数据库下serve_sync表,如下:

canal.instance.filter.regex=jzo2o-foundations\\.serve_sync

3、在Canal配置MQ的topic

这里使用动态topic,格式为:topic:schema.table,topic:schema.table,topic:schema.table

配置如下:

canal.mq.dynamicTopic=canal-mq-jzo2o-foundations:jzo2o-foundations\\.serve_sync

上边的配置表示:对jzo2o-foundations数据库的serve_sync表的修改消息发到topic为canal-mq-jzo2o-foundations关联的队列,会将当前携带topic的消息转发至交换机exchange.canal-jzo2o

4、进入rabbitMQ配置交换机和队列

进入rabbitmq管理界面 http://192.168.101.68:15672/

账号:czri 密码:czri1234

查看交换机

在这里插入图片描述
点击交换机,查看其绑定的队列

在这里插入图片描述

1.3.2.2 测试

查看当前master的binlog和偏移量

SHOW MASTER status

在这里插入图片描述

复位

reset master

复位后查询

在这里插入图片描述

删除canal的同步日志,保证master和canal是同时开始同步的

cd /data/soft/canal/conf
rm meta.dat

重新启动canal,查看其日志

docker restart canal
cd /data/soft/canal/logs
tail -f xzb-canal.log

在这里插入图片描述

并无报错

修改jzo2o-foundations数据库的serve_sync表的数据,稍等片刻查看canal-mq-jzo2o-foundations队列,如果队列中有的消息说明同步成功,如下图:

修改serve_sync数据

在这里插入图片描述

查看canal日志

在这里插入图片描述

查看mq

在这里插入图片描述

点开队列后Get Message

在这里插入图片描述

再改回来

在这里插入图片描述

1.3.2.3 数据不同步解决方法

如果停机后导致canal数据不同步解决方法:

当发现修改了数据库后修改的数据并没有发送到MQ,通过查看Canal的日志发现下边的错误。

进入Canal目录,查看日志:

cd /data/soft/canal/logs
tail -f logs/xzb-canal.log 

Canal报错如下:

2023-09-22 08:34:40.802 [destination = xzb-canal , address = /192.168.101.68:3306 , EventParser] WARN  c.a.o.c.p.inbound.mysql.rds.RdsBinlogEventParserProxy - ---> find start position successfully, EntryPosition[included=false,journalName=mysql-bin.000055,position=486221,serverId=1,gtid=,timestamp=1695341830000] cost : 13ms , the next step is binlog dump
2023-09-22 08:34:40.811 [destination = xzb-canal , address = /192.168.101.68:3306 , EventParser] ERROR c.a.o.canal.parse.inbound.mysql.dbsync.DirectLogFetcher - I/O error while reading from client socket
java.io.IOException: Received error packet: errno = 1236, sqlstate = HY000 errmsg = Could not find first log file name in binary log index file
        at com.alibaba.otter.canal.parse.inbound.mysql.dbsync.DirectLogFetcher.fetch(DirectLogFetcher.java:102) ~[canal.parse-1.1.5.jar:na]
        at com.alibaba.otter.canal.parse.inbound.mysql.MysqlConnection.dump(MysqlConnection.java:238) [canal.parse-1.1.5.jar:na]
        at com.alibaba.otter.canal.parse.inbound.AbstractEventParser$1.run(AbstractEventParser.java:262) [canal.parse-1.1.5.jar:na]
        at java.lang.Thread.run(Thread.java:748) [na:1.8.0_181]

找到关键的位置:Could not find first log file name in binary log index file

根据日志分析是Canal找不到mysql-bin.000055 的486221位置,原因是mysql-bin.000055文件不存在,这是由于为了节省磁盘空间将binlog日志清理了。

解决方法:

把canal复位从最开始开始同步的位置。

1)首先重置mysql的bin log:

连接mysql执行:

reset master

执行后所有的binlog删除,从000001号开始

通过

show master status

查看 ,结果显示 mysql-bin.000001

2)先停止canal

docker stop canal

3)删除meta.dat

rm -rf /data/soft/canal/conf/meta.dat 

4)再启动canal

docker start canal

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

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

相关文章

Linux连接工具MobaXterm详细使用教程

目录 一、MobaXterm的下载 1、访问官网 2、下载便携版 3、启动MobaXterm 二、MobaXterm基本使用设置 1、新建会话 2、使用ssh连接第一个会话 3、设置主密码 4、主界面 5、sftp文件上传下载 6、文件拖拽的上传下载 7.右键粘贴 8、查看服务器监测信息​编辑 9、个…

文件扫描工具哪个好?便捷的文件扫描工具推荐

对于初入职场的大学毕业生,申请就业补贴是一项不可忽视的福利。 它不仅能够为新生活带来经济上的缓解,也有助于职业生涯的顺利起步。面对申请过程中需提交的文件,如纸质劳动合同,不必烦恼。市面上众多文件扫描软件能助你一臂之力…

Oracle最终还是杀死了MySQL

起因 大约15年前,Oracle收购了Sun公司,从而也拥有了MySQL,互联网上关于Oracle何时会“扼杀MySQL”的讨论此起彼伏。 当时流传着各种理论:从彻底扼杀 MySQL 以减少对 Oracle 专有数据库的竞争,到干掉 MySQL 开源项目&…

vcpkg安装opencv中的特殊问题记录(无法找到opencv_corexd.dll)

我是按照网上的vcpkg安装opencv方法进行的(比如这篇:从0开始在visual studio上安装opencv(超详细,针对小白)),但是中间出现了一些别人没有遇到的问题,虽然原因没有找到,但…

离子污染测试仪有哪些检测方法?校准机构如何选择?

离子污染测试仪是许多生产企业会使用到的一种仪器,作为一种高精度的操作仪器,在长时间的使用下,仪器磨损和失准也是常见状况,因此企业都会进行定期校准来维护仪器,那么离子污染测试仪有哪些检测方法?校准机…

深度学习500问——Chapter11:迁移学习(3)

文章目录 11.3 迁移学习的常用方法 11.3.1 数据分布自适应 11.3.2 边缘分布自适应 11.3.3 条件分布自适应 11.3.4 联合分布自适应 11.3.5 概率分布自适应方法优劣性比较 11.3.6 特征选择 11.3.7 统计特征对齐方法 11.3 迁移学习的常用方法 11.3.1 数据分布自适应 数据分布自适…

阿里拍卖资产推荐算法 召回进展年中总结

阿里拍卖是阿里巴巴旗下拍卖平台,覆盖房产、机动车、土地、债权等类目。召回策略作为推荐场景的第一环,决定了整个推荐系统的上限,目前包含了包括向量召回、I2I、LBS2I、C2I等多路召回。召回的核心目标是尽可能的返回用户所有可能会感兴趣的商…

教你使用Python玩转MySQL数据库,大数据导入不再是难题!

数据分析离不开数据库,如何使用python连接MySQL数据库,并进行增删改查操作呢? 我们还会遇到需要将大批量数据导入数据库的情况,又该如何使用Python进行大数据的高效导入呢? 本文会一一讲解,并配合代码和实…

Spring Boot组件化与参数校验

Spring Boot组件化与参数校验 Spring Boot版本选择 2.3.x版本 2.6.x版本 Spring Boot核心思想 约定大于配置,简化繁琐的配置 Spring Boot自动配置原理 SpringBootApplication: Spring Boot应用标注在某个类上说明这个类是SpringBoot的主配置类,Spr…

Vue3学习日记(day5)

接下来我们继续探讨文档 event对象 在Vue.js中,$event变量或箭头函数中的event参数用于捕获原始的DOM事件对象。这个对象包含了所有与特定事件相关的信息,比如鼠标点击的位置、键盘按键的键码、触摸事件的触摸点等。 当你在事件处理器中需要做一些基于…

前端时钟页面(JSP语言)

前端时钟页面(JSP语言) 一、效果图 二、介绍 1.目前市面上很多时钟组件,像电子时钟,3D时钟,Echarts画的时钟 2.这款时钟,是本人多年前寻找并修改的,感觉效果还不错 3.目前这是jsp写的,后面有时间会用Vue写…

口罩佩戴智能监测摄像机

智能监测摄像机在现代城市安全管理中扮演着关键角色,尤其是像口罩佩戴智能监测摄像机这样的设备,其应用正在日益扩展,对于公共卫生和安全至关重要。 这类摄像机利用先进的图像识别技术,能够实时监测人群中是否佩戴口罩。通过高精度…

CVPR2023论文速览Scenes相关49篇

CVPR2023论文速览Scenes Paper1 CLIP2Scene: Towards Label-Efficient 3D Scene Understanding by CLIP 摘要原文: Contrastive Language-Image Pre-training (CLIP) achieves promising results in 2D zero-shot and few-shot learning. Despite the impressive performance …

05. Java多线程 join 方法

1. 前言 本节对 join 方法进行深入的剖析,主要内容点如下: 了解 join 方法的作用,初步的理解 join 方法的使用带来的效果是学习本节内容的基础;了解 join 方法异常处理,我们在使用 join 方法是,需要对 jo…

【odoo】常用的字符转义:“>“,“<“,““,“/“等

概要 字符转义是指在编写代码或处理文本数据时&#xff0c;将特殊字符转换为另一种形式&#xff0c;以便在特定的上下文中正确解析和处理这些字符。 内容 特殊字符描述XML转义表示法&和符号&amp;<小于符号<>大于符号>"双引号&quot;单引号&ap…

优惠卷秒杀(并发问题)

Redis实战篇 | Kyles Blog (cyborg2077.github.io) 目录 一、Redis实现全局唯一id 二、添加优惠卷 三、实现秒杀下单 四、解决超卖问题&#xff08;库存为负&#xff09; 乐观锁解决超卖问题&#xff08;CAS法&#xff09; 五、实现一人一单 ​编辑 悲观锁解决一人一单问题…

C++ 教程 - 05 构建编译

文章目录 构建工具cmake安装与使用CMakeLists.txt编写使用案例 构建工具 cmake, Cross Platform Make&#xff0c; &#xff08;对C&#xff09;跨平台编译工具&#xff0c;将CMakeLists.txt 文件编译为对应的文件&#xff0c;如linux下的 Makefile&#xff0c;然后使用make命…

这几个都秒懂的都是资深程序猿/媛了吧?

放松第三期下&#xff0c;不讲编程技术&#xff0c;来看看几个冷笑话&#xff0c;最后一个最近还真的遇到了T_T ......想知道有多少人是秒懂的&#xff0c;欢迎大家在评论区交流讨论分享自己身边的搞笑趣事。 大家身边还有什么搞笑趣事呢&#xff1f;欢迎评论区留言交流分享&am…

收银系统源码推荐,线下线上一体化收银系统

1.收银系统源码开发语言 核心开发语言: PHP、HTML5、Dart后台接口: PHP7.3后台管理网站: HTML5vue2.0element-uicssjs收银端【安卓/PC收银】: Dart3&#xff0c;框架&#xff1a;Flutter 3.11.0-6.0.pre.27商家小程序助手端: uniapp线上商城: uniapp 2.功能介绍 支持测试体验…

SARscape——Refined Lee滤波

目录 一、算法原理1、概述2、参考文献 二、软件操作三、结果展示1、原始图像2、滤波结果 一、算法原理 1、概述 精致Lee滤波通过定义8种非正方形局部窗口&#xff0c;将均匀区域像素值等于其平均值&#xff0c;将非均匀区域近似于局部窗口中心像素值。 精致 Lee 滤波 8 种模板…