Redis锁怎么用来防止并发攻击,简单说就是帮你撑住高并发那波流量压力
- 问答
- 2025-12-24 01:01:06
- 3
说到用Redis锁来防止并发攻击,撑住高并发流量,核心思想其实很简单,就跟你去抢限量商品或者医院挂号是一个道理,想象一下,10000个人同时在线抢100张票,如果售票处(也就是你的服务器)没有维持秩序,大家一窝蜂冲上去,售票员同时处理所有人的请求,很可能导致一张票被卖给了好几个人,或者系统直接卡死崩溃,Redis锁在这里扮演的角色,就是一个在售票窗口前维持秩序的“保安”,他一次只放一个人进去买票,后面的人必须排队,等前面的人买完出来了,再放下一个进去,这样虽然看起来慢了点,但保证了票不会卖重,系统也不会被挤垮。
这个“保安”用的工具,就是Redis,Redis因为速度极快,所有来抢票的人(并发请求)都先得去Redis这里领一个“通行证”(也就是锁),这个通行证有几个关键特点,理解了这几点,你就明白了Redis锁的精髓。
第一,原子性发放,这个保安发通行证的动作是瞬间完成的,不可能出现他正准备把通行证递给A的时候,B突然伸手把通行证抢走了,在技术里,这对应Redis的SET key value NX PX milliseconds命令。NX意思是只有这个key不存在的时候才能设置成功(相当于通行证还没发出去),PX是设置一个过期时间(比如5秒),这个命令的执行是一个不可分割的原子操作,确保了在高并发下,只有一个请求能成功设置这个key,也就是只有一个人能拿到锁,这是最最基础的一点,如果不用原子命令,自己先get再set,在并发下锁肯定会出问题。

第二,设置过期时间,这是非常非常重要的一点,是避免系统死锁的生命线,想象一下,如果拿到通行证的那个人,进去买票的时候突然晕倒了(比如你的业务代码执行到一半,服务器突然宕机了),那他永远也不会出来把通行证还回去,后面所有的人就都只能干等着,系统就彻底卡死了,保安在发通行证的时候,会同时说一句:“这个通行证5秒后自动作废”,这样,即使那个人晕倒了,5秒后通行证自动失效,保安就可以继续放下一个人进去,在Redis里,就是给锁设置的过期时间,无论你的业务逻辑是否执行完毕,锁到了一定时间都会自动释放,保证了系统不会因为某个意外而永久阻塞。
第三,谁加的锁谁释放,这听起来是废话,但在高并发下很容易出错,假设A拿到了锁,设置了5秒过期,但是A的业务逻辑比较复杂,执行了6秒,这时候锁已经自动过期释放了,B请求趁机拿到了锁,此时A的代码终于执行完了,它要去释放锁,如果它不做判断,直接删除锁的key,那么它删除的其实是B刚刚创建的锁!这就乱套了,正确的做法是,每个请求在加锁时,要生成一个唯一的值(比如UUID)作为锁的value,在释放锁的时候,先获取一下当前锁的value,如果跟自己当初设置的一样,证明锁还是自己的,才能删除,否则,就不能删,这个“获取值+判断+删除”的操作也必须是原子的,通常用Lua脚本来实现,因为Lua脚本在Redis中是单线程执行的,能保证这一系列操作不被打断。

在实际面对高并发攻击时,这套机制是怎么“撑住”压力的呢?
-
过滤无效请求:真正的攻击流量往往是瞬间海量的,Redis锁就像一个高效的过滤器,它把这些海量请求强行“串行化”了,绝大部分请求在尝试获取锁的那一刻就会失败(因为
SET NX失败),然后你可以让这些请求直接返回“请稍后再试”的提示,这样,真正进入核心业务逻辑(比如数据库读写)的请求,就只有拿到锁的那一个,数据库的压力瞬间就从一万降到了一,自然就撑住了。
-
保护共享资源:高并发下最怕的就是对共享资源(比如商品库存、用户账户余额)进行“超卖”或错误更新,锁确保了在同一时间,只有一个线程能操作这个资源,比如扣减库存,一定是“查询库存 -> 判断是否足够 -> 扣减”这个流程完整地、不被干扰地执行完,数据的一致性得到了保障。
-
避免重复处理:有些场景下,比如用户手快连续点击了两次提交订单,或者消息队列的同一条消息被消费了多次,通过一个与订单ID或消息ID绑定的Redis锁,可以确保同一笔订单或同一条消息的处理逻辑只会被执行一次,避免了重复下单或重复消费的问题。
Redis锁(特别是这种单Redis节点的简单锁)也不是万能的,它有一个潜在问题是,如果你的业务逻辑执行时间不稳定,有时长有时短,你很难设置一个完美的过期时间,设短了,可能业务没执行完锁就丢了,导致两个请求同时进入临界区;设长了,万一服务器宕机,恢复服务的时间就会变长,对于更苛刻的场景,人们会使用更复杂的锁,比如Redlock算法,它通过多个独立的Redis主节点来共同决策,以换取更高的可靠性,但代价是更复杂、性能更低。
用Redis锁来扛高并发,核心就是利用Redis单线程原子操作的特性,扮演一个高效的“串行化保安”,通过原子加锁、设置超时、安全释放这三板斧,将洪水般的并发请求转化为有序的队列,用“牺牲”掉绝大部分请求的即时性(让它们快速失败)为代价,来换取核心系统和数据的安全与稳定,从而帮你撑过那波最凶猛的高并发流量冲击,它是一种简单、有效且非常常用的技术手段。
(参考资料:这个概念主要基于Redis官方文档中关于SET命令NX和PX参数的说明,以及分布式系统领域中关于分布式锁的基本设计原则,比如Martin Kleppmann的论文《How to do distributed locking》中讨论的相关内容,这些原则在业界实践中被广泛采纳和应用。)
本文由芮以莲于2025-12-24发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:https://haoid.cn/wenda/67241.html
