zoukankan      html  css  js  c++  java
  • 基于Redis/Memcached的高并发秒杀设计

     如何设计高并发时的秒杀,是面试电商技术职位时必考的题目。今天在这里分享一下基于Redis或Memcached的技术方案,能解决重复提交、超发、高并发的问题。

     <?php 

    //预定义总库存
    define("TOTAL_STOCK", 5);
    //预定义商品编号
    define("ITEM_ID", "ITEM_001");

    $userId = $_GET['userId'];
    $userIdKey = ITEM_ID . '_' . $userId;

    $redis = new redis();
    //如果有多台Redis服务器,可根据商品编号哈希后得到其中一台redis的地址
    $result = $redis->connect('master104', 6379);

    //获取之前已经领取掉的数量
    $requested = $redis->get("requested");
    echo "领取前库存: " . (string)(TOTAL_STOCK - $requested) . "<br />";

    //如果已领取大于预定义库存,则认为库存为零,不允许继续
    if ($requested && ($requested >= TOTAL_STOCK))
    {
      echo "已领完,请下次再来";
      die();
    }

    //通过设置用户对该商品的领取状态,来检查该用户是否已领取过
    //如果使用Memcached的话,可以使用cas()
    if (!$redis->setnx($userIdKey, 1))
    {
      echo "您已领取过该商品,不允许重复领取";
      die();
    }

    //增加领取数量以减少库存。
    //高并发情况下可能会有多个incr()是成功的。但是没关系,在领取数大于库存数后,通过下面的if判断后,后面的请求都是无效的。
    $requested = $redis->incr("requested");

    //如果尝试增加的时候,发现库存已经为零了,需要重置用户领取状态
    if ($requested && ($requested > TOTAL_STOCK))
    {
      $redis->del($userIdKey);
      echo "已领完,请下次再来";
      die();
    }

    //以下可以做其他的后续操作,比如各种异步并行操作,或是投递消息到队列,等等
    //Step1
    //...
    //StepN

    //如果步骤进行到这里,不管以上的异步操作进行得如何,我们都必须认为用户已经领取成功。
    //即使有任何失败,我们都需要用技术手段帮用户完成上述Step1到StepN
    echo "领取成功!<br />";
    echo "领取后库存: " . (string)(TOTAL_STOCK - $requested) . "<br />";


    ?>

  • 相关阅读:
    【解题报告】CF939E
    【解题报告】洛谷P4653 [CEOI2017]Sure Bet
    【解题报告】洛谷P3406 海底高铁
    【解题报告】洛谷P1097 统计数字
    微信开发者工具下载和安装
    STS下载和安装
    HBuilderX下载和安装
    Navicat Premium下载与安装
    PLSQL下载和安装
    Oracle 11g的安装
  • 原文地址:https://www.cnblogs.com/harryc/p/5998831.html
Copyright © 2011-2022 走看看