1. 程式人生 > >Java高併發秒殺系統(一)

Java高併發秒殺系統(一)

本文內容整理自慕課網上的一套免費教學視訊–Java高併發秒殺API。課程的內容包括了秒殺業務分析、開發專案的Dao層、Service層以及Web層。其中使用的技術框架有:Spring、SpringMVC、MyBatis、Redis、Boostrap、jQuery。

1.秒殺系統分析

1.1 秒殺系統業務分析

  1. 秒殺系統的核心是對庫存的處理,業務流程圖如下所示
    業務流程圖

  2. 使用者針對庫存業務分析

    • 減庫存
    • 記錄購買明細 (記錄秒殺成功資訊)
      1)記錄誰購買成功了
      2)成功的時間/有效期
      3)付款/發貨資訊

這裡寫圖片描述

1.2 秒殺系統技術分析

  1. 為什麼需要事務?
    一旦使用者秒殺成功系統需要做兩步操作,減庫存以及記錄購買明細。利用資料庫可以實現這操作的”事務”特性。如果沒有控制事務,可能會發生如下情況:

    • 減庫存成功而記錄購買明細失敗,會導致少賣
    • 記錄購買明細成功而減庫存失敗,會導致超賣
  2. 資料落地方案選擇
    關於資料如何落地,有MySQL和NoSQL這兩種方案選擇。

    • MySQL是關係型資料庫,它有多種儲存引擎,只有InnoDB儲存引擎支援事務。使用InnoDB儲存引擎可以幫助我們完成減庫存和記錄購買明細的事務操作,InnoDB支援行級鎖和表級鎖,預設使用行級鎖。
    • NoSQL是非關係型資料庫,對於事務的支援做的不是很好,NoSQL更多的適用於高併發資料讀寫和海量資料儲存等應用場景。

    事務機制依然是目前可靠的落地方案

  3. MySQL實現秒殺的難點分析
    當一個使用者成功秒殺某件商品後,其他秒殺這件商品的使用者只能等到,直到上一個使用者成功提交事務或者回滾事務,他才能得到鎖執行秒殺操作。鎖的競爭,就是採用資料庫方案的難點問題。
    這裡寫圖片描述

MySQL實現秒殺的機制是:事務+行級鎖
這裡寫圖片描述

Start Transaction
Update 庫存數量
Insert 購買明細
Commit

2.秒殺系統實現

2.1 Dao層實現

  • 資料庫指令碼
    建立秒殺商品表、秒殺成功明細表。
-- 資料庫初始化指令碼
-- 建立資料庫
CREATE DATABASE seckill;

-- 使用資料庫
USE seckill;

-- 建立秒殺庫存表
CREATE TABLE seckill(
  `seckill_id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '商品庫存id'
, `name` VARCHAR(120) NOT NULL COMMENT '商品名稱', `number` INT NOT NULL COMMENT '庫存數量', `start_time` DATETIME NOT NULL COMMENT '秒殺開啟時間', `end_time` DATETIME NOT NULL COMMENT '秒殺結束時間', `create_time` DATETIME NOT NULL DEFAULT now() COMMENT '建立時間', PRIMARY KEY (seckill_id), KEY idx_start_time(start_time), KEY idx_end_time(end_time), KEY idx_create_time(create_time) ) ENGINE=InnoDB AUTO_INCREMENT=1000 DEFAULT CHARSET=utf8 COMMENT='秒殺庫存表';
-- 初始化資料 INSERT INTO seckill(name,number,start_time,end_time) VALUES ('1000元秒殺iPhone6',100,'2017-11-19 00:00:00','2017-11-20 00:00:00'); INSERT INTO seckill(name,number,start_time,end_time) VALUES ('500元秒殺ipad2',200,'2017-11-20 00:00:00','2017-11-21 00:00:00'); INSERT INTO seckill(name,number,start_time,end_time) VALUES ('300元秒殺小米4',300,'2017-11-21 00:00:00','2017-11-22 00:00:00'); INSERT INTO seckill(name,number,start_time,end_time) VALUES ('200元秒殺紅米note',400,'2017-11-22 00:00:00','2017-11-23 00:00:00'); -- 秒殺成功明細表 -- 使用者登入認證相關的資訊 CREATE TABLE success_killed( `seckill_id` BIGINT NOT NULL COMMENT '秒殺商品id', `user_phone` BIGINT NOT NULL COMMENT '使用者手機號', `state` TINYINT NOT NULL DEFAULT -1 COMMENT '狀態標識:-1:無效 0:成功 1:已付款', `create_time` DATETIME NOT NULL COMMENT '建立時間', PRIMARY KEY (seckill_id,user_phone), /* 聯合主鍵 */ KEY idx_create_time(create_time) )ENGINE = InnoDB DEFAULT CHARSET = utf8 COMMENT = '秒殺成功明細'; -- 連線資料庫控制檯命令 mysql -uroot -p -- 查看錶結構 show create table seckill\G
  • 建立工程
    可以使用IDE工具建立一個maven專案,也可以可以通過maven命令來建立一個專案的骨架。可以通過如下命令建立一個web專案
mvn archetype:generate -DgroupId=com.seckill -DartifactId=seckill -DarchetypeArtifactId=maven-archetype-webapp 

用maven命令創建出來的專案servlet版本比較低,不支援el表示式,需要手動將web.xml中servlet的版本改為3.1。

  • 整合Spring和MyBatis

在resources下建立jdbc.properties檔案

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/seckill?useUnicode=true&characterEncoding=utf8
username=root
password=root

在resources下建立mybatis-config.xml檔案

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 配置全域性屬性-->
    <settings>
        <!-- 使用jdbc的getGeneratedKeys 獲取資料庫自增主鍵值-->
        <setting name="useGeneratedKeys" value="true"/>
         <!-- 使用列別名替換列名 預設:true
            select name as title from table
        -->
        <setting name="useColumnLabel" value="true" />
        <!-- 開啟駝峰命名轉換:Table(create_time) -> Entity(createTime) -->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
</configuration>

在resources目錄下建立一個新的目錄spring(存放所有spring相關的配置),spring目錄下建立spring-dao.xml檔案

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 配置整合mybatis過程-->
    <!-- 1:配置資料庫相關引數properties的屬性:${url} -->
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <!-- 2:資料庫連線池-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!-- 配置連線池屬性-->
        <property name="driverClass" value="${driver}" />
        <property name="jdbcUrl" value="${url}" />
        <property name="user" value="${username}" />
        <property name="password" value="${password}" />

        <!-- c3p0連線池的私有屬性-->
        <property name="maxPoolSize" value="30" />
        <property name="minPoolSize" value="10" />
        <!-- 關閉連線後不自動commit-->
        <property name="autoCommitOnClose" value="false" />
        <!-- 獲取連線超時時間-->
        <property name="checkoutTimeout" value="1000" />
        <!-- 當獲取連線失敗重試次數-->
        <property name="acquireIncrement" value="2" />
     </bean>

    <!-- 約定大於配置-->
    <!-- 3:配置SqlSessionFactory物件-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 注入資料庫連線池-->
        <property name="dataSource" ref="dataSource" />
        <!-- 配置MyBatis全域性配置檔案:mybatis-config.xml-->
        <property name="configLocation" value="classpath:mybatis-config.xml" />
        <!-- 掃描entity包 使用別名-->
        <property name="typeAliasesPackage" value="com.seckill.entity" />
        <!-- 掃描sql配置檔案;mapper需要的xml檔案-->
        <property name="mapperLocations" value="classpath:mapper/*.xml" />
    </bean>

    <!-- 4:配置掃描Dao介面包,動態實現Dao介面,注入到Spring容器中-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- 注入sqlSessionFactory -->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
        <!-- 給出掃描Dao介面包 -->
        <property name="basePackage" value="com.seckill.dao" />
    </bean>

    <!-- 5:RedisDao配置-->
    <bean id="redisDao" class="com.seckill.dao.cache.RedisDao">
        <constructor-arg index="0" value="localhost"/>
        <constructor-arg index="1" value="6379" />
    </bean>

</beans>
  • resources下建立mapper目錄,mapper下專門存放dao對映檔案。

2.2 Service層實現

  • 配置事務
    resources/spring下建立spring-service.xml檔案
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!-- 掃描service包下所有使用註解的型別-->
    <context:component-scan base-package="com.seckill.service" />

    <!-- 配置事務管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!-- 注入資料庫連線池-->
        <property name="dataSource" ref="dataSource" />
    </bean>

    <!-- 配置基於註解的宣告式事務
         預設使用註解來管理事務行為
    -->
    <tx:annotation-driven transaction-manager="transactionManager" />
</beans>

在需要進行事務宣告的方法上用@Transactional註解

2.3 Web層實現

  • 整合SpringMVC
    配置web.xml
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1"
         metadata-complete="true">

    <!-- 修改servlet版本為3.1 -->
    <!-- 配置DispatcherServlet-->
    <servlet>
        <servlet-name>seckill-dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 配置SpringMVC需要載入的配置檔案
            Spring-dao.xml, spring-service.xml, spring-web.xml
            MyBatis -> Spring -> SpringMVC
        -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring/spring-*.xml</param-value>
        </init-param>
    </servlet>

    <servlet-mapping>
        <servlet-name>seckill-dispatcher</servlet-name>
        <!-- 預設匹配所有的請求-->
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>

resources/spring下建立spring-web.xml檔案

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- 配置SpringMVC-->
    <!-- 1.開啟SpringMVC註解模式-->
    <!-- 簡化配置
        1)自動註冊DefaultAnnotationHandlerMapping, AnnotationMethodHandlerAdapter
        2)提供一系列功能:資料繫結,數字和日期的format @NumberFormat,@DateTimeFormat,xml, json預設讀寫支援。
    -->
    <mvc:annotation-driven />

    <!-- 2.靜態資源預設servlet配置
        1)加入對靜態資源的處理:js,gif,png
        2)允許使用 "/" 做整體對映
    -->
    <mvc:default-servlet-handler />

    <!-- 3.配置jsp 顯示ViewResolver-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass"  value="org.springframework.web.servlet.view.JstlView"/>
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>

    <!-- 4.掃描web相關的bean-->
    <context:component-scan base-package="com.seckill.web" />
</beans>
  • 詳細頁流程邏輯
    這裡寫圖片描述

  • 介面設計
    秒殺功能的流程:秒殺介面暴露 -> 執行秒殺 -> 相關查詢,秒殺API的URL設計如下:
    這裡寫圖片描述

2.4 前端頁面

  • 引入Bootstrap
    通過cdn的方式引入Bootstrap相關的檔案
<!-- jQuery檔案。務必在bootstrap.min.js 之前引入 -->
<script src="https://cdn.bootcss.com/jquery/2.1.1/jquery.min.js"></script>
<!-- 最新的 Bootstrap 核心 JavaScript 檔案 -->
<script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
  • 倒計時外掛
<!-- jQuery countDown倒計時外掛-->
<script src="https://cdn.bootcss.com/jquery.countdown/2.2.0/jquery.countdown.js"></script>
  • cookie外掛
<!-- jQuery cookie外掛-->
<script src="https://cdn.bootcss.com/jquery-cookie/1.4.1/jquery.cookie.js"></script>

3.系統演示

  • 秒殺列表頁面
    這裡寫圖片描述
  • 輸入手機號
    這裡寫圖片描述

    系統沒有做登入頁面,此處使用本地cookie作為替代方案。如果cookie中沒有手機號,則在彈出頁面填寫正確手機號就可以進入秒殺頁面。

  • 秒殺成功頁面
    這裡寫圖片描述

  • 秒殺未開始頁面
    這裡寫圖片描述

    秒殺還未開始時通過外掛顯示倒計時,倒計時時間以伺服器時間為準。

3.資源地址

相關推薦

Java併發系統()

本文內容整理自慕課網上的一套免費教學視訊–Java高併發秒殺API。課程的內容包括了秒殺業務分析、開發專案的Dao層、Service層以及Web層。其中使用的技術框架有:Spring、SpringMVC、MyBatis、Redis、Boostrap、jQu

SpringBoot實現Java併發系統之DAO層開發(

秒殺系統在如今電商專案中是很常見的,最近在學習電商專案時講到了秒殺系統的實現,於是打算使用SpringBoot框架學習一下秒殺系統(本專案基於慕課網的一套免費視訊教程:Java高併發秒殺API,視訊教程中講解的很詳細,非常感謝這位講師)。也是因為最近學習了Spr

SpringBoot實現Java併發系統併發優化

秒殺系統架構的設計和優化分析,以我一個小菜雞,目前是說不出來的o(╥﹏╥)o。 因此呢,我這裡僅從本專案已經實現的優化來介紹一下: 本專案中做到了以下優化: 秒殺介面採用md5加密方式防刷。 訂單表使用聯合主鍵方式,限制一個使用者只能購買該商品一次。 配合Spring事務

SpringBoot實現Java併發系統之Web層開發(三)

接著上一篇文章:SpringBoot實現Java高併發之Service層開發,今天我們開始講SpringBoot實現Java高併發秒殺系統之Web層開發。 Web層即Controller層,當然我們所說的都是在基於Spring框架的系統上而言的,傳統的SSH專案

SpringBoot實現Java併發系統之Service層開發(二)

繼上一篇文章:SpringBoot實現Java高併發秒殺系統之DAO層開發 我們建立了SpringBoot專案並熟悉了秒殺系統的表設計,下面我們將講解一下秒殺系統的核心部分:Service業務層的開發。 Service層又稱為業務層,在Spring階段主要是由@

Java併發系統API之SSM框架整合swagger與AdminLTE

初衷與整理描述 Java高併發秒殺系統API是來源於網上教程的一個Java專案,也是我接觸Java的第一個專案。本來是一枚c#碼農,公司計劃部分業務轉java,於是我利用業務時間自學Java才有了本文,本來接觸之初聽別人說,c#要轉java很容易,我也信

Java併發系統(二)

本文主要對秒殺系統在大併發的場景下效能瓶頸的做一個分析,以及秒殺系統的優化實現。秒殺系統的業務分析和系統實現,可以參考上一篇文章 Java高併發秒殺系統(一) 1.秒殺系優化分析 下圖列出秒殺的系統流程,其中紅色部分是可能發生高併發的地方,綠色則表

Java開發面試:併發系統如何設計與優化

      如今處在一個大資料時代,應屆生找工作面試高階Java開發工程師時,經常會被問一些和大資料相關的問題,比如大資料處理問題、高併發處理問題、資料優化問題等,筆者曾經遇到兩個比較經典的問題,高併發秒殺系統的設計優化問題和大資料檔案排序問題。在這裡總結了高併發秒殺系統

2017.4.26 慕課網--Java 併發API(

Java高併發秒殺API系列(一)                  -----------------業務分析及Dao層 第一章 課程介紹 1.1 內容介紹及業務分析 (1)課程內容 1 SSM框架的整合使用 2 秒殺類系統需求理解和實現 3 常用技術解決高併發問題 (

SSM專案實戰()--- 併發系統之DAO層

專案為慕課網上 搞定Java SSM框架開發的綜合案例–實現一個秒殺系統案例。 1.首先搭建專案 使用Maven構建來管理依賴項,pom.xml檔案: 此pom.xml可作為大多數ssm專案依賴的參考 <project xmlns="http:

【備忘】Java高效能併發系統實戰視訊教程

1-1 java高併發商城秒殺優化導學.mp41-2 專案環境搭建(Eclipse).mp41-3 專案環境搭建(IDEA).mp41-4 整合mybatis.mp41-5 安裝redis.mp41-6 整合redis上.mp41-7 整合redis中.mp41-8 整合r

併發系統架構設計 · 搶購、微信紅包、一元奪寶

秒殺業務在各業務中已然非常流行,這裡我將網際網路行業中的秒殺定義為:在非常短的時間內,將一件商品分成多份進行購買的行為。微信搶紅包、一元奪寶、雙11大促搶購等業務本質上都可視作秒殺業務。而最近大熱的搶紅包的難度在於這是和錢打交道的秒殺場景,對於事務的要求性更高。秒殺業務的

併發系統技術架 構解析和實踐

學來的,個人備忘 什麼是秒殺?難點在哪? 秒殺系統難點(what)  高併發、負載壓力大  競爭資源是有限的  避免對其他業務的影響  提防“黃牛黨” 秒殺系統應用場景(why)  商品搶購  群

慕課網-java併發api之併發優化-總結

1.架構優化 2.spring宣告式事務 宣告式事務:http://www.open-open.com/lib/view/open1414310646012.html 配置並使用Spring宣告式事務 在spring-service.xml中新增上配置事務管理器 <

Java併發API之service層實現(二)

二 service層實現 1.內容 站在使用者的角度設計介面 三個方向 :方法粒度,引數,返回型別 2.程式碼 SeckillService package org.seckill.service; import java.util.L

Java併發API(二)之Service層

1. 設計前的分析 分層的必要性 DAO層工作演變為:介面設計+SQL編寫(不需要其他雜七雜八的功能) 程式碼和SQL的分離,方便review(瀏覽) DAO拼接等邏輯在Service層完成(DAO只需負責SQL語句,其他都由Servi

併發系統總結

大家也許開發過高併發的系統或者秒殺程式,但肯定都有接觸過,像電商平臺的秒殺、搶購等活動,還有12306春運搶票。 活動週期短,瞬間流量大(高併發),技術在這種情況下,會發生和要做的事。 第一:高併發 技術要做的事,一方面優化程式,讓程式效能最優,單次請求時間能從50

JAVA併發API專案的學習筆記

設計Restful介面 SpringMVC整合Spring 在web.xml中配置DispatcherServlet建立web包建立spring-web.xml配置檔案 在spring-web.xml進行SpringMVC的配置 開啟SpringMVC註解模式servl

Java併發API之併發優化(四)

四 高併發優化 1.分析 1.詳情頁 部署到cdn上,這樣使用者訪問的是cdn不是伺服器了。 使用者在上網時通過運營商訪問最近的都會網路,都會網路訪問主幹網。 2.獲取系統時間 不用優化 訪問一次記憶體大概 10ns 無法使用cdn,適合伺服

JAVA併發API之DAO層】課程筆記

最近在慕課網上學習了【JAVA高併發秒殺API】系列課程,在此整理課程內容! 課程收穫:1、學習瞭如何通過maven建立web專案,pom.xml 檔案依賴管理。