亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

如何通過SpringBoot實現(xiàn)商城秒殺系統(tǒng)

 更新時間:2019年11月20日 09:21:41   作者:念_響  
這篇文章主要介紹了如何通過SpringBoot實現(xiàn)商城秒殺系統(tǒng),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下

這篇文章主要介紹了如何通過SpringBoot實現(xiàn)商城秒殺系統(tǒng),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下

學(xué)習(xí)自:地址

1.主要流程

1.1數(shù)據(jù)庫:

  

1.2 環(huán)境

window下:Zookeeper,Redis,rabbitmq-server。jdk1.8以上。

1.3 介紹

這里只做秒殺部分功能,其他功能不會涉及。項目運行后可訪問秒殺商品頁面

當(dāng)用戶沒登陸,點擊詳情會跳轉(zhuǎn)到登陸頁面。

用戶登陸后可以查看商品的詳情并進行搶購。

注意,用戶對于一件商品只能搶購一次,進行第二次搶購時會被拒絕。當(dāng)用戶搶購成功時會異步發(fā)送一封郵件給用戶。

主要邏輯就是以上。接下來看代碼

1.4 項目結(jié)構(gòu),api封裝一些枚舉和返回值,model主要是實體類和sql映射文件,service實現(xiàn)業(yè)務(wù)邏輯代碼。

  

1.5 顯示秒殺商品到頁面以及用戶的操作使用的還是MVC模式,不細(xì)講。主要看如實現(xiàn)高并發(fā)下的秒殺。

要細(xì)述的話,東西太多,如果想深入了解,可點擊上面的鏈接。

基本的秒殺邏輯如下,判斷用戶是否已經(jīng)搶購過該商品,如果沒有則查詢待秒殺商品詳情,判斷該商品是否可以別秒殺,判斷依據(jù)為庫存是否足夠

如果符合條件,則該商品庫存減1,接著,再一次判斷扣減是否成功,如果扣減成功則生成秒殺成功的訂單,同時通知用戶秒殺成功的信息。

public Boolean killItem(Integer killId, Integer userId) throws Exception {
    Boolean result=false;

    //TODO:判斷當(dāng)前用戶是否已經(jīng)搶購過當(dāng)前商品
    if (itemKillSuccessMapper.countByKillUserId(killId,userId) <= 0){
      //TODO:查詢待秒殺商品詳情
      ItemKill itemKill=itemKillMapper.selectById(killId);

      //TODO:判斷是否可以被秒殺canKill=1?
      if (itemKill!=null && 1==itemKill.getCanKill() ){
        //TODO:扣減庫存-減一
        int res=itemKillMapper.updateKillItem(killId);

        //TODO:扣減是否成功?是-生成秒殺成功的訂單,同時通知用戶秒殺成功的消息
        if (res>0){
          commonRecordKillSuccessInfo(itemKill,userId);

          result=true;
        }
      }
    }else{
      throw new Exception("您已經(jīng)搶購過該商品了!");
    }
    return result;
  }

代碼優(yōu)化1:使用redis的分布式鎖,使用當(dāng)前秒殺商品的id和當(dāng)前用戶的id組成一個key,使用StringBuffer拼接,使用雪花算法生成一個value,存進redis中。

@Autowired
  private StringRedisTemplate stringRedisTemplate;
  /**
   * 商品秒殺核心業(yè)務(wù)邏輯的處理-redis的分布式鎖
   * @param killId
   * @param userId
   * @return
   * @throws Exception
   */
  @Override
  public Boolean killItemV3(Integer killId, Integer userId) throws Exception {
    Boolean result=false;

    if (itemKillSuccessMapper.countByKillUserId(killId,userId) <= 0){

      //TODO:借助Redis的原子操作實現(xiàn)分布式鎖-對共享操作-資源進行控制
      ValueOperations valueOperations=stringRedisTemplate.opsForValue();
      final String key=new StringBuffer().append(killId).append(userId).append("-RedisLock").toString();
      final String value=RandomUtil.generateOrderCode();
      Boolean cacheRes=valueOperations.setIfAbsent(key,value); //luna腳本提供“分布式鎖服務(wù)”,就可以寫在一起
      //TOOD:redis部署節(jié)點宕機了
      if (cacheRes){
        stringRedisTemplate.expire(key,30, TimeUnit.SECONDS);

        try {
          ItemKill itemKill=itemKillMapper.selectByIdV2(killId);
          if (itemKill!=null && 1==itemKill.getCanKill() && itemKill.getTotal()>0){
            int res=itemKillMapper.updateKillItemV2(killId);
            if (res>0){
              commonRecordKillSuccessInfo(itemKill,userId);

              result=true;
            }
          }
        }catch (Exception e){
          throw new Exception("還沒到搶購日期、已過了搶購時間或已被搶購?fù)戤叄?);
        }finally {
          if (value.equals(valueOperations.get(key).toString())){
            stringRedisTemplate.delete(key);
          }
        }
      }
    }else{
      throw new Exception("Redis-您已經(jīng)搶購過該商品了!");
    }
    return result;
  }

代碼優(yōu)化2:將 Boolean cacheRes=lock.tryLock(30,10,TimeUnit.SECONDS); 每隔30秒判斷當(dāng)前用戶是否超時寫在了鎖外面,不會因為一次卡頓而影響整個程序。

@Autowired
  private RedissonClient redissonClient;

  /**
   * 商品秒殺核心業(yè)務(wù)邏輯的處理-redisson的分布式鎖
   * @param killId
   * @param userId
   * @return
   * @throws Exception
   */
  @Override
  public Boolean killItemV4(Integer killId, Integer userId) throws Exception {
    Boolean result=false;

    final String lockKey=new StringBuffer().append(killId).append(userId).append("-RedissonLock").toString();
    RLock lock=redissonClient.getLock(lockKey);

    try {
      Boolean cacheRes=lock.tryLock(30,10,TimeUnit.SECONDS);
      if (cacheRes){
        //TODO:核心業(yè)務(wù)邏輯的處理
        if (itemKillSuccessMapper.countByKillUserId(killId,userId) <= 0){
          ItemKill itemKill=itemKillMapper.selectByIdV2(killId);
          if (itemKill!=null && 1==itemKill.getCanKill() && itemKill.getTotal()>0){
            int res=itemKillMapper.updateKillItemV2(killId);
            if (res>0){
              commonRecordKillSuccessInfo(itemKill,userId);

              result=true;
            }
          }
        }else{
          throw new Exception("redisson-您已經(jīng)搶購過該商品了!");
        }
      }
    }finally {
      lock.unlock();
      //lock.forceUnlock();
    }
    return result;
  }

代碼優(yōu)化3:

@Autowired
  private CuratorFramework curatorFramework;

  private static final String pathPrefix="/kill/zkLock/";

  /**
   * 商品秒殺核心業(yè)務(wù)邏輯的處理-基于ZooKeeper的分布式鎖
   * @param killId
   * @param userId
   * @return
   * @throws Exception
   */
  @Override
  public Boolean killItemV5(Integer killId, Integer userId) throws Exception {
    Boolean result=false;

    InterProcessMutex mutex=new InterProcessMutex(curatorFramework,pathPrefix+killId+userId+"-lock");
    try {
      if (mutex.acquire(10L,TimeUnit.SECONDS)){

        //TODO:核心業(yè)務(wù)邏輯
        if (itemKillSuccessMapper.countByKillUserId(killId,userId) <= 0){
          ItemKill itemKill=itemKillMapper.selectByIdV2(killId);
          if (itemKill!=null && 1==itemKill.getCanKill() && itemKill.getTotal()>0){
            int res=itemKillMapper.updateKillItemV2(killId);
            if (res>0){
              commonRecordKillSuccessInfo(itemKill,userId);
              result=true;
            }
          }
        }else{
          throw new Exception("zookeeper-您已經(jīng)搶購過該商品了!");
        }
      }
    }catch (Exception e){
      throw new Exception("還沒到搶購日期、已過了搶購時間或已被搶購?fù)戤叄?);
    }finally {
      if (mutex!=null){
        mutex.release();
      }
    }
    return result;
  }

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • resty client使用Java客戶端來訪問Api

    resty client使用Java客戶端來訪問Api

    這篇文章主要介紹了resty-client使用Java客戶端來訪問Api的驗證權(quán)限,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步
    2022-03-03
  • Java中的static和final關(guān)鍵字的使用詳解

    Java中的static和final關(guān)鍵字的使用詳解

    這篇文章主要介紹了Java中的static和final關(guān)鍵字的使用詳解,  當(dāng)方法名前有static,即為static方法,可以方便我們無需創(chuàng)建對象也可以調(diào)用此方法,靜態(tài)方法比較拉,只可以訪問 靜態(tài)的 屬性/變量/方法,無法訪問非靜態(tài)的這些屬性/變量/方法,需要的朋友可以參考下
    2024-01-01
  • Java 多線程的同步代碼塊詳解

    Java 多線程的同步代碼塊詳解

    這篇文章主要介紹了Java 多線程的同步代碼塊,使用synchronized關(guān)鍵字創(chuàng)建線程同步方法是實現(xiàn)線程同步的關(guān)鍵,需要的朋友可以參考下
    2021-10-10
  • java安全fastjson1.2.24反序列化TemplatesImpl分析

    java安全fastjson1.2.24反序列化TemplatesImpl分析

    這篇文章主要介紹了java安全fastjson1.2.24反序列化TemplatesImpl分析,fastjson是alibaba開源的一個用于處理json數(shù)據(jù)格式的解析庫,它支持將java對象解析成json字符串格式的數(shù)據(jù),也可以將json字符串還原成java對象
    2022-07-07
  • Spring Cloud Stream微服務(wù)消息框架原理及實例解析

    Spring Cloud Stream微服務(wù)消息框架原理及實例解析

    這篇文章主要介紹了Spring Cloud Stream微服務(wù)消息框架原理及實例解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-06-06
  • Springboot Thymeleaf實現(xiàn)HTML屬性設(shè)置

    Springboot Thymeleaf實現(xiàn)HTML屬性設(shè)置

    這篇文章主要介紹了Springboot Thymeleaf實現(xiàn)HTML屬性設(shè)置,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2007-11-11
  • SpringBoot多種生產(chǎn)打包方式詳解

    SpringBoot多種生產(chǎn)打包方式詳解

    生產(chǎn)上發(fā)布?Spring?Boot?項目時,流程頗為繁瑣且低效,但凡代碼有一丁點改動,就得把整個項目重新打包部署,耗時費力不說,生成的?JAR?包還特別臃腫,體積龐大,本文給大家介紹了SpringBoot多種生產(chǎn)打包方式,需要的朋友可以參考下
    2025-01-01
  • JAVA構(gòu)造器是否為靜態(tài)方法你知道嗎

    JAVA構(gòu)造器是否為靜態(tài)方法你知道嗎

    這篇文章主要為大家詳細(xì)介紹了JAVA構(gòu)造器是否為靜態(tài)方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-02-02
  • springboot配置mysql連接的實例代碼

    springboot配置mysql連接的實例代碼

    這篇文章主要介紹了springboot配置mysql連接的實例代碼,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-01-01
  • 基于Docker的K8s(Kubernetes)集群部署方案

    基于Docker的K8s(Kubernetes)集群部署方案

    這篇文章主要介紹了基于Docker的K8s(Kubernetes)集群部署方案,文中介紹了安裝k8s的可視化界面的相關(guān)操作,需要的朋友可以參考下
    2024-01-01

最新評論