Redis使用场景之使用分布式锁预防缓存击穿

4,277 阅读2分钟

缓存击穿

缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。

那么如何解决这个问题呢?

有很多种思路可以解决这样的问题,比如使缓存常驻内存,采用异步刷新等方法,这里介绍使用分布式锁来解决这样的问题。

大体思路

  • 1.我们从缓存中获取数据,如果获取到数据则直接返回。
  • 2.如果未从缓存中获取到数据,就需要从数据库中读取,为了防止大量并发直接访问数据库,就需要加上分布式锁,确保只有一个请求访问数据库。
  • 3.当加锁成功,做一下三步:1)从数据库中读取数据, 2)把数据写入缓存, 3)删除分布式锁。
  • 4.如果加锁没有成功,则让进程休眠一段时间,重复1步骤。
  • 5.为了防止意外情况的发生,我们需要设置一个阀值,当获取缓存中的次数超过阀值时,直接退出程序,防止大量的并发被阻塞。

redis实现分布式锁

我们这里使用redis实现分布式锁,使用下面的语句实现

    SET [KEY] [RAND_NUM] EX [LOCK_TIME] NX
  • KEY: 锁的键,根据实际情况指定。
  • RAND_NUM: 随机数,防止因执行时间过长锁失效,导致误删锁的操作。
  • EX: 表示设置此锁的失效时间防止过期后死锁。
  • LOCK_TIME: 多少秒后过期。
  • NX:表示如果次锁不存在,则创建此锁。

当锁不存在时,redis会返回"ok",表示锁创建成功,当锁存在时,redis返回"NULL",我们可以根据返回值来确定是否有创建成功。

使用场景

我们从流程图上能看到,更新缓存会导致并发线程阻塞。

这里有两个关键点会影响系统性能:

  • 1.单个缓存并发数量越大,对系统性能影响越大。
  • 2.更新单个缓存时间越长,对系统性能影响越大。

所以使用此方法使用场景是:非热点的简单缓存数据(并发小,更新时间短)。