Redis从入门到精通(二):分布式锁以及缓存相关问题

本文介绍了Redis分布式锁的概念、分类及实现条件,并探讨了缓存击穿、缓存雪崩和缓存穿透等问题及其解决方案,旨在帮助读者深入理解分布式锁在解决并发问题中的应用和缓存管理的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录:
Redis从入门到精通(一):缓存
Redis从入门到精通(二):分布式锁以及缓存相关问题
Redis从入门到精通(三):Redis持久化算法以及内存淘汰策略
Redis从入门到精通(四):Redis常用数据结构以及指令
Redis从入门到精通(五):Redis6整合SpringBoot2.x+Mybatis+SpringCache
Redis从入门到精通(六):Redis高可用原理
Redis从入门到精通(七):跳跃表的简介与实现
Redis从入门到精通(八):Redis新特性

分布式架构

什么是分布式架构?

很简单,那就是服务不放在同一台主机上,或者不放在同一个CPU的核心上。这么做主要目的是发挥出CPU核心的性能,配合上集群,可以减少因故障导致的整个服务的瘫痪。但是,一旦做了分布式,就要面临几个问题:

  • 同一个服务之间的数据怎么同步?
  • 同一个数据在不同的服务之间怎么变化?
  • 当一个服务挂掉,其他的服务怎么响应?

这里面是分布式架构的核心,当我们的Redis部署成分布式缓存的时候,同样要考虑这三点问题。这三个问题的背后其实就是著名的CAP理论。所谓CAP理论,就是:

  • C(Consistency)一致性
  • A(Availability)可用性
  • P(Partition tolerance)分区容错性

这个问题的核心在于,CAP三个方面不能同时满足。很好理解,举个例子:淘宝的架构是分布式架构,那么假设在河北和广东分别有两个用户几乎同时购买同一件商品,同时这个商品只有最后一个库存,该怎么处理?

上面是一个很典型的生产者---消费者模型。就是资源被两个消费者同时征用,如何处理?我们先看看操作系统是怎么处理的:谁要消费,就先在资源上上一个锁,其他进程无法再使用该资源,直到锁被释放。这在操作系统是很常见并且很稳定的解决方法,但是放在分布式系统中就成了棘手的问题。河北的用户买了该商品,同时将该商品锁定,理论上广东的用户无法再购买,因为商品已经被锁定了,但是呢,分布式架构数据同步(Consistency,数据一致性)需要时间,在上锁这个动作被另一台服务于广东人的服务器接收到前,广东人也完成了下单业务,问题就出现了,虽然广东人和河北人都买了该商品,但是该商品只有一个了,该给谁?

很明显,上述例子中,对于用户来说,可用性一直存在,但是数据一致性出现了问题。那么我们可不可以牺牲可用性保证数据一致性呢?当然可以,只需要将该商品服务存放于一台服务器,所有的消费都在这个服务器上就行。由于是一台服务器,用户下单后给商品上锁,同时另一个人不能在这期间购买,系统可用性下降,但是保证了数据一致性。

分区容错性我们暂时不考虑,那是集群的事,以后再说。

真实的项目不会和我说的一样简单,程序猿们往往在系统和用户之间加了中间件,比如消息队列来缓解CAP问题,但是也只是缓解,根源矛盾还是存在的。消息队列以后会出个专题专门学习一下。

分布式锁

什么是分布式锁

保证同一时间下,保证只有一个客户端对可共享资源进行某种操作。

我这里写的很含糊,某种操作,因为操作可以分成读、写、执行等等,上面的话如果分开讲,就会说到很复杂锁理论,以后也会出个文章说说我们见到的各种锁机制。这里我们不提那些。

还用上述的案例,下图中,用户1对服务器1上锁,用户2对服务器2上锁,结果依旧导致了数据不一致,因为每个服务器都是可以对数据库进行操作的,所以本地锁杜宇分布式架构来说显得很多余,于是便有了分布式锁。
图一
分布式锁:
在这里插入图片描述
只有我们用一个统一的锁管理器,才能做到分布式锁的目标。那我们这个系列讲的Redis分布式锁,就是部署在这个分布式锁服务器上的。

分布式锁分类

  • 基于数据库的MySQL锁,将MySQL部署在锁服务器,建立一个表,对表进行操作达到锁的目的
  • 基于缓存的Redis锁,将Redis部署在锁服务器,利用缓存对锁ID进行处理达到锁目的
  • 基于ZooKeeper的分布式锁,这个说起来太麻烦了,也不是系列文章重点,略过。

分布式锁满足条件

实现分布式锁需要满足的条件,这些条件缺一不可:

  1. 排他性:一个用户拿到锁,其他用户不能再对资源进行操作。
  2. 可重入性:同一个用户多种操作,不能被排斥。比如我买东西,先下单,后付款,两个操作,不能说下单加了锁,付款的时候就不能访问了。
  3. 容错性:如果一个用户加锁后,突然走了,可能网络故障等原因,但是呢锁一直没有释放,其他资源进不来,就成了死锁,所以我们要考虑这种情况,用户与所服务器无连接时,自动释放锁。
  4. 高性能、高可用

分布式锁的SpringBoot+Redis+lua脚本实现

本节内容在后面的学习中会提到,所以这里不讲,先把基础知识完善在说。
本节内容在Redis从入门到精通(五):Redis6整合SpringBoot2.x+Mybatis+SpringCache中有讲解。

缓存问题

我们在前一篇文章中说了热点key问题,在这里我们将缓存问题进一步细化。

缓存击穿

什么是缓存击穿呢,实际上缓存击穿是指,当某一主键key在某一时刻缓存过期,需要更新,但是同时有大量数据访问主键key代表的数据时,造成的缓存中无法击中key,需要从数据库中拉去数据,但是大量访问将数据库拖垮的问题。

解决方法:

  • 设置key不过期
  • 定期更新缓存,配合集群
  • 设置互斥锁,某一个请求访问发现key过期,可以对该key加锁。只允许一个请求访问数据库,取出key,存入缓存(此时更新完毕),释放锁。其他的请求可以等待,也可以直接返回空数据。

缓存雪崩

什么是缓存雪崩,就是大量的缓存击穿同时出现,即大量热点key同时过期。

解决方法和缓存击穿一样:

  • 设置热点缓存不过期,定时更新
  • 设置随机过期时间

缓存穿透

注意,缓存穿透和缓存击穿不一样。缓存穿透是指访问大量不存在的数据,导致数据库被拖垮。这是黑客攻击的一种手段。比如在DDoS攻击中,假设某一场景,有大量数据登录QQ,账号密码都是随机的。这就可能出现非法qq账号,比如1,-625这种账号,明显不是qq号标准,这样就缓存中没有这些数据,这些数据就会被拿去到数据库查询。上万个连接同时到达,数据库就完蛋了。

解决方案:

  • 前端设置规则校验
  • 缓存存放临时key-null,设置其更新时间很短。被称为缓存空值。

我们的目的就是不让那么多数据访问到数据库从而数据库的拉闸,所以这种问题的核心思想就是“建墙阻挡”。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值