php redis实现秒杀功能

主要针对并发情况下,通过redis的分布式锁和队列的方式进行处理的代码

Queue:{商品ID}:   数据类型是有序集合(zset),成员是用户ID,score是用户入队的时间戳

Lock:Queue:{商品ID}: 数据类型是字符串(string),存储的是该锁的过期时间

goods:{商品ID}:stock: 存储的是商品的库存数量

简单介绍demo代码中的实现思路:

将当前秒杀的商品id作为一个队列名称

$queue_name = “Queue:{商品ID}”;

对$queue_name进行加锁

    通过setnx(满足原子性)实现加锁  :$redis->setnx("Lock:Queue:{商品ID}",  $expire time)

    加锁成功,给该锁设置一个过期时间,主要是为了防止死锁

    如果加锁失败,通过设置休眠时间,进行循环请求

加锁成功后,判断队列中的成员数是否超过指定的大小

$count = $this->redis->zCard("Queue:{$name}");
if($count >=  $this->redis->get("goods:{$name}:stock")) {
    $this->lockModel->unlock("Queue:$name");
    return '超过指定集合数量';
}

 判断用户ID是否存在队列中,如不存在则加入队列(score:存入的是当前时间戳 )

if (false === $this->redis->zScore("Queue:$name", $user_id)) {
    $this->redis->zAdd("Queue:$name", $score, $user_id);
}

入队成功,进行解锁$redis->del("Lock:Queue:{商品ID}");提示用户抢购成功。成功的用户会跳转到确认购买的页面,点击确认后才会生成订单、出队等后续操作

ps: 针对多个账号,一次性发送多个请求可以通过ip的访问频率的限制来预防

参考文章:http://blog.jobbole.com/95156/

demo代码的下载地址:https://github.com/Ritajiajia/redis_test/tree/master/test/seckill

    

转载于:https://my.oschina.net/u/863367/blog/789653

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值