Redis进阶 | 04.缓存击穿 - 分布式锁

本文介绍了缓存击穿现象,即当缓存中某个key失效时,大量请求直接穿透缓存导致数据库压力骤增。解决方案包括设置永不过期和使用分布式锁。分布式锁确保了互斥访问,防止死锁,并在加锁与解锁时保持原子性,同时具备自动续锁机制以防止锁过期。
摘要由CSDN通过智能技术生成

参考文章、视频

文章:Redis实现分布式锁的7种方案,及正确使用姿势

视频:什么是Redis缓存雪崩、穿透、击穿,十分钟给你讲的明明白白

1.缓存击穿

情形概述

缓存中某个key失效的瞬间,大量请求并发涌入,所有请求都打向了MySQL数据库,没等到Redis重建缓存便已宕机。

image-20220306181656374

解决方案

  • 设置永不过期:如果全部key都如此处理,可能导致OOM;
  • 分布式锁

2.分布式锁

原理概述

多线程并行访问时,第一个线程将抢到锁并重建缓存,其他线程没能抢到锁则进入休眠,待唤醒后从缓存中获取数据。

分布式锁

分布式锁特征

  1. 互斥性:只有一个线程持有锁,即一个key只能被一个线程锁住;
  2. 避免死锁:万一抢到锁的线程崩溃,锁能自动解开;
  3. 解铃还须系铃人:只有抢到锁的线程可以解开锁;
  4. 加锁与解锁都必须具有原子性:加锁可用set <key> <value> NX EX <expireSeconds>,解锁则使用lua脚本
  5. 正常执行时锁不能自动失效:在上锁后,开启watch dog线程定期续锁。

分布式锁核心技术点实现:

  • 互斥性、避免死锁、解铃还须系铃人

    – 上锁时,使用NX保证每个key只有一个值(即一个key只有一把锁);

    – 上锁时,使用EX <expireSeconds>避免因线程崩溃导致死锁;

    – 上锁时,以用户id作为value,在解锁时需要对value进行验证,确保上锁与解锁的为同一个人。

    # 示例:用户3119004000对3号商品上锁,锁有效时间为30s
    set product:3 3119004000 NX EX 30
    
  • 加锁与解锁必须具有原子性

    – 上锁不能用setNx,因为该指令不能设置有效时间,无法保证原子性;

    – 解锁只能用Lua脚本实现,因为解锁分为两步:

    ------ 验证:通过get指令获取value(用户id),判断上锁与解锁的人是否为同一个;

    ------ 解锁:通过del指令解锁(删除key)

  • 正常执行时锁不能自动失效

    在成功执行上锁(set …)之后,开启子线程,每隔一定时间(10s)判断主线程是否崩溃;若未崩溃,重新使用上锁指令来为锁续期。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值