前言:
实现MySQL和Redis数据同步有以下几种常见方法:
- 使用数据库触发器 可以在MySQL数据库中创建触发器,当有数据更新时,自动触发并将更新的数据同步到Redis中。这种方法比较简单,但可能会对数据库性能产生一定影响。
- 使用定时任务 可以编写定时任务,定期从MySQL中读取数据,并将数据同步到Redis中。这种方法可以根据实际需要灵活设置同步频率,但可能会有一定的延迟。
- 使用数据库写操作的日志 可以监听MySQL数据库的binlog(二进制日志),当有写操作的时候,解析binlog,将更新的数据同步到Redis中。这种方法可以实现实时同步,但需要对数据库的binlog进行解析和处理,较为复杂。
- 使用消息队列 可以将MySQL中的数据变更作为消息发送到消息队列中,然后订阅这些消息并将数据同步到Redis中。这种方法可以实现解耦和异步处理,但需要额外引入消息队列组件。
- 使用Canal 使用Canal实现Mysql和Redis的数据同步
需要根据具体情况选择合适的方法。要考虑数据的一致性、同步延迟、性能以及系统的复杂度等因素。
推荐使用Canal的方式,进行异步同步。其次是MQ方式
什么是Canal:
Canal是阿里巴巴开源的一款基于数据库增量日志解析的中间件,可以实时监听Mysql的Binlog变更,将变更数据解析为指定格式后推送给消费端。
在使用Canal实现Mysql和Redis的数据同步时,你可以通过Canal监听Mysql的Binlog,将变更数据解析为适当的格式,然后将变更数据推送给Redis作为消费端,实现数据的同步。
具体的实现步骤如下:
- 配置Canal和Redis的相关配置信息,包括Mysql数据库连接信息、Canal的监听端口、Redis的连接信息等。
- 启动Canal Server,开启Binlog日志解析功能。
- 开发Canal Client,用于监听Canal Server推送的Binlog数据。
- 在Canal Client中,将解析后的变更数据转换为合适的格式,并通过Redis的客户端API将数据写入Redis。
- 验证数据同步的效果,通过模拟Mysql数据的增删改操作,观察Redis中的数据是否同步更新。
需要注意的是,Canal并不直接支持将Binlog数据推送到Redis,需要自己开发Canal Client来实现转换和推送的逻辑。
总的来说,使用Canal实现Mysql和Redis的数据同步是可行的,但需要根据具体的需求开发和配置对应的Canal Client来实现数据的转换和推送。
具体代码:
1.首先mysql数据库得开启binlog
(这里不演示如何开启binlog,只演示如何用Canal实现Mysql Redis数据同步)
2.导入canal依赖
<!--Canal 依赖-->
<dependency>
<groupId>top.javatool</groupId>
<artifactId>canal-spring-boot-starter</artifactId>
<version>1.2.1-RELEASE</version>
</dependency>
3.application.yml配置设置连接
#canal配置信息
canal:
destination: example
server: 121.77.14.222:11111 #连接地址
4.在要监听的表的实体类上加上注解
package com.sks.product.entity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Builder;
import lombok.Data;
import org.springframework.data.annotation.Id;
import javax.persistence.Column;
import java.io.Serializable;
import java.util.Date;
import static com.baomidou.mybatisplus.annotation.IdType.INPUT;
/**
演示如何加注解实体类
@author common
@date 2022/04/17
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TableName("sks_product_info")
public class ProductInfoEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
1.必须加上@Id,要不然canal监控不到表
*/
@Id
@TableId()
private Long id;
/**
2.实体类字段名与数据库字段名不一致 ,需要加上@Column(name = "")注解
*/
@Column(name = "product_name")
private String productName;
/**
2.实体类字段名与数据库字段名不一致 ,需要加上@Column(name = "")注解
*/
@Column(name = "classify_id")
private Long classifyId;
private Integer state;
private Integer acura;
/**
2.实体类字段名与数据库字段名不一致 ,需要加上@Column(name = "")注解
*/
@Column(name = "view_image")
private String viewImage;
/**
2.实体类字段名与数据库字段名不一致 ,需要加上@Column(name = "")注解
*/
@Column(name = "default_spec_id")
private Long defaultSpecId;
}
5.复写 EntryHandler<需要监听实体类> 接口 得到三个方法 insert() update() delete()
package com.sks.product.canal;
import com.sks.commons.util.RedisUtil;
import com.sks.product.config.RedisConfig;
import com.sks.product.entity.ProductCarouselEntity;
import org.springframework.stereotype.Component;
import top.javatool.canal.client.annotation.CanalTable;
import top.javatool.canal.client.handler.EntryHandler;
/**
1.首先加上 @CanalTable("需要监控的表名") 注解
2.实现 EntryHandler<需要监控的表对应的实体类> 借口
3.按 alt键+insert键,会得到三个方法 ,分别是 增 ,改 ,删
4.在这三个方法中分别写对应Redis 增,改, 删 方法 ,然后就可以了
5.当你用canal监控的mysql表发生增,改,删事件时,canal会自动同步Redis里面的数据
@author common
@date 2022/04/27
*/
@CanalTable("sks_product_carousel")
@Component
public class ProductCarouselHandle implements EntryHandler<ProductCarouselEntity> {
/**
插入
只要canal监控的mysql表,发生增加操作,就会执行此方法
@param productCarouselEntity 演示实体类
*/
@Override
public void insert(ProductCarouselEntity productCarouselEntity) {
//这是我向Redis里面插入数据的方法(你们可以写自己的方法)
RedisUtil.hSetNotExist(RedisConfig.PRODUCT_CAROUSEL.getMsg(),productCarouselEntity.getId(),productCarouselEntity);
}
/**
* 更新
*
*
*只要canal监控的mysql表,发生更新操作,就会执行此方法
*
*
* @param before 之前
* @param after 后
*/
@Override
public void update(ProductCarouselEntity before, ProductCarouselEntity after) {
//这是我向Redis里面更新数据的方法(你们可以写自己的方法)
RedisUtil.hSetNotExist(RedisConfig.PRODUCT_CAROUSEL.getMsg(),after.getId(),after);
}
/**
* 删除
*
*
*
*只要canal监控的mysql表,发生删除操作,就会执行此方法
*
*
* @param productCarouselEntity 轮播图实体产品
*/
@Override
public void delete(ProductCarouselEntity productCarouselEntity) {
//这是我向Redis里面删除数据的方法(你们可以写自己的方法)
RedisUtil.hDel(RedisConfig.PRODUCT_CAROUSEL.getMsg(),productCarouselEntity.getId());
}
}
就可以实现Mysql Redis数据同步了