前言
在我们的工作中为经常遇到 缓存中数据要和redis 数据一致性问题,既然是两份数据就一定存在不一致的情况,但是咱们要根据咱们自行的业务场景来决定,数据不一致时间、如果出现不一致业务会有多大的影响等一些因素来决定数据同步方案是否能够满足业务要求。
数据同步方案
数据同步过程中,会存在短暂的延迟,这属于正常的现象。在分布式架构中很难实现数据强一致性.
弱一致性: 主从之间数据允许不一致性;
强一致性: 主从之间数据必须一致性; 如果实现 成本是非常高,会设计到一些锁的技术,
最终一致性:短暂的数据延迟是允许的,但是最终数据是需要一致; —在分布式中做数据同步需要经过网络传输的,网络传输数据需要一定的时间,所以数据短暂的延迟是允许的,但是最终数据一定达成一致。延迟是很难避免的,优化 减少延迟的时间。
同步方案
- 更新 mysql 数据,在手动清除 Redis 缓存 ,在重新查询最新的数据同步到 Redis 中。
- 更新 mysql 数据,在采用 mq 异步的形式 同步数据到Redis 中。
- 基于订阅 mysql binlog 采用 mq 异步的形式将数据同步到Redis 中。
-
订阅 mysql binlog 文件 异步的形式同步到 redis 中(canal 框架、阿里开源)
上述的只是一些基本的处理方式。
canal 解决mysql 与Redis数据同步方案(异步更新缓存)
1.canal 伪装成 mysql 从节点 订阅 mysql 主节点的 binlog 文件;
2 .当我们的 mysql 主节点 binlog 文件发生了变化,则将该 binlog 文件发送给 canal 服务器端;
3.canal 服务器端将该 binlog 文件二进制转化成 json 格式给 canal 客户端;
4.canal 客户端在将该数据同步到 Redis/ES;
延时双删策略
1.t1 线程先删除缓存;
2.t2 线程读取缓存为 null,同步 db 数据到缓存中;
3.t1 线程更新 db 中的数据;
4.t3 线程查询缓存中数据是旧数据;
如何解决该问题:延迟双删策略
t1 线程更新完 DB 后,让它 sleep 一段时间,再删除缓存 ;
延迟双删缺点就是 第二次删除缓存时间很难控制
public void write( String key, Object data )
{
redis.delKey( key );
db.updateData( data );
Thread.sleep( 500 );
redis.delKey( key );
}