Docker 环境安装、MySQL 安装、Redis 安装、Canal 安装、MySQL文件配置和 Canal 文件配置请移步 Canal通过TCP实现MySQL与Redis同步 查看。
docker pull zookeeper:3.7.0
docker run --name zookeeper -p 2181:2181 --restart always -d zookeeper:3.7.0
–restart always 的设置可以使 docker 启动时同时启动 Zookeeper。
docker run -d --name kafka -p 9092:9092 -e KAFKA_BROKER_ID=0
-e KAFKA_ZOOKEEPER_CONNECT=10.0.0.4:2181 -e
KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://10.0.0.4:9092 -e
KAFKA_LISTENERS=PLAINTEXT://0.0.0.0:9092 -t wurstmeister/kafka:2.13-2.8.1
docker exec -it kafka /bin/sh
cd opt/kafka_2.13-2.8.1
kafka-topics.bat --create --zookeeper localhost:2181
--replication-factor 1 --partitions 1 --topic mall
docker exec -it canal /bin/bash
vi canal-server/conf/instance.properties
vi canal-server/conf/example/instance.properties
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
kafka:
bootstrap-servers: 10.0.0.4:9092
consumer:
group-id: mall-master
package com.macro.mall.canal;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* @ClassName CanalBean
* @Description TODO
* @Author 听秋
* @Date 2022/5/9 19:46
* @Version 1.0
**/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CanalBean {
/** 数据 */
private List<UmsAdmin> data;
/** 数据库名称 */
private String database;
private long es;
/** 递增,从1开始 */
private int id;
/** 是否是DDL语句 */
private boolean isDdl;
/** 表结构的字段类型 */
private MysqlType mysqlType;
/** UPDATE语句,旧数据 */
private String old;
/** 主键名称 */
private List<String> pkNames;
/** sql语句 */
private String sql;
private SqlType sqlType;
/** 表名 */
private String table;
private long ts;
/** (新增)INSERT、(更新)UPDATE、(删除)DELETE、(删除表)ERASE等等 */
private String type;
}
package com.macro.mall.canal;
/**
* @ClassName MysqlType
* @Description TODO
* @Author 听秋
* @Date 2022/5/9 19:48
* @Version 1.0
**/
public class MysqlType {
private String id;
private String username;
private String password;
private String icon;
private String email;
private String nickName;
private String note;
private String createTime;
private String loginTime;
private String status;
}
package com.macro.mall.canal;
/**
* @ClassName SqlType
* @Description TODO
* @Author 听秋
* @Date 2022/5/9 19:49
* @Version 1.0
**/
public class SqlType {
private int id;
private int username;
private int password;
private int icon;
private int email;
private int nickName;
private int note;
private int createTime;
private int loginTime;
private int status;
}
package com.macro.mall.canal;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @ClassName CanalConsumer
* @Description TODO
* @Author 听秋
* @Date 2022/5/9 19:49
* @Version 1.0
**/
@Component
@Slf4j
public class CanalConsumer {
@Autowired
private RedisTemplate redisTemplate;
private static String REDIS_DATABASE = "mall";
private static String REDIS_KEY_ADMIN = "ums:admin";
private static String insert = "INSERT";
private static String update = "UPDATE";
@KafkaListener(topics = "mall")
public void receive(ConsumerRecord<?, ?> consumer) {
String value = (String) consumer.value();
log.info("topic名称:{}, key:{}, 分区位置:{}, 下标:{}, value:{}", consumer.topic(), consumer.key(),
consumer.partition(), consumer.offset(), value);
// 转换为javaBean
CanalBean canalBean = JSONObject.parseObject(value, CanalBean.class);
// 获取类型
String type = canalBean.getType();
// 获取是否是DDL语句
boolean isDdl = canalBean.isDdl();
// 不是DDL语句
if (!isDdl) {
List<UmsAdmin> UmsAdmins = canalBean.getData();
if (insert.equals(type) || update.equals(type)) {
//新增或更新语句
for (UmsAdmin umsAdmin : UmsAdmins) {
//新增到redis中
redisTemplate.opsForValue().set(REDIS_DATABASE + ":" + REDIS_KEY_ADMIN + ":" + umsAdmin.getUsername(),
JSONObject.toJSONString(umsAdmin));
}
} else {
// 删除语句
for (UmsAdmin umsAdmin : UmsAdmins) {
//从redis中删除
redisTemplate.delete(REDIS_DATABASE + ":" + REDIS_KEY_ADMIN + ":" + umsAdmin.getUsername());
}
}
}
}
}