目录

  • 分布式缓存
  • 缓存击穿,穿透,雪崩
  • 分布式锁
    • Redisson实现分布式锁
      • Lock锁
      • 读写锁

分布式缓存

对于本地模式下的缓存,每次如果负载均衡请求的服务器不相同,那么会有很大的几率不通过缓存,而是直接通过DB进行数据交换。

因此我们将缓存抽离,如下图所示,即操作同一个缓存,这就不会存在数据不一致的问题。

缓存击穿,穿透,雪崩

缓存穿透:
指查询一个一定不存在的数据,由于缓存是不命中,将去查询数据库,但是 数据库也无此记录,我们没有将这次查询的null写入缓存,这将导致这个不 存在的数据每次请求都要到存储层去查询,失去了缓存的意义。

解决: null结果缓存,并加入短暂过期时间

缓存雪崩:
缓存雪崩是指在我们设置缓存时key采用了相同的过期时间, 导致缓存在某一时刻同时失效,请求全部转发到DB,DB瞬时 压力过重雪崩。

解决: 原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这 样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。

缓存穿透:
对于一些设置了过期时间的key,如果这些key可能会在某些 时间点被超高并发地访问,是一种非常“热点”的数据。
如果这个key在大量请求同时进来前正好失效,那么所有对 这个key的数据查询都落到db,我们称为缓存击穿。

解决: 加锁,大量并发只让一个去查,其他人等待,查到以后释放锁,其他 人获取到锁,先查缓存,就会有数据,不用去db

springboot整合redis进行缓存操作。

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>
  @Overridepublic Book getById(Integer id) {String s = stringRedisTemplate.opsForValue().get(String.valueOf(id));if (!StringUtils.hasText(s)) {Book book = bookDao.selectById(id);//book不为null再执行下一步,为null则退出,解决缓存穿透(可使用布隆过滤器)String toJSONString = JSON.toJSONString(book);stringRedisTemplate.opsForValue().set(String.valueOf(id), toJSONString, 60, TimeUnit.SECONDS);//解决缓存雪崩return book;} else {Book book = JSON.parseObject(s, new TypeReference<Book>() {});return book;}}

分布式锁

推荐博客:
https://www.jianshu.com/p/2afeae8cda89?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation.

Redisson实现分布式锁

整合springboot

<!-- https://mvnrepository.com/artifact/org.redisson/redisson --><dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.16.8</version></dependency>

单redis节点模式配置:

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.io.IOException;@Configuration
public class MyRedissonConfig {@Bean(destroyMethod="shutdown")RedissonClient redisson() throws IOException {//创建配置Config config = new Config();config.useSingleServer().setAddress("redis://localhost:6379");RedissonClient redissonClient = Redisson.create(config);return redissonClient;}
}

其他集群等配置可参考官网:
https://github.com/redisson/redisson/wiki/2.-%E9%85%8D%E7%BD%AE%E6%96%B9%E6%B3%95#26-%E5%8D%95redis%E8%8A%82%E7%82%B9%E6%A8%A1%E5%BC%8F.

Lock锁

官网介绍:
基于Redis的Redisson分布式可重入锁RLock Java对象实现了java.util.concurrent.locks.Lock接口。同时还提供了异步(Async)、反射式(Reactive)和RxJava2标准的接口。

大家都知道,如果负责储存这个分布式锁的Redisson节点宕机以后,而且这个锁正好处于锁住的状态时,这个锁会出现锁死的状态。为了避免这种情况的发生,Redisson内部提供了一个监控锁的看门狗,它的作用是在Redisson实例被关闭前,不断的延长锁的有效期。默认情况下,看门狗的检查锁的超时时间是30秒钟,也可以通过修改Config.lockWatchdogTimeout来另行指定。

另外Redisson还通过加锁的方法提供了leaseTime的参数来指定加锁的时间。超过这个时间后锁便自动解开了。

@GetMapping("/findById/{id}")public Book findById(@PathVariable("id") Integer id) {/*redisson实现分布式锁*/Book book = null;//1获取一把锁,只要锁的名字一样就可以RLock lock = redissonClient.getLock("my-lock");//2、加锁lock.lock();//阻塞式等待:不断尝试获取锁(获取到锁后默认加锁30s)//锁是自动续期的,如果业务超长,运行期间自动给锁续上新的30s,不用担心业务时间长,锁自动过期被删掉//加锁的业务只要运行完成,就不会给当前锁续期,即使不手动解锁(宕机),锁默认在30s以后自动删除//lock.lock(10, TimeUnit.SECONDS); //此有参方法并不会自动续期!!!10自动解锁,自动解锁时间一定要大于业务的执行时间//1、如果我们传递了锁的超时时间,就发送给redis执行脚本,进行占锁,默认超时就是我们指定的时间//2、如果我们没有指定锁的超时时间,就使用30*1000[看门狗的默认时间]//只要占锁成功,就会启动一个定时任务【重新给锁设置过期时间,新的过期时间就是看门狗的默认时间】,每隔10s秒自动续期,直至30s//internallockleasetime【看门狗时间】/3,10stry {book = bookService.findById(id);return book;}finally {lock.unlock();//解锁}}

读写锁

官网介绍:基于Redis的Redisson分布式可重入读写锁RReadWriteLock Java对象实现了java.util.concurrent.locks.ReadWriteLock接口。其中读锁和写锁都继承了RLock接口。

分布式可重入读写锁允许同时有多个读锁和一个写锁处于加锁状态。
同样具有看门狗限定锁的时间。

保证一定读到最新数据,修改期间,写锁是一个排它锁(互斥锁),写锁没释放读就必须等待。读锁是一个共享锁。读读不互斥;读写、写写均互斥

@GetMapping("/getall/{page}/{size}")public Page<Book> getall(@PathVariable("page") Integer page, @PathVariable("size") Integer size) {//获取读写锁RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("rw-lock");//加读锁RLock rLock = readWriteLock.readLock();rLock.lock();Page<Book> bookPage = null;try {bookPage = bookService.getall(page, size);} catch (Exception e) {e.printStackTrace();} finally {rLock.unlock();//释放锁}return bookPage;}@PutMapping("/update")public Integer update(@RequestBody Book book) {RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("rw-lock");Integer integer=-1;//加写锁RLock rLock = readWriteLock.writeLock();rLock.lock();try {integer = bookService.updateById(book);} catch (Exception e) {e.printStackTrace();} finally {rLock.unlock();}return integer;}

其他锁可参照官网。

推荐阅读:
链接: https://www.cnblogs.com/liuqingzheng/p/11080501.html

Redis缓存——(分布式锁)相关推荐

  1. MySQL建表添加乐观锁字段_Java秒杀系统优化-Redis缓存-分布式session-RabbitMQ异步下单-页面静态化...

    Java秒杀系统优化-Redis缓存-分布式session-RabbitMQ异步下单-页面静态化 项目介绍 基于SpringBoot+Mybatis搭建的秒杀系统,并且针对高并发场景进行了优化,保证线 ...

  2. 【分布式缓存系列】Redis实现分布式锁的正确姿势

    一.前言 在我们日常工作中,除了Spring和Mybatis外,用到最多无外乎分布式缓存框架--Redis.但是很多工作很多年的朋友对Redis还处于一个最基础的使用和认识.所以我就像把自己对分布式缓 ...

  3. 基于 Redis 实现分布式锁思考

    以下文章来源方志朋的博客,回复"666"获面试宝典 来源:blog.csdn.net/xuan_lu/article/details/111600302 分布式锁 基于redis实 ...

  4. Redis实现分布式锁的深入探究

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 一.分布式锁简介 锁 是一种用来解决多个执行线程 访问共享资源 错 ...

  5. Zookeeper和Redis实现分布式锁,附我的可靠性分析

    作者:今天你敲代码了吗 链接:https://www.jianshu.com/p/b6953745e341 在分布式系统中,为保证同一时间只有一个客户端可以对共享资源进行操作,需要对共享资源加锁来实现 ...

  6. Redis——由分布式锁造成的重大事故

    作者:浪漫先生 原文:juejin.im/post/6854573212831842311 前言 基于Redis使用分布式锁在当今已经不是什么新鲜事了.本篇文章主要是基于我们实际项目中因为redis分 ...

  7. 基于Redis的分布式锁和Redlock算法

    来自:后端技术指南针 1 前言 今天开始来和大家一起学习一下Redis实际应用篇,会写几个Redis的常见应用. 在我看来Redis最为典型的应用就是作为分布式缓存系统,其他的一些应用本质上并不是杀手 ...

  8. redis使用sysc超时_基于redis的分布式锁实现

    随着业务越来越复杂,应用服务都会朝着分布式.集群方向部署,而分布式CAP原则告诉我们,Consistency(一致性). Availability(可用性).Partition tolerance(分 ...

  9. Redis的分布式锁详解

    一.什么是分布式锁: 1.什么是分布式锁: 分布式锁,即分布式系统中的锁.在单体应用中我们通过锁解决的是控制共享资源访问的问题,而分布式锁,就是解决了分布式系统中控制共享资源访问的问题.与单体应用不同 ...

  10. 【Redis学习】Redis实现分布式锁

      目前几乎很多大型网站及应用都是分布式部署的,分布式场景中的数据一致性问题一直是一个比较重要的话题.分布式的CAP理论告诉我们"任何一个分布式系统都无法同时满足一致性(Consistenc ...

最新文章

  1. SpringSecurity-eclipse
  2. C语言表达式和运算符大学霸IT达人
  3. 渗透测试集成环境Faraday
  4. 机器人 陆梅东_上海乐高创客工作坊活动顺利举行
  5. 显示android缓存文件,android – 使用ACTION_VIEW在缓存目录中打开文件
  6. TypeScript基础入门 - 接口 - 可索引的类型
  7. 2015/04/01     RHCS
  8. asp.net html helper,6. ASP.NET MVC 5.0 中的HTML Helper【HTML 帮助类】
  9. udp linux 获取本机ip
  10. C++11 原生字符串
  11. 自动登录Windows系统
  12. finclip设计指南与小程序设计指南
  13. database-oracle
  14. nRF24L01+不能接收或接收偶尔异常等问题实战分享
  15. java计算时间差(耗时计算)的三种方式
  16. Prometheus和Grafana告警服务创建与对接腾讯云短信告警平台(prometheus_alert)
  17. 「游戏」c++ 炸弹人2.0(新增人机)
  18. 「轻阅读」京东到家订单中心系统mysql到es的转化之路
  19. 网络位置添加一个ftp服务器,win7网络中添加ftp服务器
  20. ChatGPT能完全取代软件开发吗,看看它怎么回答?

热门文章

  1. 【Java项目实战】CRM客户关系管理系统
  2. html显示隐藏表格内外边框
  3. 前端vue+后台node实现获取微信用户基本信息+调用微信JS-SDK(下篇)
  4. 我为什么鼓励你读计算机领域的博士?
  5. 微信朋友圈卖货五大法则
  6. Android studio实现类微信界面
  7. 手机照片丢失怎么才能恢复
  8. matlab中arccotx,微积分计算公式的推导过程
  9. php 排它性,排他性
  10. 头条号如何做原创,老家底都翻出来了,又要被人骂了