在现如今电商盛行的时期,会出现很多促销活动,最为常见的就是秒杀。在秒杀系统中最为常见的问题就是会出现超卖的情况,那么如何来杜绝超卖的情形了,在业务逻辑层面可以使用缓存以及加锁的手法来避免超卖的情形。
现如今nosql已经非常流行和稳定了,在此我将通过redis和php来说明如何实现锁机制。当然我使用redis加锁并不是我的秒杀系统,而是最近做的一个项目有个用户提现,初期没有考虑到会有人恶意刷新接口,而导致用户无限制提现。经过查看nginx日志,发现用户在同一时间段,通过刷接口的方法超额提现,导致亏损
起初的提现代码如下:
看上面代码逻辑感觉似乎没有什么问题,确实,在正常的情况下是不会出现问题,如果有人恶意的去刷接口的话,上述问题就出现了。为了防止用户恶意刷接口,所以对现有代码做了如下修改
代码调整后似乎防止了用户刷接口的行为,但是后期有用户反映,自己提不了现了。经过一番查看,原来redis的值一直存在,虽然用户操作完成后会删除key,但是也会存在在用户没有完全操作完成而导致流程中断,所以会导致key删除失败,为了解决锁不释放的问题,又对上述代码进行修改,在设置锁的时候,设置一个过期时间,修复如下
这样就可以实现锁不释放的问题,但是上述代码除了使用incr操作外,还可以使用redis的setnx来代替,其实是一样的效果,但是无论你用那种还是有点问题就是,当你写入成功之后,突然断网或服务器宕机的情况,这时还会出现上述问题,那应该如何来解决呢。其实完全可以通过redis的 Multi/Exec结合来解决上述问题,其代码如下
这样就可以解决突然情况带来的妖怪问题了
总结:通过redis可以实现大并发的数据请求操作,通过事务的操作来加锁和释放锁,达到数据完整性
虽然上述问题解决了,但是代码还是有待优化,从 2.6.12 起,SET 涵盖了 SETEX 的功能,并且 SET 本身已经包含了设置过期时间的功能,也就是说,我们前面需要的功能只用 SET 就可以实现。所以上述代码可以简化为
以上就是如何解决并发和恶意刷接口的解决方法,以作记录
Original: https://www.cnblogs.com/tm2015/p/7845503.html
Author: 铁猛
Title: php在大并发下redis锁实现
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/589381/
转载文章受原作者版权保护。转载请注明原作者出处!