当前位置:首页 > 问答 > 正文

Redis在高并发场景下怎么抗阻塞,实测效果还挺惊人的

这个说法其实来源于一个非常经典的、在实际生产环境中被反复验证过的Redis使用技巧,核心思想很简单:与其让大量的请求同时去竞争一个资源,导致绝大多数请求在等待中阻塞(也就是“惊群效应”),不如让这些请求自己先“排好队”,一个一个有序地执行。

这个技巧最典型的应用场景就是缓存重建,我来给你讲一个具体的例子,你就明白它是怎么抗阻塞并且效果惊人的了。

场景:一个热门商品详情页的缓存失效了

Redis在高并发场景下怎么抗阻塞,实测效果还挺惊人的

假设你运营着一个电商网站,有一个爆款商品,每秒有10万个请求来查询它的详情,这个详情信息是存储在Redis缓存里的,并且设置了一个过期时间,突然,这个缓存过期失效了。

如果没有做任何特殊处理,会发生什么?

  1. 10万个请求同时到达你的后端服务器。
  2. 它们发现Redis里没有缓存了(缓存失效),于是这10万个请求会全部涌向数据库,去查询这个热门商品的详细信息。
  3. 数据库瞬间承受了它本不该承受的10万QPS(每秒查询率)的压力,很可能直接被打挂,导致整个网站瘫痪。
  4. 即使数据库很坚挺,没有挂掉,这10万个请求也会在数据库层面造成严重的锁竞争,响应变得极慢。
  5. 当第一个请求从数据库查到数据后,会把它写回Redis,但是在这个过程中,可能已经有成千上万个请求已经穿透到了数据库,这是一种巨大的资源浪费。

这个过程就是典型的“缓存击穿”问题,阻塞和压力主要发生在数据库层面。

Redis在高并发场景下怎么抗阻塞,实测效果还挺惊人的

那个“效果惊人”的解决方案是怎么做的呢?

它的关键点在于:使用Redis的分布式锁机制,让只有一个请求去干活,其他请求等着。

具体步骤如下:

Redis在高并发场景下怎么抗阻塞,实测效果还挺惊人的

  1. 缓存失效,请求涌入:和之前一样,10万个请求发现缓存失效了。
  2. 争抢“许可证”(分布式锁):这10万个请求不会直接去查数据库,而是先做另一件事:它们都尝试在Redis里设置一个特殊的键值对,lock:product_id_123,设置这个键的时候,必须使用 SETNX 命令(SET if Not eXists),意思是只有在这个键不存在的时候才能设置成功,这个操作是原子性的,所以同一时刻,绝对只有一个请求能设置成功。
  3. 成功的请求去干活:那个唯一设置成功的请求,就相当于拿到了“许可证”或“钥匙”,只有它有权去数据库查询数据,其他99999个请求设置SETNX都失败了。
  4. 失败的请求怎么办?——等待和重试:那99999个失败的请求并不会报错返回,也不会直接去冲击数据库,它们会进入一个短暂的“休眠”状态,比如等待50毫秒,然后重新去查询Redis缓存,因为它们相信,那个拿到许可证的“先锋”请求,很快就能把数据从数据库取回来并重新设置到缓存中。
  5. 重建缓存,释放“信号”:那个“先锋”请求辛苦地从数据库查出数据后,会把数据写入Redis缓存中,这里有个关键细节:在写入缓存数据之后,它应该删除(DEL)或者过期(EXPIRE)那个临时的锁键 lock:product_id_123,这个删除操作相当于一个信号弹,告诉其他所有等待的请求:“活儿我干完了,新数据已经放进缓存了!”
  6. 后续请求成功返回:之前那些在休眠和重试的请求,在某一轮重试中,会发现Redis里已经有新的缓存数据了(因为第5步已经完成),于是它们直接读取缓存并返回结果,根本不需要接触数据库。

为什么这个方案效果“惊人”?

  • 对数据库的冲击从10万QPS降为1QPS:无论有多少并发请求,数据库在缓存重建期间最多只被访问一次,这完全避免了数据库被瞬间流量打垮的风险。
  • 极大地减少了阻塞:绝大多数请求只是在Redis上进行非常快速的 GET(查询缓存)和 SETNX(尝试获取锁)操作,这些都是内存操作,微秒级就能完成,虽然它们可能经历了短暂的休眠和重试,但等待的时间是可预测且非常简短的(比如循环几次,每次几十毫秒),远比在数据库层面排队等待锁或者等待慢查询要快得多,整个系统的响应时间变得非常平滑。
  • 资源利用率高:避免了99999次重复的、昂贵的数据库查询,节省了大量的CPU和IO资源。

实测中的一些优化点

在实际应用中,为了让这个方案更健壮,还会加入一些优化:

  • 锁超时机制:万一那个拿到锁的“先锋”请求在查询数据库时突然崩溃了,没有来得及释放锁,那就会导致死锁,其他所有请求会永远等下去,在设置锁的时候,通常会给它一个较短的过期时间,比如5秒,这样即使持有锁的进程崩溃,锁也会自动释放,让下一个请求有机会去重建缓存。
  • 避免锁超时后的重复重建:如果锁超时了,可能会有多个请求都以为自己是“先锋”,从而都去查询数据库,为了避免这种情况,可以在逻辑上再加一层判断。

这个方案之所以被广泛传播且被认为效果惊人,就是因为它用一个非常巧妙和简单的方式(利用Redis原子操作实现分布式锁),将一场可能引发雪崩的“混乱拥堵”变成了一次“井然有序的排队”,用极小的代价解决了高并发下的核心痛点,很多大型互联网公司的核心系统都在使用类似的模式来保证高并发下的稳定性。

备用