1. 程式人生 > >java秒殺高併發------ 秒殺功能實現

java秒殺高併發------ 秒殺功能實現

先宣告,這裡只是簡單的秒殺功能的實現,後續文章寫了基於這個優化的。
評論讓我回去看看什麼叫高併發的請看看我文章的標題 java秒殺高併發------ 看到這個線了麼,說明這是很多篇文章。而且這個是我對高併發秒殺實現感興趣去慕課網學習記錄下來的筆記。評論別人前請先看下自己謝謝。

資料庫設計

商品表

CREATE TABLE `miaosha`.`Untitled`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `goods_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `goods_title` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `goods_img` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `goods_detail` longtext CHARACTER SET utf8 COLLATE utf8_general_ci COMMENT '商品詳情介紹',
  `goods_price` decimal(10, 2) DEFAULT 0.00 COMMENT '商品單價',
  `goods_stock` int(11) DEFAULT 0 COMMENT '商品庫存,-1表示沒有限制',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = MyISAM AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

訂單表

CREATE TABLE `miaosha`.`Untitled`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `user_id` bigint(20) DEFAULT NULL,
  `goods_id` bigint(20) DEFAULT NULL,
  `delivery_addr_id` bigint(20) DEFAULT NULL COMMENT '收貨地址ID',
  `goods_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '商品名稱',
  `goods_count` int(11) DEFAULT 0 COMMENT '商品數量',
  `goods_price` decimal(10, 2) DEFAULT 0.00 COMMENT '商品單價',
  `order_channel` tinyint(4) DEFAULT 0 COMMENT '1PC,2Android,3Ios',
  `status` tinyint(4) NOT NULL DEFAULT 0 COMMENT '訂單狀態,0新建支付,1已支付,2已發貨,3已收貨,4已退款,5已完成',
  `create_date` datetime DEFAULT NULL COMMENT '訂單建立時間',
  `pay_date` datetime DEFAULT NULL COMMENT '支付時間',
    PRIMARY KEY (`id`) USING BTREE) ENGINE = MyISAM AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

秒殺商品表(把秒殺拉出來,單獨做一個表,以後有其他活動在拉出來做一個表)

CREATE TABLE `miaosha`.`Untitled`  (
  `id` bigint(20) NOT NULL,
  `goods_id` bigint(20) DEFAULT NULL,
  `miaosha_price` decimal(10, 2) DEFAULT 0.00 COMMENT '秒殺價',
  `stock_count` int(11) DEFAULT NULL COMMENT '庫存數量',
  `start_date` datetime DEFAULT NULL COMMENT '秒殺開始時間',
  `end_date` datetime DEFAULT NULL COMMENT '秒殺結束時間',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = MyISAM CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Fixed;

秒殺訂單表

秒殺訂單表


CREATE TABLE `miaosha`.`Untitled`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `user_id` bigint(20) NOT NULL,
  `order_id` bigint(20) NOT NULL,
  `goods_id` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = MyISAM AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Fixed;

對應建立實體類
對商品資訊和對應的商品秒殺資訊獲取
一起獲取

@Mapper
public interface GoodsDao {
  @Select("select g.*,mg.stock_count,mg.start_date,mg.end_date from miaosha_goods mg left join goods g on mg.goods_id = g.id")
    public List<GoodsVo> listGoodsVo();
    }

單獨建立了返回的VO

建立的GoodsVO是 goods商品表和一些秒殺資訊的實體類,用於儲存查詢返回的資料

將返回的資料寫入 模板就可以了。

<div class="panel panel-default">
  <div class="panel-heading">秒殺商品列表</div>
  <table class="table" id="goodslist">
   <tr><td>商品名稱</td><td>商品圖片</td><td>商品原價</td><td>秒殺價</td><td>庫存數量</td><td>詳情</td></tr>
   <tr  th:each="goods,goodsStat : ${goodsList}">  
                <td th:text="${goods.goodsName}"></td>  
                <td ><img th:src="@{${goods.goodsImg}}" width="100" height="100" /></td>  
                <td th:text="${goods.goodsPrice}"></td>  
                <td th:text="${goods.miaoshaPrice}"></td>  
                <td th:text="${goods.stockCount}"></td>
                <td><a th:href="'/goods/to_detail/'+${goods.id}">詳情</a></td>  
     </tr>  
  </table>
</div>

這裡寫圖片描述

商品詳情
這裡寫圖片描述

秒殺功能實現

提交的時候就交了一個id

首先我們要判斷使用者是否登入,
然後判斷 根據這個商品ID獲取商品的庫存是否還有
是否已經秒殺成功了(根據訂單判斷)
沒有就要減少庫存,並且增加訂單和秒殺訂單。

@RequestMapping("/do_miaosha")
public String list(Model model, MiaoshaUser user, @RequestParam("goodsId") long goodsId){
    //沒登入就跳轉到登入頁面
    model.addAttribute("user",user);
    if (user==null){
        return "login";
    }
    //判斷庫存
    GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId);
    int stock = goods.getGoodsStock();
    if (stock<=0){//沒有庫存了.
        model.addAttribute("errmsg", CodeMsg.MIAO_SHA_OVER.getMsg());
        return "miaosha_fail";
    }
    //判斷是否已經秒殺到了
    MiaoshaOrder order  = orderService.getMiaoshaOrderByUserIdGoodsId(user.getId(),goodsId);
    if(order!=null){
        model.addAttribute("errmsg",CodeMsg.REPEATE_MIAOSHA.getMsg());
        return "miaosha_fail" ;
    }else {
        //秒殺
        //減庫存 下訂單 寫入秒殺訂單
        OrderInfo orderInfo = miaoshaService.miaosha(user,goods);
        model.addAttribute("orderInfo",orderInfo);
        model.addAttribute("goods",goods);
        return "order_detail";
    }

秒殺的操作寫在秒殺service方法中

每個service中的最好只使用自己的dao
如果要使用別的dao最好注入別的 service!!!

@Service
public class MiaoshaService {

    @Autowired
    GoodsService goodsServic;

    @Autowired
    OrderService orderService;

    @Transactional
    public OrderInfo miaosha(MiaoshaUser user, GoodsVo goods){
        //減少庫存 下訂單 寫入秒殺訂單
        goodsServic.reduceStock(goods);
        //訂單表,秒殺表
        OrderInfo orderInfo = orderService.createOrder(user,goods);



        return orderInfo;
    }

個訂單並且將插入的id封裝到原來的物件中
@SelectKey(keyColumn=“id”, keyProperty=“id”, resultType=long.class, before=false, statement=“select last_insert_id()”)



@Insert("insert into order_info(user_id, goods_id, goods_name, goods_count, goods_price, order_channel, status, create_date)values("
        + "#{userId}, #{goodsId}, #{goodsName}, #{goodsCount}, #{goodsPrice}, #{orderChannel},#{status},#{createDate} )")
        @SelectKey(keyColumn="id", keyProperty="id", resultType=long.class, before=false, statement="select last_insert_id()")long insert(OrderInfo orderInfo);

成功後就會跳轉到 訂單詳情。