当前位置:网站首页>Distributed Lock-Redission - Cache Consistency Solution
Distributed Lock-Redission - Cache Consistency Solution
2022-08-11 07:51:00 【flower padded jacket】
🧑 个人主页:花棉袄
本章内容:【Redission - 缓存一致性解决】
版权: 本文由【花棉袄】原创在CSDN首发需要转载请联系博主
️如果文章对你有帮助【关注点赞️收藏】
双写模式
- 两个线程写 In the end, only one thread writes successfully,If the post-write is successful, the previously written data will be overwritten,This creates dirty data
失效模式
三个连接
Connection number one 写数据库 然后删缓存
connection number two The network connection is slow when writing to the database,The writing has not been successful yet
Link number three 直接读取数据,What is read is the data written by connection No. 1,此时 The second link successfully writes data and deletes the cache,No. 3 began to update the cache and found that it was the cache of No. 2 that was updated
解决方案
无论是双写模式还是失效模式,Will come to this cache inconsistency problem,That is, if multiple strengths are updated at the same time, something will happen,怎么办?
1、If it is user purity data(订单数据、用户数据),There is very little chance of this concurrency,There is almost no need to think about it,缓存数据加上过期时间,每隔一段时间触发读的主动更新即可
2、如果是菜单,商品介绍等基础数据,也可以去使用 canal 订阅,binlog 的方式
3、缓存数据 + The expiration time is also sufficient to meet the cache requirements of most businesses
4、通过加锁保证并发读写,Line up in order as you write,读读无所谓,So it is suitable for read-write locks,(业务不关心脏数据,允许临时脏数据可忽略)
- 总结:
The data we can put into the cache should never be real-time、一致性要求超高的.所以缓存数据的时候加上过期时间,Make sure to get the current latest value every day
我们不应该过度设计,增加系统的复杂性
遇到实时性、一致性要求高的数据,就应该查数据库,即使慢点
配置Redission
- 引入依赖
<!-- https://mvnrepository.com/artifact/org.redisson/redisson -->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.15.5</version>
</dependency>
- 自定义配置类
@Configuration
public class MyRedissonConfig {
/** * 对 Redisson 的使用都是通过 RedissonClient 对象 * @return * @throws IOException */
@Bean(destroyMethod="shutdown") // 服务停止后调用 shutdown 方法.
public RedissonClient redisson() throws IOException {
// 1.创建配置
Config config = new Config();
// 集群模式
// config.useClusterServers().addNodeAddress("127.0.0.1:7004", "127.0.0.1:7001");
// 2.根据 Config 创建出 RedissonClient 示例.
config.useSingleServer().setAddress("redis://127.0.0.1:6379");
return Redisson.create(config);
}
}
- 使用分布式锁Redission解决缓存一致性问题
public Map<String, List<Catelog2Vo>> getCatalogJsonFromDbWithRedisLock() {
String uuid = UUID.randomUUID().toString();
// Setting the value also sets the expiration time
Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock", uuid, 300, TimeUnit.SECONDS);
if (lock) {
// 加锁成功..执行业务
// 设置过期时间,必须和加锁是同步的,原子的
Map<String, List<Catelog2Vo>> dataFromDb;
try {
dataFromDb = getCatelogJsonFromDb();
} finally {
String script = "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end";
//删除锁
Long lock1 = redisTemplate.execute(new DefaultRedisScript<Long>(script, Long.class), Arrays.asList("lock"), uuid);
}
return dataFromDb;
} else {
// 加锁失败,重试 synchronized()
// 休眠200ms重试
System.out.println("获取分布式锁失败,等待重试");
try {
TimeUnit.MILLISECONDS.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
return getCatalogJsonFromDbWithRedisLock();
}
}
//三级分类
public Map<String, List<Catelog2Vo>> getCatelogJsonFromDb() {
// 0.After getting the lock, get it from the cache
String catelogJSON = redisTemplate.opsForValue().get("categoryJSON");
if (!StringUtils.isEmpty(catelogJSON)) {
// Convert to the object we specify
Map<String, List<Catelog2Vo>> result = JSON.parseObject(catelogJSON, new TypeReference<Map<String, List<Catelog2Vo>>>() {
});
System.out.println("获得锁-从缓存中获取");
return result;
}
System.out.println("获得锁-查询了数据库");
//Turns multiple queries of the database into one query
List<CategoryEntity> selectList = baseMapper.selectList(null);
//1.查询所有一级分类
List<CategoryEntity> categoryOne = getParent_cid(selectList, 0L);
//2.封装数据
Map<String, List<Catelog2Vo>> collect = categoryOne.stream().collect(Collectors.toMap(k -> k.getCatId().toString(), v -> {
//2.1根据一级分类ID查询二级分类
List<CategoryEntity> categoryTwo = getParent_cid(selectList, v.getCatId());
List<Catelog2Vo> catelog2Vos = null;
if (categoryTwo != null) {
//2.2 封装二级分类
catelog2Vos = categoryTwo.stream().map(levelTwo -> {
Catelog2Vo catelog2Vo = new Catelog2Vo(v.getCatId().toString(), null, levelTwo.getCatId().toString(), levelTwo.getName().toString());
List<CategoryEntity> categoryThree = getParent_cid(selectList, levelTwo.getCatId());
if (categoryThree != null) {
List<Catelog2Vo.Catelog3Vo> catalog3List = categoryThree.stream().map(levelThree -> {
//2.3 Packaging three-level classification
Catelog2Vo.Catelog3Vo catelog3Vo = new Catelog2Vo.Catelog3Vo(levelTwo.getCatId().toString(), levelThree.getCatId().toString(), levelThree.getName().toString());
return catelog3Vo;
}).collect(Collectors.toList());
//Set up three-level classification
catelog2Vo.setCatalog3List(catalog3List);
}
return catelog2Vo;
}).collect(Collectors.toList());
}
return catelog2Vos;
}));
return collect;
}
边栏推荐
- redis操作
- 1076 Wifi密码 (15 分)
- js判断图片是否存在
- 如何选择专业、安全、高性能的远程控制软件
- 2022-08-10 Group 4 Self-cultivation class study notes (every day)
- There may be fields that cannot be serialized in the abnormal object of cdc and sqlserver. Is there anyone who can understand it? Help me to answer
- prometheus学习5altermanager
- 线程交替输出(你能想出几种方法)
- 分布式锁-Redission - 缓存一致性解决
- 1056 Sum of Combinations (15 points)
猜你喜欢
About # SQL problem: how to set the following data by commas into multiple lines, in the form of column display
Implementation of FIR filter based on FPGA (5) - FPGA code implementation of parallel structure FIR filter
2022年中国软饮料市场洞察
基于FPGA的FIR滤波器的实现(5)— 并行结构FIR滤波器的FPGA代码实现
Tidb二进制集群搭建
【Pytorch】nn.ReLU(inplace=True)
项目1-PM2.5预测
3GPP LTE/NR信道模型
项目2-年收入判断
tf中矩阵乘法
随机推荐
TF中的One-hot
Unity3D learning route?
CIKM 2022 AnalytiCup Competition: 联邦异质任务学习
1.1-回归
go-grpc TSL认证 解决 transport: authentication handshake failed: x509 certificate relies on ... ...
Edge 提供了标签分组功能
TF通过feature与label生成(特征,标签)集合,tf.data.Dataset.from_tensor_slices
2.1-梯度下降
Depth (relay supervision)
为什么C#中对MySQL不支持中文查询
4.1 - Support Vector Machines
prometheus学习4Grafana监控mysql&blackbox了解
1003 我要通过 (20 分)
matplotlib
1106 2019数列 (15 分)
1076 Wifi Password (15 points)
关于Excel实现分组求和最全文档
年薪40W测试工程师成长之路,你在哪个阶段?
LeetCode刷题系列 -- 46. 全排列
TF中的四则运算