Redis 业务结构
流程图
缓存一致性
Redis 和 MySQL 中数据保持一致
双检加锁策略
主要用于解决多线程环境下的并发问题,确保在高并发场景下对共享资源的访问是互斥的,避免因竞争条件导致的不一致状态
public User findUserById(Integer id) {User user = null;String key = CACHE_KEY_USER + id;user = (User) redisTemplate.opsForValue().get(key);if (user == null) {// 处理缓存击穿synchronized (UserService.class) {user = (User) redisTemplate.opsForValue().get(key);if (user == null) {user = userMapper.selectByPrimaryKey(id);if (user == null) {// 缓存null,处理缓存穿透redisTemplate.opsForValue().setIfAbsent(key, null, 7L, TimeUnit.DAYS);} else {// mysql里面有数据的,需要回写redis,完成数据一致性的同步工作redisTemplate.opsForValue().setIfAbsent(key, user, 7L, TimeUnit.DAYS);}}}}return user;
}
缓存都要设置超时时间的原因
因为业务一般以MySQL的数据为准,给缓存设置过期时间,定期清理,可以保证最终一致性
缓存一致性的实现
延时双删
先删除缓存 + 更新数据库 + 再删除缓存
分布式锁
保证只有一个线程能持有资源,避免数据不一致
异步通知
canal ,监控mysql binlog,当bin log更新时,同步到redis
MySQL主从复制原理
canal 工作原理
1、canal 模拟MySQL 交互协议,把自己伪装成 slave
2、canal 读取到 mysql 的bin log 并解析
3、执行自定义操作,如 对Redis 进行相同的变更
canal 缓存一致性实践
添加主从用户
MySQL添加 canal 用户,(测试也可以直接使用 root用户)
DROP USER IF EXISTS 'canal'@'%';
create user 'canal'@'%' identified by 'canal';
grant SELECT, REPLICATION SLAVE, REPLICATION CLIENT on *.* to 'canal'@'%';
ALTER USER 'canal'@'%' IDENTIFIED WITH mysql_native_password BY 'canal';
FLUSH PRIVILEGES;
修改MySQL配置文件
修改MySQL配置文件,开启 bin_log
my.cnf
下载 canal
docker pull canal/canal-server
启动 canal
从镜像获取配置文件 => 修改配置文件 => 开启新镜像
# 第一遍 不挂载 获取配置文件
docker run -p 11111:11111 --name canal -d canal/canal-server:latest# 复制配置文件
docker cp df67a55b855d:/home/admin/canal-server/conf/example/instance.properties /usr/local/canal/conf/# 删除原来的容器
docker rm $(doc ker stop canal)# 挂载启动新容器
docker run -p 11111:11111 --name canal \
-v /usr/local/canal/conf/instance.properties:/home/admin/canal-server/conf/example/instance.properties \
-d canal/canal-server:latest
通过日志查看 canal 服务状态
如果出问题,这里可以看到信息
docker exec -it canal /bin/bashtail -f /home/admin/canal-server/logs/example/example.log
配置 canal
1、这里的
canal.instance.mysql.slaveId
与 前面 MySQL配置的server_id
不同即可2、
master.address
填 mysql 地址3、canal 连接 mysql的账密
4、canal 监控的 mysql 库表
5、这里的
canal.mq、topic
对应后续代码实践的 destination
Java 业务代码
gitee 业务代码
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
插入数据前
MySQL 插入数据
insert into bigdata.t_user VALUES (1, 'zhangsan'), (2, 'lisi');
业务代码监控
插入数据后
bin log 内容查看
show variables like 'log_bin';
show binary logs;
show master status;
show binlog events in 'mysql-bin.000006';
返回值字段说明:
- Log_name:查询的binlog文件名
- Pos:pos起始位置
- Event_type:事件类型
- Server_id:服务器ID,my.cnf 进行设置
- End_log_pos:pos结束点
- Info:日志说明