iis7网站绑定域名163网易免费邮箱登录
web/
2025/9/26 18:36:25/
文章来源:
iis7网站绑定域名,163网易免费邮箱登录,分类信息的网站如何推广,杭州软件开发公司排名#x1f389;#x1f389;欢迎光临#xff0c;终于等到你啦#x1f389;#x1f389;
#x1f3c5;我是苏泽#xff0c;一位对技术充满热情的探索者和分享者。#x1f680;#x1f680;
#x1f31f;持续更新的专栏Redis实战与进阶
本专栏讲解Redis从原理到实践
… 欢迎光临终于等到你啦
我是苏泽一位对技术充满热情的探索者和分享者。
持续更新的专栏Redis实战与进阶
本专栏讲解Redis从原理到实践
这是苏泽的个人主页可以看到我其他的内容哦 努力的苏泽http://suzee.blog.csdn.net 最近超级无敌忙 就断更好久了 实在是抽不出时间来 没办法 这篇文章也只是整理我以前学习的资料 目前还有一整套企业级的Redis处理方案没写哈 敬请期待朋友们 下面是正文 目录
首先我们要明白什么是缓存击穿
分析有什么办法能解决
业务解析
编辑
代码实现
然后我们将缓存穿透的函数给封装起来
原函数
我们将这部分逻辑 封装到 queryWithPassThrough中
我们再写一个函数queryWithMutex来用互斥锁解决缓存穿透的问题
于是原本的查询函数的结构就变成了这样
这样做的优缺点
优点
缺点
下一篇我们来讲解如何使用另一个方案解决这个问题 首先我们要明白什么是缓存击穿
Redis缓存击穿是指在高并发的情况下当某个热点数据的缓存过期或不存在时大量的请求同时涌入数据库或后端服务导致数据库或后端服务负载过高甚至崩溃的情况。 分析有什么办法能解决
当涉及到并发访问共享资源时互斥锁和逻辑过期是两种常用的技术手段。
互斥锁Mutex 互斥锁是一种并发控制机制用于在多个线程或进程之间保证共享资源的互斥访问。它通过在关键代码段前后设置锁来确保同一时间只有一个线程或进程可以执行关键代码段。当某个线程或进程获取到互斥锁时其他线程或进程需要等待锁的释放才能继续执行。 业务解析 代码实现
先写两个函数 一个加锁 一个释放锁
private boolean tryLock(String key){//自定义互斥锁 将申请锁的结果返回Boolean flag stringRedisTemplate.opsForValue().setIfAbsent(key, 1, 10L, TimeUnit.SECONDS);return BooleanUtil.isTrue(flag);}
//释放锁
private void unLock(String key){stringRedisTemplate.delete(key);}
然后我们将缓存穿透的函数给封装起来
原函数
public Result queryById(Long id) {//1.从Redis查询id 这里使用的数据结构可以是String也可以是hash 若是查询不到就为空了 CACHE_SHOP_KEY就是cache:shop:String shopJson stringRedisTemplate.opsForValue().get(CACHE_SHOP_KEY id);//2.判断是否存在 在字符串意义上是否为空if (StrUtil.isNotBlank(shopJson)) {//3.存在直接返回Shop shop JSONUtil.toBean(shopJson, Shop.class);return Result.ok(shop);}//3.判断是否命中写入redis中的nullif(shopJson ! null){return Result.fail(店铺信息不能为空);}//4.不存在 查询数据库Shop shop getById(id);//5.数据库中不存在 返回报错if (shop null){//空值写入redisstringRedisTemplate.opsForValue().set(cache:shop: id, null,CACHE_NULL_TTL, TimeUnit.MINUTES);return Result.fail(店铺不存在);}//6.数据库中存在 写入Redis 并返回stringRedisTemplate.opsForValue().set(cache:shop: id, JSONUtil.toJsonStr(shop),30L, TimeUnit.MINUTES);return Result.ok(shop);
}
我们将这部分逻辑 封装到 queryWithPassThrough中
//封装缓存穿透函数
private Shop queryWithPassThrough(Long id){//1.从Redis查询id 这里使用的数据结构可以是String也可以是hash 若是查询不到就为空了 CACHE_SHOP_KEY就是cache:shop:String shopJson stringRedisTemplate.opsForValue().get(CACHE_SHOP_KEY id);//2.判断是否 在字符串意义上是否为空if (StrUtil.isNotBlank(shopJson)) {//3.存在直接返回Shop shop JSONUtil.toBean(shopJson, Shop.class);return shop;}//3.判断是否命中写入redis中的nullif(shopJson ! null){return null;}Shop shop getById(id);//5.数据库中不存在 返回报错if (shop null){//空值null写入redisstringRedisTemplate.opsForValue().set(cache:shop: id, null,CACHE_NULL_TTL, TimeUnit.MINUTES);return null;}//6.数据库中存在 写入Redis 并返回stringRedisTemplate.opsForValue().set(cache:shop: id, JSONUtil.toJsonStr(shop),30L, TimeUnit.MINUTES);return shop;
}
我们再写一个函数queryWithMutex来用互斥锁解决缓存穿透的问题
于是原本的查询函数的结构就变成了这样
public Result queryById(Long id) {//缓存穿透
// Shop shop queryWithPassThrough(id);//互斥锁解决缓存穿透Shop shop queryWithMutex(id);if (shop null) {return Result.fail(店铺不存在);}//返回return Result.ok(shop);}
//解决缓存穿透的问题
private Shop queryWithMutex(Long id) throws InterruptedException{String lockKey lockKey id;while (true) {//1.从Redis查询id 这里使用的数据结构可以是String也可以是hash 若是查询不到就为空了 CACHE_SHOP_KEY就是cache:shop:String shopJson stringRedisTemplate.opsForValue().get(CACHE_SHOP_KEY id);//2.判断是否 在字符串意义上是否为空if (StrUtil.isNotBlank(shopJson)) {//3.存在直接返回Shop shop JSONUtil.toBean(shopJson, Shop.class);return shop;}//3.判断是否命中写入redis中的nullif(shopJson ! null){return null;}//4重建缓存//4.1申请互斥锁boolean flag tryLock(lockKey);//4.2判断是否成功if (!flag){try {Thread.sleep(100);} catch (InterruptedException e) {throw new RuntimeException(e);}}else//成功了就跳出循环 这里不敢用递归 怕栈溢出了break;}//4.4 成功 查询数据库Shop shop getById(id);//5.数据库中不存在 返回报错if (shop null){//空值null写入redisstringRedisTemplate.opsForValue().set(cache:shop: id, null,CACHE_NULL_TTL, TimeUnit.MINUTES);return null;}//6.数据库中存在 写入Redis 并返回stringRedisTemplate.opsForValue().set(cache:shop: id, JSONUtil.toJsonStr(shop),30L, TimeUnit.MINUTES);//7.释放互斥锁unLock(lockKey);return shop;
}
这样做的优缺点
互斥锁作为一种并发控制机制在解决缓存击穿问题时具有以下优点和缺点
优点 确保数据一致性互斥锁可以确保同一时间只有一个线程或进程可以访问共享资源避免了并发访问导致的数据不一致性问题。 避免竞态条件互斥锁可以防止多个线程或进程同时执行关键代码段避免了竞态条件的发生。竞态条件是指多个线程或进程对共享资源的访问顺序不确定导致结果的不可预测性。 简单易用互斥锁的使用相对简单可以通过加锁和解锁操作来控制对共享资源的访问。
缺点 性能开销互斥锁在多线程环境下会引入一定的性能开销。当多个线程竞争同一个锁时其他线程需要等待锁的释放这会导致一些线程的阻塞和等待降低系统的并发性能。 可能引发死锁如果在使用互斥锁时处理不当可能会发生死锁的情况。死锁是指多个线程或进程相互等待对方持有的资源导致所有线程都无法继续执行。 容易导致线程饥饿当某个线程持有互斥锁并长时间不释放时其他线程可能会一直等待锁的释放导致线程饥饿现象出现。 下一篇我们来讲解如何使用另一个方案解决这个问题
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/81373.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!