redisトークンメカニズムを用いて電子商取引の秒殺を実現する

2911 ワード

双11当社の秒殺活動(redisトークンメカニズム)


説明:当社はサービス会社であり、電子商取引会社ではないため、在庫削減などの事務操作技術の選択型には関与しない:redisのlistデータ型の「スタック」の特徴は行い、redisは多重io多重化を採用し、メモリベースの単一スレッドデータベースを採用しているため、プログラムが速く、マルチスレッド同時発生による超過販売問題もなく、単純な楽観ロックで秒殺を実現し、ユーザーの大量の失敗問題を形成することもない
ここでは食事時間を利用して簡単なコードを書いて実現していますが、間違っている点が指摘できます.
準備作業:秒殺開始前に、プログラムを事前に利用して秒殺が必要な商品(サービス)をredisのlist.に書き込む.注:一中商品(サービス)一keyは、この商品が50個を秒殺する場合、listに50個の一意の標識(トークン)を格納する.
1.トークンの取得
public boolean miaoshaTokenFromRedis(Integer goodsId, String user) {
    String token = (String)redisTemplate.boundListOps("token_goods_"+goodsId).rightPop();
    if(token == null || token.equals("")){
        return false;
    }else{
        //             ,             
  
        String yes  = (String)redisTemplate.boundValueOps(token).get();
        if(yes != null && yes.equals("yes")) {
            System.out.println("  token     ,     ");
            redisTemplate.boundListOps("token_goods_"+goodsId).remove(1,token);
            return false;
        }
        //value     (token,    )---           
        redisTemplate.boundHashOps("user_token").put(user,{token,new Date()});
        return true;
    }
}

2.トークンの返却(タイミングタスクは5 sごとに実行)
public boolean returnToken(String user) {
    //         
    String token =  (String) redisTemplate.boundHashOps("user_token").get(user);
    if(token == null || token.equals("")){
        return false;
    }else {
        //    id     list         
        String goodsId = token.split("_")[1];
        redisTemplate.boundListOps("token_goods_"+goodsId).leftPush(token);
        return true;
    }
}

3.支払い成功
public boolean payTokenToOrder(String user) {
    //         
    String token =  (String) redisTemplate.boundHashOps("user_token").get(user);
    if(token == null || token.equals("")){
        return false;
    }else {
        //     token      ,           token       token    
        //  redis    token     
        //redisTemplate.boundValueOps("key").setIfAbsent("value")
        //      key  ,       false,     ,  s     value,    true
        boolean flag = redisTemplate.boundValueOps(token).setIfAbsent("yes");
        //  token       flag=true
        if(flag) {
            //    (f  )id
            String goodsId = token.split("_")[1];
            Order order = new Order();
            order.setUser(user);
            order.setGoodId(Integer.parseInt(goodsId));
            orderMapper.insert(order);
            //        ,      ,        ,      
            redisTemplate.boundHashOps("user_token").delete(user);//       token

            redisTemplate.boundListOps("token_goods_" + goodsId).remove(1, token);//  token,         
        }
        return true;
    }
}