Java高併發秒殺系統(一)
本文內容整理自慕課網上的一套免費教學視訊–Java高併發秒殺API。課程的內容包括了秒殺業務分析、開發專案的Dao層、Service層以及Web層。其中使用的技術框架有:Spring、SpringMVC、MyBatis、Redis、Boostrap、jQuery。
1.秒殺系統分析
1.1 秒殺系統業務分析
秒殺系統的核心是對庫存的處理,業務流程圖如下所示
使用者針對庫存業務分析
- 減庫存
- 記錄購買明細 (記錄秒殺成功資訊)
1)記錄誰購買成功了
2)成功的時間/有效期
3)付款/發貨資訊
1.2 秒殺系統技術分析
為什麼需要事務?
一旦使用者秒殺成功系統需要做兩步操作,減庫存以及記錄購買明細。利用資料庫可以實現這操作的”事務”特性。如果沒有控制事務,可能會發生如下情況:- 減庫存成功而記錄購買明細失敗,會導致少賣
- 記錄購買明細成功而減庫存失敗,會導致超賣
資料落地方案選擇
關於資料如何落地,有MySQL和NoSQL這兩種方案選擇。- MySQL是關係型資料庫,它有多種儲存引擎,只有InnoDB儲存引擎支援事務。使用InnoDB儲存引擎可以幫助我們完成減庫存和記錄購買明細的事務操作,InnoDB支援行級鎖和表級鎖,預設使用行級鎖。
- NoSQL是非關係型資料庫,對於事務的支援做的不是很好,NoSQL更多的適用於高併發資料讀寫和海量資料儲存等應用場景。
事務機制依然是目前可靠的落地方案
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 檔案依賴管理。