基于canal的Redis缓存双写

canal地址:alibaba/canal: 阿里巴巴 MySQL binlog 增量订阅&消费组件 (github.com)icon-default.png?t=O83Ahttps://github.com/alibaba/canal

1. 准备

1.1 MySQL

查看主机二进制日志

show master status

查看binlog是否开启

show variables like 'log_bin'

授权canal连接MySQL账号

CREATE USER 'canal'@'%' IDENTIFIED BY 'canal';
GRANT ALL PRIVILEGES ON *.* TO 'canal'@'%';
FLUSH PRIVILEGES;SELECT * FROM mysql.user;

1.2 canal 

下载canal,上传redis所在服务器

 解压

修改conf/example下instance.properties

修改mysql主机ip

修改在mysql新建的canal账户 

启动

 2. canal客户端编写

新建表

CREATE TABLE `t_user` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`userName` varchar(100) NOT NULL,PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4

依赖

<dependency><groupId>com.alibaba.otter</groupId><artifactId>canal.client</artifactId><version>1.1.4</version>
</dependency>
package com.example.redis.utils;import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;public class RedisUtils
{public static final String  REDIS_IP_ADDR = "192.168.229.102";// public static final String  REDIS_pwd = "111111";public static JedisPool jedisPool;static {JedisPoolConfig jedisPoolConfig=new JedisPoolConfig();jedisPoolConfig.setMaxTotal(20);jedisPoolConfig.setMaxIdle(10);jedisPool=new JedisPool(jedisPoolConfig,REDIS_IP_ADDR,6379,10000);}public static Jedis getJedis() throws Exception {if(null!=jedisPool){return jedisPool.getResource();}throw new Exception("Jedispool is not ok");}}
package com.example.redis;import com.alibaba.fastjson.JSONObject;
import com.alibaba.otter.canal.client.CanalConnector;
import com.alibaba.otter.canal.client.CanalConnectors;
import com.alibaba.otter.canal.protocol.CanalEntry.*;
import com.alibaba.otter.canal.protocol.Message;
import com.example.redis.utils.RedisUtils;
import org.springframework.boot.test.context.SpringBootTest;
import redis.clients.jedis.Jedis;import java.net.InetSocketAddress;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;@SpringBootTest
public class CanalTest {public static final Integer _60SECONDS = 60;public static final String  REDIS_IP_ADDR = "192.168.229.102";private static void redisInsert(List<Column> columns){JSONObject jsonObject = new JSONObject();for (Column column : columns){System.out.println(column.getName() + " : " + column.getValue() + "    update=" + column.getUpdated());jsonObject.put(column.getName(),column.getValue());}if(columns.size() > 0){try(Jedis jedis = RedisUtils.getJedis()){jedis.set(columns.get(0).getValue(),jsonObject.toJSONString());}catch (Exception e){e.printStackTrace();}}}private static void redisDelete(List<Column> columns){JSONObject jsonObject = new JSONObject();for (Column column : columns){jsonObject.put(column.getName(),column.getValue());}if(columns.size() > 0){try(Jedis jedis = RedisUtils.getJedis()){jedis.del(columns.get(0).getValue());}catch (Exception e){e.printStackTrace();}}}private static void redisUpdate(List<Column> columns){JSONObject jsonObject = new JSONObject();for (Column column : columns){System.out.println(column.getName() + " : " + column.getValue() + "    update=" + column.getUpdated());jsonObject.put(column.getName(),column.getValue());}if(columns.size() > 0){try(Jedis jedis = RedisUtils.getJedis()){jedis.set(columns.get(0).getValue(),jsonObject.toJSONString());System.out.println("---------update after: "+jedis.get(columns.get(0).getValue()));}catch (Exception e){e.printStackTrace();}}}public static void printEntry(List<Entry> entrys) {for (Entry entry : entrys) {if (entry.getEntryType() == EntryType.TRANSACTIONBEGIN || entry.getEntryType() == EntryType.TRANSACTIONEND) {continue;}RowChange rowChage = null;try {//获取变更的row数据rowChage = RowChange.parseFrom(entry.getStoreValue());} catch (Exception e) {throw new RuntimeException("ERROR ## parser of eromanga-event has an error,data:" + entry.toString(),e);}//获取变动类型EventType eventType = rowChage.getEventType();System.out.println(String.format("================&gt; binlog[%s:%s] , name[%s,%s] , eventType : %s",entry.getHeader().getLogfileName(), entry.getHeader().getLogfileOffset(),entry.getHeader().getSchemaName(), entry.getHeader().getTableName(), eventType));for (RowData rowData : rowChage.getRowDatasList()) {if (eventType == EventType.INSERT) {redisInsert(rowData.getAfterColumnsList());} else if (eventType == EventType.DELETE) {redisDelete(rowData.getBeforeColumnsList());} else {//EventType.UPDATEredisUpdate(rowData.getAfterColumnsList());}}}}public static void main(String[] args){System.out.println("---------O(∩_∩)O哈哈~ initCanal() main方法-----------");//=================================// 创建链接canal服务端CanalConnector connector = CanalConnectors.newSingleConnector(new InetSocketAddress(REDIS_IP_ADDR,11111), "example", "", "");int batchSize = 1000;//空闲空转计数器int emptyCount = 0;System.out.println("---------------------canal init OK,开始监听mysql变化------");try {connector.connect();//connector.subscribe(".*\\..*");connector.subscribe("redis_canal.t_user");connector.rollback();int totalEmptyCount = 10 * _60SECONDS;while (emptyCount < totalEmptyCount) {System.out.println("我是canal,每秒一次正在监听:"+ UUID.randomUUID().toString());Message message = connector.getWithoutAck(batchSize); // 获取指定数量的数据long batchId = message.getId();int size = message.getEntries().size();if (batchId == -1 || size == 0) {emptyCount++;try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }} else {//计数器重新置零emptyCount = 0;printEntry(message.getEntries());}connector.ack(batchId); // 提交确认// connector.rollback(batchId); // 处理失败, 回滚数据}System.out.println("已经监听了"+totalEmptyCount+"秒,无任何消息,请重启重试......");} finally {connector.disconnect();}}}

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.3.3</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>Redis</artifactId><version>0.0.1-SNAPSHOT</version><name>Redis</name><description>Redis</description><url/><licenses><license/></licenses><developers><developer/></developers><scm><connection/><developerConnection/><tag/><url/></scm><properties><java.version>17</java.version></properties><dependencies><!--SpringBoot通用依赖模块--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.28</version><scope>compile</scope></dependency><dependency><groupId>com.alibaba.otter</groupId><artifactId>canal.client</artifactId><version>1.1.4</version></dependency><!-- 数据库相关配置启动器 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><!-- druid启动器的依赖  --><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-3-starter</artifactId><version>1.2.18</version></dependency><!-- 驱动类--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.28</version></dependency><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>3.8.0</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>2.0.0</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
spring.application.name=Redis
server.port=8080# ========================redis??=====================
spring.data.redis.database=0
spring.data.redis.host=192.168.229.102
spring.data.redis.port=6379
spring.data.redis.lettuce.pool.max-active=8
spring.data.redis.lettuce.pool.max-wait=-1ms
spring.data.redis.lettuce.pool.max-idle=8
spring.data.redis.lettuce.pool.min-idle=0# ========================alibaba.druid=====================
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/redis_canal?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=abc123
spring.datasource.druid.test-while-idle=false

canal启动失败可能是没有durid依赖,将durid放入lib下即可

Central Repository: com/alibaba/druid/1.2.22 (maven.org)icon-default.png?t=O83Ahttps://repo1.maven.org/maven2/com/alibaba/druid/1.2.22/

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

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

相关文章

【OpenCV3】图像的翻转、图像的旋转、仿射变换之图像平移、仿射变换之获取变换矩阵、透视变换

1 图像的放大与缩小 2 图像的翻转 3 图像的旋转 4 仿射变换之图像平移 5 仿射变换之获取变换矩阵 6 透视变换 1 图像的放大与缩小 resize(src, dsize[, dst[, fx[, fy[, interpolation]]]]) src: 要缩放的图片dsize: 缩放之后的图片大小, 元组和列表表示均可.dst: 可选参数, 缩…

【无标题】XSS安全防护:responseBody (输入流可重复读) 配置

接上文:配置XSS过滤器 XXS 安全防护:拦截器+注解实现校验-CSDN博客XSS(跨站脚本)攻击是一种网络安全威胁,允许攻击者注入恶意脚本到看似安全的网站。当用户浏览这些被注入恶意代码的网页时,恶意脚本会在用户的浏览器环境中执行,这可能导致多种安全问题,如窃取敏感数据、…

将添加功能的抽屉剥离,在父组件调用思路

一、新建组件 新建AddRoleEditerDrawer.vue<template><div><el-drawer v-model"dialog" title"添加角色" :before-close"handleClose" direction"rtl" colse"cancelForm"class"demo-drawer" moda…

「数学::质数」试除法 / Luogu P5736(C++)

概述 在质数的第一节我们来讲解试除法。 质数是指在大于1的自然数中只能被1和它自己整除的数。 我们可以利用这一除法性质对质数进行判定。 Luogu P5736&#xff1a; 输入 n 个不大于 10^5 的正整数。要求全部储存在数组中&#xff0c;去除掉不是质数的数字&#xff0c;依…

LLM Attention and Rotary Position Embedding(旋转位置编码)

旋转位置编码&#xff08;Rotary Position Embedding&#xff0c;RoPE&#xff09;是一种能够将相对位置信息依赖集成Attention计算里的方法。就是在做词表映射的时候不是单一的进行一个embedding计算&#xff0c;还考虑位置信息。 一些资料 [1] https://arxiv.org/pdf/2104.0…

面对养老困局我心安若素

“2025年&#xff0c;我们需要注意什么&#xff1f;是复杂的国际环境么&#xff1f;明年对于我国70岁以上的老年人来说这可不是主要关心的问题。反而有这两件事情需要他们来关注&#xff0c;如果70岁老人不提前做好准备&#xff0c;可能会有非常严重的后果......”这是昨天发表…

鸿蒙轻内核M核源码分析系列十五 CPU使用率CPUP

往期知识点记录&#xff1a; 鸿蒙&#xff08;HarmonyOS&#xff09;应用层开发&#xff08;北向&#xff09;知识点汇总 轻内核M核源码分析系列一 数据结构-双向循环链表 轻内核M核源码分析系列二 数据结构-任务就绪队列 鸿蒙轻内核M核源码分析系列三 数据结构-任务排序链表 轻…

国产脑机全面超越马斯克Nearlink

&#x1f4a5;&#x1f4a5;&#x1f4a5;刚刚&#xff0c;世界首富马斯克同学已经是完全懵逼了&#xff0c;心态都崩了&#xff01;因为今天爆出来了一个轰动了全世界科技界的大新闻&#xff0c;国产脑机在多个维度上全面超越了马斯克的Nearlink&#xff01; &#x1f4a5;&am…

SpringBoot2:请求处理原理分析-RESTFUL风格接口

一、RESTFUL简介 Rest风格支持&#xff08;使用HTTP请求方式&#xff0c;动词来表示对资源的操作&#xff09; 以前&#xff1a;/getUser 获取用户 /deleteUser 删除用户 /editUser 修改用户 /saveUser 保存用户 现在&#xff1a; /user GET-获取用户 DELETE-删除用户 PUT-修改…

数据仓库技术选型方案文档

关联博客&#xff1a; 数据仓库技术选型方案文档 Flink CDC MySQL数据同步到Doris表同步配置生成工具类 新版报表系统&#xff08;明细报表、看板、数据大屏&#xff09;方案&介绍 文章目录 数据仓库技术选型背景现状现状架构目标架构业务反馈&痛点问题&#xff1a;原因…

随手记:小程序体积超出2M包大小如何优化

小程序的包体积限制是2M&#xff0c;超出包大小如何优化 先简单列出&#xff0c;最近比较忙&#xff0c;后续优化明细&#xff0c;有着急的先留言踢我 1.分包 留几个主要的页面体积小的&#xff0c;剩下的在page.json中拆到subpackages中&#xff0c;简单举个例子 "page…

多维动态规划-面试高频!-最长公共子序列和最长公共子串、回文串-c++实现和详解

1143. 最长公共子序列 中等 给定两个字符串 text1 和 text2&#xff0c;返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 &#xff0c;返回 0 。 一个字符串的 子序列 是指这样一个新的字符串&#xff1a;它是由原字符串在不改变字符的相对顺序的情况下删…

力扣1049-最后一块石头的重量II(Java详细题解)

题目链接&#xff1a;1049. 最后一块石头的重量 II - 力扣&#xff08;LeetCode&#xff09; 前情提要&#xff1a; 因为本人最近都来刷dp类的题目所以该题就默认用dp方法来做。 最近刚学完01背包&#xff0c;所以现在的题解都是以01背包问题为基础再来写的。 如果大家不懂…

FPGA实现串口升级及MultiBoot(二)FPGA启动流程

这个系列开篇肯定要先了解FPGA的启动流程&#xff0c;试想一下&#xff1a;我想实现MultiBoot&#xff0c;那么我应该在什么时候开始升级&#xff0c;升级失败后FPGA进行了哪些操作&#xff0c;以及怎么回到Golden区&#xff1f; 还有一个问题&#xff0c;就是我硬件打板回来&a…

Selenium 实现图片验证码识别

前言 在测试过程中&#xff0c;有的时候登录需要输入图片验证码。这时候使用Selenium进行自动化测试&#xff0c;怎么做图片验证码识别&#xff1f;本篇内容主要介绍使用Selenium、BufferedImage、Tesseract进行图片 验证码识别。 环境准备 jdk&#xff1a;1.8 tessdata&…

深度学习--对抗生成网络(GAN, Generative Adversarial Network)

对抗生成网络&#xff08;GAN, Generative Adversarial Network&#xff09;是一种深度学习模型&#xff0c;由Ian Goodfellow等人在2014年提出。GAN主要用于生成数据&#xff0c;通过两个神经网络相互对抗&#xff0c;来生成以假乱真的新数据。以下是对GAN的详细阐述&#xff…

如果电脑一直提示微软账号登录……

前言 今天小白接了个电脑故障问题&#xff1a;电脑提示微软账号登录&#xff0c;然后经过各种操作…… 电脑重启之后就变成了这样&#xff1a; 按理说&#xff0c;登录了微软账号之后&#xff0c;Windows系统要进入到桌面就必须有一个输入密码验证的过程&#xff0c;但这个界…

Harmony OS DevEco Studio 如何导入第三方库(以lottie为例)?-- HarmonyOS自学2

在做鸿蒙开发时&#xff0c;离不开第三方库的引入 一.有哪些支持的Harmony OS的 第三方库&#xff1f; 第三方库下载地址&#xff1a; 1 tpc_resource: 三方组件资源汇总 2 OpenHarmony三方库中心仓 二. 如何加入到DevEco Studio工程 以 lottie为例 OpenHarmony-TPC/lot…

nginx 新建一个 PC web 站点

注意&#xff1a;进行实例之前必须完成nginx的源码编译。&#xff08;阅读往期文章完成步骤&#xff09; 1.编辑nginx的配置文件&#xff0c;修改内容 [rootlocalhost ~]# vim /usr/local/nginx/conf/nginx.conf 2.创建新目录/usr/local/nginx/conf.d/&#xff0c;编辑新文件…

基于飞腾平台的Hive的安装配置

【写在前面】 飞腾开发者平台是基于飞腾自身强大的技术基础和开放能力&#xff0c;聚合行业内优秀资源而打造的。该平台覆盖了操作系统、算法、数据库、安全、平台工具、虚拟化、存储、网络、固件等多个前沿技术领域&#xff0c;包含了应用使能套件、软件仓库、软件支持、软件适…