当前位置:网站首页>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;
}
边栏推荐
- 1091 N-Defensive Number (15 points)
- 数仓开发知识总结
- Redis source code: how to view the Redis source code, the order of viewing the Redis source code, the sequence of the source code from the external data structure of Redis to the internal data structu
- 1106 2019 Sequence (15 points)
- 接口测试的基础流程和用例设计方法你知道吗?
- 【LeetCode每日一题】——844.比较含退格的字符串
- STM32CUBEIDE(11)----输出PWM及修改PWM频率与占空比
- 软件测试主要做什么工作,难不难?
- JRS303-Data Verification
- 年薪40W测试工程师成长之路,你在哪个阶段?
猜你喜欢
1061 判断题 (15 分)
3.2 - classification - Logistic regression
MySQL使用GROUP BY 分组查询时,SELECT 查询字段包含非分组字段
Pico neo3 Unity打包设置
1081 Check Password (15 points)
TF中的条件语句;where()
查找最新人员工资和上上次人员工资的变动情况
Redis source code-String: Redis String command, Redis String storage principle, three encoding types of Redis string, Redis String SDS source code analysis, Redis String application scenarios
About # SQL problem: how to set the following data by commas into multiple lines, in the form of column display
分布式锁-Redission - 缓存一致性解决
随机推荐
【Pytorch】nn.ReLU(inplace=True)
maxwell concept
1.1-Regression
TF中的One-hot
Service的两种启动方式与区别
【latex异常和错误】Missing $ inserted.<inserted text>You can‘t use \spacefactor in math mode.输出文本要注意特殊字符的转义
oracle19c不支持实时同步参数,请教一下大佬们有什么好的解决办法吗?
How Unity handles C# under the hood
TF中使用softmax函数;
Four operations in TF
break pad源码编译--参考大佬博客的总结
Discourse's Close Topic and Reopen Topic
从何跟踪伦敦金最新行情走势?
Redis source code: how to view the Redis source code, the order of viewing the Redis source code, the sequence of the source code from the external data structure of Redis to the internal data structu
1106 2019数列 (15 分)
1096 大美数 (15 分)
【LaTex-错误和异常】\verb ended by end of line.原因是因为闭合边界符没有在\verb命令所属行中出现;\verb命令的正确和错误用法、verbatim环境的用法
1096 big beautiful numbers (15 points)
Edge 提供了标签分组功能
项目2-年收入判断