Redis14-缓存同步

目录

缓存同步策略

安装Canal

监听Canal


缓存同步策略

缓存数据同步的常见方式有三种:

1.设置有效期:给缓存设置有效期,到期后自动删除,再次查询时更新

  • 优势:简单、方便
  • 缺点:时效性差,缓存过期之前可能不一致
  • 场景:更新频率较低,时效性要求低的业务

2.同步双写:在修改数据库的同时,直接修改缓存

  • 优势:时效性强,缓存与数据库强一致
  • 缺点:有代码侵入,耦合度高;
  • 场景:对一致性、时效性要求较高的缓存数据

3.异步通知:修改数据库时发送事件通知,相关服务监听到通知后修改缓存数据

  • 优势:低耦合,可以同时通知多个缓存服务
  • 缺点:时效性一般,可能存在中间不一致状态
  • 场景:时效性要求一般,有多个服务需要同步

异步通知可以基于MQ或者Canal来实现:

1)基于MQ的异步通知

商品服务完成对数据的修改后,只需要发送一条消息到MQ中,缓存服务监听MQ消息,然后完成对缓存的更新

依然有少量的代码侵入

2)基于Canal的异步通知

商品服务完成商品修改后,业务直接结束,没有任何代码侵入,Canal监听MySQL变化,当发现变化后,立即通知缓存服务,缓存服务接收到canal通知,更新缓存

代码零侵入

安装Canal

Canal [kə'næl],译意为水道/管道/沟渠,Canal是阿里巴巴旗下的一款开源项目,基于Java开发,基于数据库增量日志解析,提供增量数据订阅&消费

GitHub的地址:GitHub - alibaba/canal: 阿里巴巴 MySQL binlog 增量订阅&消费组件

Canal是基于MySQL的主从同步来实现的,MySQL主从同步的原理如下:

  1. MySQL master将数据变更写入二进制日志( binary log),其中记录的数据叫做binary log events

  2. MySQL slave将master的binary log events拷贝到它的中继日志(relay log)

  3. MySQL slave重放relay log中事件,将数据变更反映它自己的数据

Canal就是把自己伪装成MySQL的一个slave节点,从而监听master的binary log变化,再把得到的变化信息通知给Canal的客户端,进而完成对其它数据库的同步

安装步骤:

1.开启MySQL主从

vi /tmp/mysql/conf/my.cnf

添加

log-bin=/var/lib/mysql/mysql-bin
binlog-do-db=heima
  • log-bin=/var/lib/mysql/mysql-bin:设置binary log文件的存放地址和文件名,叫做mysql-bin
  • binlog-do-db=heima:指定对哪个database记录binary log events,这里记录heima这个库

设置用户权限

create user canal@'%' IDENTIFIED by 'canal';
GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT,SUPER ON *.* TO 'canal'@'%' identified by 'canal';
FLUSH PRIVILEGES;

重启mysql容器 

docker restart mysql

2.创建网络,将MySQL、Canal、MQ放到同一个Docker网络中

docker network create heima

让mysql加入

docker network connect heima mysql

3.导入canal的镜像

docker load -i canal.tar

4.创建canal容器

docker run -p 11111:11111 --name canal \
-e canal.destinations=heima \
-e canal.instance.master.address=mysql:3306  \
-e canal.instance.dbUsername=canal  \
-e canal.instance.dbPassword=canal  \
-e canal.instance.connectionCharset=UTF-8 \
-e canal.instance.tsdb.enable=true \
-e canal.instance.gtidon=false  \
-e canal.instance.filter.regex=heima\\..* \
--network heima \
-d canal/canal-server:v1.1.5
  • -p 11111:11111:这是canal的默认监听端口
  • -e canal.instance.master.address=mysql:3306:数据库地址和端口,如果不知道mysql容器地址,可以通过docker inspect 容器id来查看
  • -e canal.instance.dbUsername=canal:数据库用户名
  • -e canal.instance.dbPassword=canal :数据库密码
  • -e canal.instance.filter.regex=:要监听的表名称

表名称监听支持的语法:

mysql 数据解析关注的表,Perl正则表达式.
多个正则之间以逗号(,)分隔,转义符需要双斜杠(\\) 
常见例子:
1.  所有表:.*   or  .*\\..*
2.  canal schema下所有表: canal\\..*
3.  canal下的以canal打头的表:canal\\.canal.*
4.  canal schema下的一张表:canal.test1
5.  多个规则组合使用然后以逗号隔开:canal\\..*,mysql.test1,mysql.test2 

监听Canal

Canal提供了各种语言的客户端,当Canal监听到binlog变化时,会通知Canal的客户端

GitHub上的第三方开源的canal-starter客户端。地址:GitHub - NormanGyllenhaal/canal-client: spring boot canal starter 易用的canal 客户端 canal client

引入依赖:

<dependency><groupId>top.javatool</groupId><artifactId>canal-spring-boot-starter</artifactId><version>1.2.1-RELEASE</version>
</dependency>

编写配置:

canal:destination: heima # canal的集群名字,要与安装canal时设置的名称一致server: 192.168.150.101:11111 # canal服务地址

通过@Id、@Column、@Transient注解完成Item与数据库表字段的映射:

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Transient;import javax.persistence.Column;
import java.util.Date;@Data
@TableName("tb_item")
public class Item {@TableId(type = IdType.AUTO)@Idprivate Long id;//商品id@Column(name = "name")private String name;//商品名称private String title;//商品标题private Long price;//价格(分)private String image;//商品图片private String category;//分类名称private String brand;//品牌名称private String spec;//规格private Integer status;//商品状态 1-正常,2-下架private Date createTime;//创建时间private Date updateTime;//更新时间@TableField(exist = false)@Transientprivate Integer stock;@TableField(exist = false)@Transientprivate Integer sold;
}

编写监听器,监听Canal消息:

import com.github.benmanes.caffeine.cache.Cache;
import com.heima.item.config.RedisHandler;
import com.heima.item.pojo.Item;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import top.javatool.canal.client.annotation.CanalTable;
import top.javatool.canal.client.handler.EntryHandler;@CanalTable("tb_item")
@Component
public class ItemHandler implements EntryHandler<Item> {@Autowiredprivate RedisHandler redisHandler;@Autowiredprivate Cache<Long, Item> itemCache;@Overridepublic void insert(Item item) {// 写数据到JVM进程缓存itemCache.put(item.getId(), item);// 写数据到redisredisHandler.saveItem(item);}@Overridepublic void update(Item before, Item after) {// 写数据到JVM进程缓存itemCache.put(after.getId(), after);// 写数据到redisredisHandler.saveItem(after);}@Overridepublic void delete(Item item) {// 删除数据到JVM进程缓存itemCache.invalidate(item.getId());// 删除数据到redisredisHandler.deleteItemById(item.getId());}
}
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.heima.item.pojo.Item;
import com.heima.item.pojo.ItemStock;
import com.heima.item.service.IItemService;
import com.heima.item.service.IItemStockService;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;import java.util.List;@Component
public class RedisHandler implements InitializingBean {@Autowiredprivate StringRedisTemplate redisTemplate;@Autowiredprivate IItemService itemService;@Autowiredprivate IItemStockService stockService;private static final ObjectMapper MAPPER = new ObjectMapper();@Overridepublic void afterPropertiesSet() throws Exception {// 初始化缓存// 1.查询商品信息List<Item> itemList = itemService.list();// 2.放入缓存for (Item item : itemList) {// 2.1.item序列化为JSONString json = MAPPER.writeValueAsString(item);// 2.2.存入redisredisTemplate.opsForValue().set("item:id:" + item.getId(), json);}// 3.查询商品库存信息List<ItemStock> stockList = stockService.list();// 4.放入缓存for (ItemStock stock : stockList) {// 2.1.item序列化为JSONString json = MAPPER.writeValueAsString(stock);// 2.2.存入redisredisTemplate.opsForValue().set("item:stock:id:" + stock.getId(), json);}}public void saveItem(Item item) {try {String json = MAPPER.writeValueAsString(item);redisTemplate.opsForValue().set("item:id:" + item.getId(), json);} catch (JsonProcessingException e) {throw new RuntimeException(e);}}public void deleteItemById(Long id) {redisTemplate.delete("item:id:" + id);}
}

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

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

相关文章

【keepalived】高可用集群

一、高可用集群 1.1集群类型 LB&#xff1a;Load Balance 负载均衡 LVS/HAProxy/nginx&#xff08;http/upstream, stream/upstream&#xff09; HA&#xff1a;High Availability 高可用集群 数据库、Redis SPoF: Single Point of Failure&#xff0c;解决单点故障 HPC&…

Spring boot框架指南

1. Spring Boot 概述 1.1 定义与起源 Spring Boot是一种基于Spring框架的开源框架&#xff0c;旨在简化Spring应用程序的创建和开发过程。它通过提供一系列默认配置和自动配置功能&#xff0c;减少了开发者在配置上的工作量&#xff0c;使得快速搭建生产级别的Spring应用程序…

HTML零基础自学笔记(下)篇一 -8.8

HTML零基础自学笔记&#xff08;下&#xff09;---之表格标签详解 参考&#xff1a;pink老师篇一、表格标签是什么&#xff1f;基础内容&#xff08;主要作用、基本语法、标签释义、属性&#xff09;主要作用基本语法标签释义表格结构标签属性 合并单元格代码练习代码运行效果&…

RAG和微调哪个是LLM优化的最优解

RAG和微调哪个是LLM优化的最优解 序言 随着对大型语言模型(llm)的兴起&#xff0c;许多开发人员和组织都在忙着利用它的能力构建自己的应用程序。然而&#xff0c;当预训练的大语言模型开箱即用的表现不如预期时&#xff0c;关于如何提高LLM应用程序性能的问题就被提了出来。就…

【C++】6.类和对象(4)

文章目录 5.赋值运算符重载5.1 运算符重载5.2 赋值运算符重载5.3 前置和后置重载5.4 日期类的实现 6.取地址运算符重载6.1 const成员函数6.2 取地址运算符重载 5.赋值运算符重载 5.1 运算符重载 当运算符被用于类类型的对象时&#xff0c;C语言允许我们通过运算符重载的形式指…

排序算法之--插入排序

文章目录 一、简介二、算法思路分析三、算法复杂度分析&#xff1a;3.1、时间复杂度方面&#xff1a;3.2、空间复杂度方面&#xff1a; 四、代码实现&#xff1a; 一、简介 插入排序是一种简单直观的排序算法&#xff0c;‌它的工作原理是通过构建有序序列&#xff0c;‌该算法…

水表数字识别4:C/C++实现水表数字识别(含源码 可实时检测)

水表数字识别4&#xff1a;C/C实现水表数字识别(含源码 可实时检测) 目录 水表数字识别4&#xff1a;C/C实现水表数字识别(含源码 可实时检测) 1. 前言 2. 水表数字分割模型 &#xff08;1&#xff09; 将Pytorch模型转换ONNX模型 &#xff08;2&#xff09; 将ONNX模型转…

NoSQL 之Redis集群模式

目录 案例概述 redis工作模式 主从模式 哨兵模式 redis cluster模式 Redis集群介绍 Redis集群的优势 Redis集群的实现方法 Redis-Cluster数据分片 Redis-Cluster的主从复制模型 Redis集群部署 案例部署 安装redis 检查redis的状态 修改配置文件 重启启动redis服…

C#小桌面程序调试出错,如何解决??

&#x1f3c6;本文收录于《CSDN问答解惑-专业版》专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收…

pythonUI自动化007::pytest的组成以及运行

pytest组成&#xff1a; 测试模块&#xff1a;以“test”开头或结尾的py文件 测试用例&#xff1a;在测试模块里或测试类里&#xff0c;名称符合test_xxx函数或者示例函数。 测试类&#xff1a;测试模块里面命名符合Test_xxx的类 函数级&#xff1a; import pytestclass Test…

大数据面试SQL(七):累加刚好超过各省GDP40%的地市名称

文章目录 累加刚好超过各省GDP40%的地市名称 一、题目 二、分析 三、SQL实战 四、样例数据参考 累加刚好超过各省GDP40%的地市名称 一、题目 现有各省地级市的gdp数据,求从高到低累加刚好超过各省GDP40%的地市名称&#xff0c;临界地市也需要。 例如&#xff1a; 浙江省…

物理网卡MAC修改器v3.0-直接修改网卡内部硬件MAC地址,重装系统不变!

直接在操作系统里就能修改网卡硬件mac地址&#xff0c;刷新网卡mac序列号硬件码机器码&#xff0c;电脑主板集成网卡&#xff0c;pcie网卡&#xff0c;usb有线网卡&#xff0c;usb无线网卡&#xff0c;英特尔网卡&#xff0c;瑞昱网卡全支持&#xff01; 一键修改mac&#xff0…

求1000以内的水仙花数【C语言】

求1000以内的水仙花数 #include <stdio.h> //包含标准输入输出头文件&#xff0c;用于使用printf函数int main() { //程序的主函数开始int a, b, c, i; //i用于循环遍历100到999之间的所有数&#xff08;三位数&#xff09;&#xff0c;a, b, c分别用于存储当前数i的百位…

SPSS 数据分析,掌握这 6 大模块就够

SPSS 全称为「社会科学统计软件包」&#xff0c;是 IBM 公司推出的一系列用于统计学分析运算、数据挖掘、预测分析和决策支持任务的软件产品及相关服务的总称。 图中我们看到 SPSS 有 23 个方法模块&#xff0c;虽然我们不能每个模块都能用到&#xff0c;但作为一个科研工作者…

C++-类与对象(上篇)

一、目标&#xff1a; 1. 面向过程和面向对象初步认识 2. 类的引入 3. 类的定义 4. 类的访问限定符及封装 5. 类的作用域 6. 类的实例化 7. 类的对象大小的计算 8. 类成员函数的 this 指针 二、对类与对象的介绍&#xff1a; 1.面向过程和面向对象初步认识 &#xff1a…

前端代码编辑神器:sublime text 4(WinMac)中文注册版

Sublime Text 4 是一款广受欢迎的文本和代码编辑器&#xff0c;由程序员 Jon Skinner 于2008年开发。这款编辑器以其漂亮的用户界面和强大的功能而著称&#xff0c;适用于多种编程语言的开发。 主要特点&#xff1a; 用户界面&#xff1a;Sublime Text 4 拥有一个简洁且美观的…

旧手机拍摄的视频模糊可以修复清晰吗?

你是否时常“考古”一些老电影、老动漫来回忆旧日时光&#xff1f;你是否也有一些珍贵的录像&#xff0c;带你重温过去的美好&#xff1f;然而&#xff0c;我们已经习惯了高清体验&#xff0c;回头再看曾经的旧影像&#xff0c;画质或许“渣”的让人不忍直视。 旧手机像素不好&…

[VBA]使用VBA在Excel中 操作 形状shape 对象

excel已关闭地图插件,对于想做 地图可视化 的,用形状来操作是一种办法,就是要自行找到合适的 地图形状,修改形状颜色等就可以用于 可视化展示不同省市销量、人口等数据。 引言 在Excel中,通过VBA(Visual Basic for Applications)可以极大地增强数据可视化和报告自动化…

【ARM CoreLink 系列 5.5 -- CI-700 Debug trace and PMU 】

文章目录 Debug trace and PMUCI-700 Debug trace 系统概述DTC DomainDTC Domain 约束条件DTM device portsDTM FIFO BufferDTM FIFO 缓冲区特点Debug trace and PMU 本篇文章主要是介绍 CI-700中实现的 Debug Trace (DT) and Performance Monitoring Unit (PMU). CI-700 Deb…

运维高级内容--lvs按权重值轮询调度

创建5台主机(一些配置是基于实验一的基础)&#xff1a; 客户端client 172.25.254.200路由器route 172.25.254.100 192.168.0.100 &#xff08;需要eth0、eth1两个网关&#xff09;LVS 192.168.0.50webserver1 192.168.0.10webserver2 192.168.0.20 1.LVS主机&#xff1a; vim…