Redis实现 分布式缓存、分布式锁

缓存逻辑

 

Redis实现 分布式缓存、分布式锁_第1张图片

代码实例

Redis实现 分布式缓存、分布式锁_第2张图片

堆外内存溢出

 springboot2.0以后默认使用lettuce作为操作rendis的客户端,在高并发下回产生“堆外内存溢出”,可以通过切换使用jedis。

Redis实现 分布式缓存、分布式锁_第3张图片

缓存穿透

Redis实现 分布式缓存、分布式锁_第4张图片

缓存雪崩

Redis实现 分布式缓存、分布式锁_第5张图片

缓存击穿

Redis实现 分布式缓存、分布式锁_第6张图片

解决方案 

上面的基础逻辑回存在一定的问题,为了避免缓存穿透、缓存雪崩、缓存击穿的问题,可以通过下面方法解决

  • 解决缓存穿透:空结果缓存,比如数据库查询结果为空,则缓存一个特殊值
  • 解决缓存雪崩:设置过期时间 (加随机值),避免缓存同时失效
  • 解决缓存击穿:对操作数据库的逻辑加锁,不能让所有请求都查询数据库

单体架构加锁 (本地锁)

当并发请求时,只让其中一个请求拿到锁以后,去查一次数据库,然后将查询的结果放入缓存中,其他请求就不需要再次查询数据库了,

当一个请求拿到锁以后,需要再次查询缓存,如果没有才继续进行数据库查询。

代码实例如下

Redis实现 分布式缓存、分布式锁_第7张图片

 锁的时序性问题

Redis实现 分布式缓存、分布式锁_第8张图片

 在并发情况下,当一个请求拿到锁以后,当执行完“确认缓存” 和 “查数据库” 操作后,就会释放锁,当下一个请求获取锁后继续执行“确认缓存” 和 “查数据库” 操作,但此时第一个请求还没有将数据放入缓存成功,就会导致后面的请求重复查询数据库。

所以就需要将“结果放入缓存” 也加到锁中。

Redis实现 分布式缓存、分布式锁_第9张图片

分布式锁

Redis实现 分布式缓存、分布式锁_第10张图片

 本地锁只能锁住当前进程,在多个服务节点下需要使用分布式锁。

分布式锁的基本原理就是,让过个请求去同一个地方去抢占锁,如果能抢到,则执行业务逻辑,否则就必须等待,直到释放锁,抢锁可以去redis,也可以是数据库,等待可以采用自旋的方式。

Redis实现 分布式缓存、分布式锁_第11张图片死锁 

一个请求进来获取到锁以后,开始执行业务逻辑,如果在业务代码执行的过程中发生异常,后面的删除锁的逻辑没有执行,就会永远锁在这里,造成死锁。

解决方式就是设置锁的自动过期,这样即使没有删除,过期后也会自动删除

Redis实现 分布式缓存、分布式锁_第12张图片

事务的原子性

为了避免死锁发生,上面设置的锁的过期时间,但是如果在这是锁的过期时间的过程中有发生了异常、宕机,删除锁的操作依然没有执行,又会出现死锁。

为了避免这种现象,必须将“抢锁”和“设置过期时间” 放到一个事务当中

Redis实现 分布式缓存、分布式锁_第13张图片

删除锁

由于设置了锁的过期时间,在并发请求下,由于业务执行时间比较长,如果直接删除锁,有可能把别人持有的锁给删除了。

Redis实现 分布式缓存、分布式锁_第14张图片

 解决办法,可以加一个uuid,在执行删除锁的时候判断一下,自己删除的锁是不是自己从redis中获取的那一个,实例代码如下

Redis实现 分布式缓存、分布式锁_第15张图片

删除锁的原子性 

如果程序执行到 “判断是删除的自己的锁” 此时锁正好过期,此时下一个请求获取了新的锁,后面在删除锁的时候,那么删除的就又是别人的锁了。

解决办法就是将“获取当前锁的值”、“判断删除的是否是自己的锁”和“删除锁” 放到一个事务中去,保证原子性

Redis实现 分布式缓存、分布式锁_第16张图片

分布式锁Redisson 

上面通过redis 实现的分布式锁比较复杂,如果控制不好就会出现“锁不住”或者“死锁”的问题,Redis 提供了一个更强大的分布式锁,Redisson ,Redisson 的宗旨是促进使用者对redis关注分离,从而将更多精力放到业务处理上.

引入依赖

Redis实现 分布式缓存、分布式锁_第17张图片

 添加配置

参考官方文档

Redis实现 分布式缓存、分布式锁_第18张图片

示例代码如下

Redis实现 分布式缓存、分布式锁_第19张图片

通过redisson,不需要在关心是否出现死锁问题,只需要关注业务逻辑即可

读写锁

redisson提供读写锁,读数据的气候加读锁,写数据的时候加写锁,保证一定能够获取到最新数据,读写锁是同时存在的,例如,在写入数据前加锁,在写入逻辑完成之前,读数据的操作会一直在等待,知道写操作完成后释放锁,才能正常读到最新的数据,示例代码如下

读锁

Redis实现 分布式缓存、分布式锁_第20张图片

写锁 

Redis实现 分布式缓存、分布式锁_第21张图片

总结

Redis实现 分布式缓存、分布式锁_第22张图片

闭锁

Redis实现 分布式缓存、分布式锁_第23张图片

通过redisson的闭锁,可以实现当gogogo方法调用5次的时候,lockDoor方法才会执行完成

信号量

例如在redis中初始化一个key为park ,value 为3的键值,示例代码中每执行一次go 方法,value值就会减1,当值减到0的时候,park方法返回false ,值大于零的时候park方法返回true ,信号量可以在分布式系统中实现限流的功能,

Redis实现 分布式缓存、分布式锁_第24张图片

你可能感兴趣的:(缓存)