├── src
├── main
│ ├── resources
│ │ ├── jmeter
│ │ │ ├── origin.png
│ │ │ ├── data-config.png
│ │ │ ├── operation.txt
│ │ │ ├── param-repeat.txt
│ │ │ ├── seckill.jmx
│ │ │ └── param.txt
│ │ ├── stress_test_result
│ │ │ ├── atomicInteger
│ │ │ │ ├── result_1.png
│ │ │ │ ├── result_2.png
│ │ │ │ └── result_3.png
│ │ │ ├── pessLockInMySQL
│ │ │ │ ├── result_1.png
│ │ │ │ ├── result_2.png
│ │ │ │ └── result_3.png
│ │ │ ├── posiLockInMySQL
│ │ │ │ ├── result_1.png
│ │ │ │ ├── result_2.png
│ │ │ │ └── result_3.png
│ │ │ └── posiLockInRedis
│ │ │ │ ├── result_1.png
│ │ │ │ ├── result_2.png
│ │ │ │ └── result_3.png
│ │ ├── sql
│ │ │ └── seckill.sql
│ │ ├── dao
│ │ │ └── SecKillMapper.xml
│ │ └── application.properties
│ └── java
│ │ └── com
│ │ └── scut
│ │ └── seckill
│ │ ├── web
│ │ ├── vo
│ │ │ └── SecKillResponse.java
│ │ └── req
│ │ │ └── SecKillRequest.java
│ │ ├── common
│ │ ├── Head.java
│ │ ├── GlobalExceptionHandler.java
│ │ ├── Message.java
│ │ └── SecKillEnum.java
│ │ ├── exception
│ │ └── SecKillException.java
│ │ ├── SecKillApp.java
│ │ ├── cache
│ │ ├── RedisCacheHandle.java
│ │ └── RedisLoaderListener.java
│ │ ├── constant
│ │ ├── SecKillStateConst.java
│ │ └── RedisCacheConst.java
│ │ ├── entity
│ │ ├── User.java
│ │ ├── Product.java
│ │ └── Record.java
│ │ ├── mapper
│ │ └── SecKillMapper.java
│ │ ├── mq
│ │ ├── RabbitMQReceiver.java
│ │ └── RabbitMQSender.java
│ │ ├── utils
│ │ └── SecKillUtils.java
│ │ ├── concurrent
│ │ └── AtomicStock.java
│ │ ├── config
│ │ ├── RedisCacheConfig.java
│ │ ├── RabbitmqCallBackConfig.java
│ │ └── MyBatisConfig.java
│ │ ├── controller
│ │ └── SecKillController.java
│ │ └── service
│ │ └── SecKillService.java
└── test
│ └── java
│ └── JUnitTest.java
├── .idea
├── vcs.xml
├── smartfox_info.xml
├── encodings.xml
├── modules.xml
├── misc.xml
├── libraries
│ ├── Maven__junit_junit_4_12.xml
│ ├── Maven__org_ow2_asm_asm_5_0_3.xml
│ ├── Maven__org_json_json_20140107.xml
│ ├── Maven__com_alibaba_druid_1_0_18.xml
│ ├── Maven__org_yaml_snakeyaml_1_17.xml
│ ├── Maven__redis_clients_jedis_2_8_1.xml
│ ├── Maven__org_mybatis_mybatis_3_4_0.xml
│ ├── Maven__org_objenesis_objenesis_2_1.xml
│ ├── Maven__com_alibaba_fastjson_1_2_31.xml
│ ├── Maven__org_slf4j_slf4j_api_1_7_21.xml
│ ├── Maven__com_fasterxml_classmate_1_3_1.xml
│ ├── Maven__net_minidev_json_smart_2_2_1.xml
│ ├── Maven__org_projectlombok_lombok_1_16_6.xml
│ ├── Maven__com_rabbitmq_amqp_client_3_6_3.xml
│ ├── Maven__org_hamcrest_hamcrest_core_1_3.xml
│ ├── Maven__org_assertj_assertj_core_2_5_0.xml
│ ├── Maven__org_slf4j_jul_to_slf4j_1_7_21.xml
│ ├── Maven__org_skyscreamer_jsonassert_1_3_0.xml
│ ├── Maven__commons_codec_commons_codec_1_10.xml
│ ├── Maven__net_minidev_accessors_smart_1_1.xml
│ ├── Maven__ch_qos_logback_logback_core_1_1_7.xml
│ ├── Maven__com_jayway_jsonpath_json_path_2_2_0.xml
│ ├── Maven__org_mockito_mockito_core_1_10_19.xml
│ ├── Maven__org_mybatis_mybatis_spring_1_3_0.xml
│ ├── Maven__org_slf4j_jcl_over_slf4j_1_7_21.xml
│ ├── Maven__org_apache_tomcat_tomcat_jdbc_8_5_5.xml
│ ├── Maven__org_apache_tomcat_tomcat_juli_8_5_5.xml
│ ├── Maven__org_hamcrest_hamcrest_library_1_3.xml
│ ├── Maven__org_slf4j_log4j_over_slf4j_1_7_21.xml
│ ├── Maven__ch_qos_logback_logback_classic_1_1_7.xml
│ ├── Maven__mysql_mysql_connector_java_5_1_39.xml
│ ├── Maven__org_apache_httpcomponents_httpcore_4_4_5.xml
│ ├── Maven__org_apache_commons_commons_pool2_2_4_2.xml
│ ├── Maven__org_apache_httpcomponents_httpclient_4_5_2.xml
│ ├── Maven__com_rabbitmq_http_client_1_0_0_RELEASE.xml
│ ├── Maven__com_fasterxml_jackson_core_jackson_core_2_8_3.xml
│ ├── Maven__org_springframework_spring_tx_4_3_3_RELEASE.xml
│ ├── Maven__org_apache_tomcat_embed_tomcat_embed_el_8_5_5.xml
│ ├── Maven__org_jboss_logging_jboss_logging_3_3_0_Final.xml
│ ├── Maven__javax_validation_validation_api_1_1_0_Final.xml
│ ├── Maven__org_springframework_spring_aop_4_3_3_RELEASE.xml
│ ├── Maven__org_springframework_spring_oxm_4_3_3_RELEASE.xml
│ ├── Maven__org_springframework_spring_web_4_3_3_RELEASE.xml
│ ├── Maven__org_springframework_spring_core_4_3_3_RELEASE.xml
│ ├── Maven__org_springframework_spring_jdbc_4_3_3_RELEASE.xml
│ ├── Maven__org_springframework_spring_test_4_3_3_RELEASE.xml
│ ├── Maven__org_apache_tomcat_embed_tomcat_embed_core_8_5_5.xml
│ ├── Maven__com_fasterxml_jackson_core_jackson_databind_2_8_3.xml
│ ├── Maven__org_springframework_spring_beans_4_3_3_RELEASE.xml
│ ├── Maven__org_springframework_spring_webmvc_4_3_3_RELEASE.xml
│ ├── Maven__org_hibernate_hibernate_validator_5_2_4_Final.xml
│ ├── Maven__org_springframework_amqp_spring_amqp_1_6_2_RELEASE.xml
│ ├── Maven__org_springframework_boot_spring_boot_1_4_1_RELEASE.xml
│ ├── Maven__org_springframework_spring_context_4_3_3_RELEASE.xml
│ ├── Maven__com_fasterxml_jackson_core_jackson_annotations_2_8_3.xml
│ ├── Maven__org_springframework_amqp_spring_rabbit_1_6_2_RELEASE.xml
│ ├── Maven__org_springframework_retry_spring_retry_1_1_4_RELEASE.xml
│ ├── Maven__org_springframework_spring_messaging_4_3_3_RELEASE.xml
│ ├── Maven__org_apache_tomcat_embed_tomcat_embed_websocket_8_5_5.xml
│ ├── Maven__org_springframework_spring_expression_4_3_3_RELEASE.xml
│ ├── Maven__org_springframework_boot_spring_boot_test_1_4_1_RELEASE.xml
│ ├── Maven__org_springframework_data_spring_data_redis_1_7_3_RELEASE.xml
│ ├── Maven__org_mybatis_spring_boot_mybatis_spring_boot_starter_1_1_1.xml
│ ├── Maven__org_springframework_boot_spring_boot_starter_1_4_1_RELEASE.xml
│ ├── Maven__org_springframework_spring_context_support_4_3_3_RELEASE.xml
│ ├── Maven__org_springframework_data_spring_data_commons_1_12_3_RELEASE.xml
│ ├── Maven__org_springframework_data_spring_data_keyvalue_1_1_3_RELEASE.xml
│ ├── Maven__org_springframework_boot_spring_boot_starter_web_1_4_1_RELEASE.xml
│ ├── Maven__org_springframework_boot_spring_boot_starter_amqp_1_4_1_RELEASE.xml
│ ├── Maven__org_springframework_boot_spring_boot_starter_jdbc_1_4_1_RELEASE.xml
│ ├── Maven__org_springframework_boot_spring_boot_starter_test_1_4_1_RELEASE.xml
│ ├── Maven__org_mybatis_spring_boot_mybatis_spring_boot_autoconfigure_1_1_1.xml
│ ├── Maven__org_springframework_boot_spring_boot_autoconfigure_1_4_1_RELEASE.xml
│ ├── Maven__org_springframework_boot_spring_boot_starter_redis_1_4_1_RELEASE.xml
│ ├── Maven__org_springframework_boot_spring_boot_starter_tomcat_1_4_1_RELEASE.xml
│ ├── Maven__org_springframework_boot_spring_boot_starter_logging_1_4_1_RELEASE.xml
│ └── Maven__org_springframework_boot_spring_boot_test_autoconfigure_1_4_1_RELEASE.xml
├── compiler.xml
├── inspectionProfiles
│ └── Project_Default.xml
└── uiDesigner.xml
├── pom.xml
├── SecKillDesign.iml
└── README.md
/src/main/resources/jmeter/origin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SkyScraperTwc/SecKillDesign/HEAD/src/main/resources/jmeter/origin.png
--------------------------------------------------------------------------------
/src/main/resources/jmeter/data-config.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SkyScraperTwc/SecKillDesign/HEAD/src/main/resources/jmeter/data-config.png
--------------------------------------------------------------------------------
/src/main/resources/stress_test_result/atomicInteger/result_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SkyScraperTwc/SecKillDesign/HEAD/src/main/resources/stress_test_result/atomicInteger/result_1.png
--------------------------------------------------------------------------------
/src/main/resources/stress_test_result/atomicInteger/result_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SkyScraperTwc/SecKillDesign/HEAD/src/main/resources/stress_test_result/atomicInteger/result_2.png
--------------------------------------------------------------------------------
/src/main/resources/stress_test_result/atomicInteger/result_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SkyScraperTwc/SecKillDesign/HEAD/src/main/resources/stress_test_result/atomicInteger/result_3.png
--------------------------------------------------------------------------------
/src/main/resources/stress_test_result/pessLockInMySQL/result_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SkyScraperTwc/SecKillDesign/HEAD/src/main/resources/stress_test_result/pessLockInMySQL/result_1.png
--------------------------------------------------------------------------------
/src/main/resources/stress_test_result/pessLockInMySQL/result_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SkyScraperTwc/SecKillDesign/HEAD/src/main/resources/stress_test_result/pessLockInMySQL/result_2.png
--------------------------------------------------------------------------------
/src/main/resources/stress_test_result/pessLockInMySQL/result_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SkyScraperTwc/SecKillDesign/HEAD/src/main/resources/stress_test_result/pessLockInMySQL/result_3.png
--------------------------------------------------------------------------------
/src/main/resources/stress_test_result/posiLockInMySQL/result_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SkyScraperTwc/SecKillDesign/HEAD/src/main/resources/stress_test_result/posiLockInMySQL/result_1.png
--------------------------------------------------------------------------------
/src/main/resources/stress_test_result/posiLockInMySQL/result_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SkyScraperTwc/SecKillDesign/HEAD/src/main/resources/stress_test_result/posiLockInMySQL/result_2.png
--------------------------------------------------------------------------------
/src/main/resources/stress_test_result/posiLockInMySQL/result_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SkyScraperTwc/SecKillDesign/HEAD/src/main/resources/stress_test_result/posiLockInMySQL/result_3.png
--------------------------------------------------------------------------------
/src/main/resources/stress_test_result/posiLockInRedis/result_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SkyScraperTwc/SecKillDesign/HEAD/src/main/resources/stress_test_result/posiLockInRedis/result_1.png
--------------------------------------------------------------------------------
/src/main/resources/stress_test_result/posiLockInRedis/result_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SkyScraperTwc/SecKillDesign/HEAD/src/main/resources/stress_test_result/posiLockInRedis/result_2.png
--------------------------------------------------------------------------------
/src/main/resources/stress_test_result/posiLockInRedis/result_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SkyScraperTwc/SecKillDesign/HEAD/src/main/resources/stress_test_result/posiLockInRedis/result_3.png
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/main/java/com/scut/seckill/web/vo/SecKillResponse.java:
--------------------------------------------------------------------------------
1 | package com.scut.seckill.web.vo;
2 |
3 | import lombok.Data;
4 |
5 | @Data
6 | public class SecKillResponse {
7 | //todo 这里可以添加想要返回的字段,这里返回一个
8 | }
9 |
--------------------------------------------------------------------------------
/.idea/smartfox_info.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/main/java/com/scut/seckill/common/Head.java:
--------------------------------------------------------------------------------
1 | package com.scut.seckill.common;
2 |
3 | import lombok.Data;
4 |
5 | /**
6 | * @author twc
7 | */
8 | @Data
9 | public class Head {
10 |
11 | /**
12 | * 状态码
13 | */
14 | private String statusCode;
15 |
16 | /**
17 | * 状态信息
18 | */
19 | private String statusMessage;
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/com/scut/seckill/web/req/SecKillRequest.java:
--------------------------------------------------------------------------------
1 | package com.scut.seckill.web.req;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 |
7 | @Data
8 | @NoArgsConstructor
9 | @AllArgsConstructor
10 | public class SecKillRequest {
11 |
12 | private Integer userId;
13 |
14 | private Integer productId;
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/com/scut/seckill/exception/SecKillException.java:
--------------------------------------------------------------------------------
1 | package com.scut.seckill.exception;
2 |
3 | import com.scut.seckill.common.SecKillEnum;
4 | import lombok.Data;
5 |
6 | @Data
7 | public class SecKillException extends RuntimeException {
8 |
9 | private SecKillEnum secKillEnum;
10 |
11 | public SecKillException(SecKillEnum secKillEnum){
12 | this.secKillEnum = secKillEnum;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/scut/seckill/SecKillApp.java:
--------------------------------------------------------------------------------
1 | package com.scut.seckill;
2 |
3 | import org.mybatis.spring.annotation.MapperScan;
4 | import org.springframework.boot.SpringApplication;
5 | import org.springframework.boot.autoconfigure.SpringBootApplication;
6 |
7 | @SpringBootApplication
8 | @MapperScan("com.scut.seckill.mapper")
9 | public class SecKillApp {
10 | public static void main(String[] args) {
11 | SpringApplication.run(SecKillApp.class,args);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/main/java/com/scut/seckill/cache/RedisCacheHandle.java:
--------------------------------------------------------------------------------
1 | package com.scut.seckill.cache;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.stereotype.Component;
5 | import redis.clients.jedis.Jedis;
6 | import redis.clients.jedis.JedisPool;
7 |
8 | @Component
9 | public class RedisCacheHandle {
10 |
11 | @Autowired
12 | private JedisPool jedisPool;
13 |
14 | public Jedis getJedis(){
15 | return jedisPool.getResource();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/resources/jmeter/operation.txt:
--------------------------------------------------------------------------------
1 | {
2 | "head":{},
3 | "body":{
4 | "userId":${userId},
5 | "productId":${productId}
6 | }
7 | }
8 |
9 | 这是本人此项目的github地址:https://github.com/SkyScraperTwc/SecKillDesign,希望各位能点Star,也欢迎Pull Request!
10 | 项目提供了SQL文件和JMeter压测参数等文件,代码也都有详细的注释!
11 | 我的项目提供了三种解决方案来实现秒杀系统:
12 | 1.利用MySQL实现悲观锁。
13 | 2.利用MySQL实现乐观锁。
14 | 3.基于AtomicInteger的CAS机制。
15 | 4.使用Redis作为原子计数器(watch事务+decr操作),RabbitMQ作为消息队列记录用户抢购行为,MySQL做异步存储。
16 | 最后使用JMeter进行性能测试,分析其吞吐量、平均响应时间、错误率等参数,得出相应结论。
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/main/java/com/scut/seckill/constant/SecKillStateConst.java:
--------------------------------------------------------------------------------
1 | package com.scut.seckill.constant;
2 |
3 | public final class SecKillStateConst {
4 | /**
5 | * 秒杀成功
6 | */
7 | public final static String SUCCESS = "1";
8 | /**
9 | * 秒杀失败
10 | */
11 | public final static String FAIL = "0";
12 | /**
13 | * 重复秒杀
14 | */
15 | public final static String REPEAT = "-1";
16 | /**
17 | * 系统错误
18 | */
19 | public final static String SYSTEM_EXCEPTION = "-2";
20 | }
21 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__junit_junit_4_12.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/main/java/com/scut/seckill/constant/RedisCacheConst.java:
--------------------------------------------------------------------------------
1 | package com.scut.seckill.constant;
2 |
3 | public final class RedisCacheConst {
4 | /**
5 | * 用户已买集合
6 | */
7 | public final static String IPHONE_HAS_BOUGHT_SET = "iphone_has_bought_set";
8 |
9 | public final static String HUAWEI_HAS_BOUGHT_SET = "huawei_has_bought_set";
10 |
11 | public final static String SAMSUNG_HAS_BOUGHT_SET = "samsung_has_bought_set";
12 |
13 | public final static String XIAOMI_HAS_BOUGHT_SET = "xiaomi_has_bought_set";
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_ow2_asm_asm_5_0_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_json_json_20140107.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_alibaba_druid_1_0_18.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_yaml_snakeyaml_1_17.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__redis_clients_jedis_2_8_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_mybatis_mybatis_3_4_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_objenesis_objenesis_2_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_alibaba_fastjson_1_2_31.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_slf4j_slf4j_api_1_7_21.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_fasterxml_classmate_1_3_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__net_minidev_json_smart_2_2_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_projectlombok_lombok_1_16_6.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_rabbitmq_amqp_client_3_6_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_assertj_assertj_core_2_5_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_slf4j_jul_to_slf4j_1_7_21.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_skyscreamer_jsonassert_1_3_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__commons_codec_commons_codec_1_10.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__net_minidev_accessors_smart_1_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__ch_qos_logback_logback_core_1_1_7.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_jayway_jsonpath_json_path_2_2_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_mockito_mockito_core_1_10_19.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_mybatis_mybatis_spring_1_3_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_slf4j_jcl_over_slf4j_1_7_21.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_apache_tomcat_tomcat_jdbc_8_5_5.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_apache_tomcat_tomcat_juli_8_5_5.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_hamcrest_hamcrest_library_1_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_slf4j_log4j_over_slf4j_1_7_21.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__ch_qos_logback_logback_classic_1_1_7.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__mysql_mysql_connector_java_5_1_39.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_apache_httpcomponents_httpcore_4_4_5.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_apache_commons_commons_pool2_2_4_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_apache_httpcomponents_httpclient_4_5_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_rabbitmq_http_client_1_0_0_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_core_2_8_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_tx_4_3_3_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/main/java/com/scut/seckill/entity/User.java:
--------------------------------------------------------------------------------
1 | package com.scut.seckill.entity;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 |
7 | import java.math.BigDecimal;
8 | import java.util.Date;
9 |
10 | /**
11 | * @author twc
12 | */
13 | @Data
14 | @NoArgsConstructor
15 | @AllArgsConstructor
16 | public class User {
17 | /**
18 | * 主键
19 | */
20 | private Integer id;
21 | /**
22 | * 用户名
23 | */
24 | private String username;
25 | /**
26 | * 手机号码
27 | */
28 | private String phone;
29 | /**
30 | * 创建时间
31 | */
32 | private Date createTime;
33 |
34 | public User(Integer id) {
35 | this.id = id;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_apache_tomcat_embed_tomcat_embed_el_8_5_5.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_jboss_logging_jboss_logging_3_3_0_Final.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__javax_validation_validation_api_1_1_0_Final.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_aop_4_3_3_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_oxm_4_3_3_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_web_4_3_3_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_core_4_3_3_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_jdbc_4_3_3_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_test_4_3_3_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_apache_tomcat_embed_tomcat_embed_core_8_5_5.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_databind_2_8_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_beans_4_3_3_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_webmvc_4_3_3_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_hibernate_hibernate_validator_5_2_4_Final.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_amqp_spring_amqp_1_6_2_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_boot_spring_boot_1_4_1_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_context_4_3_3_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_annotations_2_8_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_amqp_spring_rabbit_1_6_2_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_retry_spring_retry_1_1_4_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_messaging_4_3_3_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_apache_tomcat_embed_tomcat_embed_websocket_8_5_5.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_expression_4_3_3_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_boot_spring_boot_test_1_4_1_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_data_spring_data_redis_1_7_3_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/main/java/com/scut/seckill/entity/Product.java:
--------------------------------------------------------------------------------
1 | package com.scut.seckill.entity;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 |
7 | import java.math.BigDecimal;
8 | import java.util.Date;
9 |
10 | @Data
11 | @NoArgsConstructor
12 | @AllArgsConstructor
13 | public class Product {
14 | /**
15 | * id
16 | */
17 | private Integer id;
18 | /**
19 | * 产品名称
20 | */
21 | private String productName;
22 | /**
23 | * 价格
24 | */
25 | private BigDecimal price;
26 | /**
27 | * 库存
28 | */
29 | private int stock;
30 | /**
31 | * 版本号
32 | */
33 | private int version;
34 | /**
35 | * 创建时间
36 | */
37 | private Date createTime;
38 |
39 | public Product(Integer id){
40 | this.id = id;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/com/scut/seckill/mapper/SecKillMapper.java:
--------------------------------------------------------------------------------
1 | package com.scut.seckill.mapper;
2 |
3 | import com.scut.seckill.entity.Product;
4 | import com.scut.seckill.entity.Record;
5 | import com.scut.seckill.entity.User;
6 | import org.springframework.stereotype.Repository;
7 |
8 | import java.util.List;
9 |
10 | @Repository
11 | public interface SecKillMapper{
12 |
13 | List getAllUser();
14 |
15 | User getUserById(Integer id);
16 |
17 | List getAllProduct();
18 |
19 | Product getProductById(Integer id);
20 |
21 | boolean updatePessLockInMySQL(Product product);
22 |
23 | boolean updatePosiLockInMySQL(Product product);
24 |
25 | boolean insertRecord(Record record);
26 |
27 | boolean updateByAsynPattern(Product product);
28 | }
29 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_mybatis_spring_boot_mybatis_spring_boot_starter_1_1_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_1_4_1_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_context_support_4_3_3_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/main/java/com/scut/seckill/common/GlobalExceptionHandler.java:
--------------------------------------------------------------------------------
1 | package com.scut.seckill.common;
2 |
3 | import com.scut.seckill.exception.SecKillException;
4 | import lombok.extern.slf4j.Slf4j;
5 | import org.springframework.web.bind.annotation.ControllerAdvice;
6 | import org.springframework.web.bind.annotation.ExceptionHandler;
7 | import org.springframework.web.bind.annotation.ResponseBody;
8 |
9 | @ControllerAdvice
10 | @Slf4j
11 | public class GlobalExceptionHandler {
12 |
13 | @ExceptionHandler(value = SecKillException.class)
14 | @ResponseBody
15 | public Message handleSecKillException(SecKillException secKillException){
16 | log.info(secKillException.getSecKillEnum().getMessage());
17 | return new Message(secKillException.getSecKillEnum());
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/scut/seckill/entity/Record.java:
--------------------------------------------------------------------------------
1 | package com.scut.seckill.entity;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 |
7 | import java.util.Date;
8 |
9 | /**
10 | * 购买明细记录
11 | */
12 | @Data
13 | @NoArgsConstructor
14 | @AllArgsConstructor
15 | public class Record {
16 | /**
17 | * id
18 | */
19 | private Integer id;
20 | /**
21 | * 用户
22 | */
23 | private User user;
24 | /**
25 | * 产品
26 | */
27 | private Product product;
28 | /**
29 | * 1秒杀成功,0秒杀失败,-1重复秒杀,-2系统异常
30 | */
31 | private String state;
32 | /**
33 | * 状态的明文标识
34 | */
35 | private String stateInfo;
36 | /**
37 | * 创建时间
38 | */
39 | private Date createTime;
40 | }
41 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_data_spring_data_commons_1_12_3_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_data_spring_data_keyvalue_1_1_3_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_web_1_4_1_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_amqp_1_4_1_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_jdbc_1_4_1_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_test_1_4_1_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_mybatis_spring_boot_mybatis_spring_boot_autoconfigure_1_1_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/main/java/com/scut/seckill/common/Message.java:
--------------------------------------------------------------------------------
1 | package com.scut.seckill.common;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 |
7 | @Data
8 | @NoArgsConstructor
9 | @AllArgsConstructor
10 | public class Message {
11 |
12 | private Head head;
13 |
14 | private T body;
15 |
16 | public Message(SecKillEnum resultEnum, T body){
17 | this.head = new Head();
18 | this.head.setStatusCode(resultEnum.getCode());
19 | this.head.setStatusMessage(resultEnum.getMessage());
20 | this.body = body;
21 | }
22 |
23 | public Message(SecKillEnum resultEnum){
24 | this.head = new Head();
25 | this.head.setStatusCode(resultEnum.getCode());
26 | this.head.setStatusMessage(resultEnum.getMessage());
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_boot_spring_boot_autoconfigure_1_4_1_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_redis_1_4_1_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_tomcat_1_4_1_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_logging_1_4_1_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_boot_spring_boot_test_autoconfigure_1_4_1_RELEASE.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/main/java/com/scut/seckill/common/SecKillEnum.java:
--------------------------------------------------------------------------------
1 | package com.scut.seckill.common;
2 |
3 |
4 | import com.scut.seckill.constant.SecKillStateConst;
5 |
6 | /**
7 | * @author twc
8 | */
9 |
10 | public enum SecKillEnum {
11 | /**
12 | * 服务级错误
13 | */
14 | SUCCESS(SecKillStateConst.SUCCESS,"秒杀成功"),
15 | LOW_STOCKS(SecKillStateConst.FAIL, "库存不足"),
16 | FAIL(SecKillStateConst.FAIL, "秒杀失败"),
17 | REPEAT(SecKillStateConst.REPEAT, "重复秒杀"),
18 | SYSTEM_EXCEPTION(SecKillStateConst.SYSTEM_EXCEPTION, "系统错误"),
19 | ;
20 |
21 | private String code;
22 |
23 | private String message;
24 |
25 | SecKillEnum(String code, String message){
26 | this.code = code;
27 | this.message = message;
28 | }
29 |
30 | public String getCode() {
31 | return code;
32 | }
33 |
34 | public String getMessage() {
35 | return message;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/com/scut/seckill/mq/RabbitMQReceiver.java:
--------------------------------------------------------------------------------
1 | package com.scut.seckill.mq;
2 |
3 | import com.alibaba.fastjson.JSON;
4 | import com.alibaba.fastjson.TypeReference;
5 | import com.scut.seckill.entity.Record;
6 | import com.scut.seckill.mapper.SecKillMapper;
7 | import org.springframework.amqp.rabbit.annotation.RabbitHandler;
8 | import org.springframework.amqp.rabbit.annotation.RabbitListener;
9 | import org.springframework.beans.factory.annotation.Autowired;
10 | import org.springframework.stereotype.Component;
11 |
12 | @Component
13 | @RabbitListener(queues = "seckillQueue")
14 | public class RabbitMQReceiver {
15 |
16 | @Autowired
17 | private SecKillMapper secKillMapper;
18 |
19 | @RabbitHandler
20 | public void process(String message) throws Exception {
21 | Record record = JSON.parseObject(message, new TypeReference(){});
22 | //插入record
23 | secKillMapper.insertRecord(record);
24 | //更改物品库存
25 | secKillMapper.updateByAsynPattern(record.getProduct());
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/scut/seckill/utils/SecKillUtils.java:
--------------------------------------------------------------------------------
1 | package com.scut.seckill.utils;
2 |
3 | import com.scut.seckill.constant.RedisCacheConst;
4 |
5 | public class SecKillUtils {
6 |
7 | /**
8 | * 获取用户已买队列key
9 | * @param productName
10 | * @return
11 | */
12 | public static String getRedisHasBoughtSetKey(String productName){
13 | String hasBySet = "";
14 | if (productName!=null && !productName.isEmpty()){
15 | switch (productName){
16 | case "iphone":
17 | hasBySet = RedisCacheConst.IPHONE_HAS_BOUGHT_SET;
18 | break;
19 | case "huawei":
20 | hasBySet = RedisCacheConst.HUAWEI_HAS_BOUGHT_SET;
21 | break;
22 | case "samsung":
23 | hasBySet = RedisCacheConst.SAMSUNG_HAS_BOUGHT_SET;
24 | break;
25 | case "xiaomi":
26 | hasBySet = RedisCacheConst.XIAOMI_HAS_BOUGHT_SET;
27 | break;
28 | }
29 | }
30 | return hasBySet;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/java/com/scut/seckill/cache/RedisLoaderListener.java:
--------------------------------------------------------------------------------
1 | package com.scut.seckill.cache;
2 |
3 | import com.scut.seckill.entity.Product;
4 | import com.scut.seckill.mapper.SecKillMapper;
5 | import com.scut.seckill.concurrent.AtomicStock;
6 | import lombok.extern.slf4j.Slf4j;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.stereotype.Component;
9 | import redis.clients.jedis.Jedis;
10 |
11 | import javax.annotation.PostConstruct;
12 | import java.util.List;
13 |
14 | @Slf4j
15 | @Component
16 | public class RedisLoaderListener {
17 |
18 | @Autowired
19 | private RedisCacheHandle redisCacheHandle;
20 |
21 | @Autowired
22 | private SecKillMapper secKillMapper;
23 |
24 | @Autowired
25 | private AtomicStock atomicStock;
26 |
27 | @PostConstruct
28 | public void initRedis(){
29 | Jedis jedis = redisCacheHandle.getJedis();
30 | //清空Redis缓存
31 | jedis.flushDB();
32 | List productList = secKillMapper.getAllProduct();
33 | for (Product product:productList) {
34 | jedis.set(product.getProductName()+"_stock", String.valueOf(product.getStock()));
35 | }
36 | log.info("Redis缓存数据初始化完毕!");
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/resources/sql/seckill.sql:
--------------------------------------------------------------------------------
1 | use seckill;
2 |
3 | DROP TABLE IF EXISTS user;
4 | CREATE TABLE user(
5 | id INT NOT NULL AUTO_INCREMENT PRIMARY KEY comment "ID",
6 | username VARCHAR (20) UNIQUE NOT NULL comment "用户名",
7 | phone VARCHAR (20) NOT NULL comment "手机号码",
8 | createTime DATE NOT NULL comment "创建时间"
9 | );
10 |
11 | DROP TABLE IF EXISTS product;
12 | CREATE TABLE product(
13 | id INT NOT NULL AUTO_INCREMENT PRIMARY KEY comment "ID",
14 | productName VARCHAR (20) UNIQUE NOT NULL comment "产品名称",
15 | price DECIMAL(16,3) NOT NULL comment "价格",
16 | stock INT NOT NULL comment "库存",
17 | createTime DATE NOT NULL comment "创建时间"
18 | );
19 |
20 | DROP TABLE IF EXISTS record;
21 | CREATE TABLE record(
22 | id INT NOT NULL AUTO_INCREMENT PRIMARY KEY comment "ID",
23 | userId INT NOT NULL comment "用户ID",
24 | productId INT NOT NULL comment "产品ID",
25 | state VARCHAR (6) NOT NULL comment "秒杀状态1秒杀成功,0秒杀失败,-1重复秒杀,-2系统异常",
26 | stateInfo VARCHAR (6) NOT NULL comment "状态的明文标识",
27 | createTime DATE NOT NULL comment "创建时间"
28 | );
29 |
30 | -- use seckill;
31 | -- update product set stock=100 where id>=1;
32 | -- delete from record where id>=0
33 |
34 | -- update product set stock=100 and version=0 where id>=1 ;
--------------------------------------------------------------------------------
/src/main/java/com/scut/seckill/mq/RabbitMQSender.java:
--------------------------------------------------------------------------------
1 | package com.scut.seckill.mq;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import org.springframework.amqp.rabbit.core.RabbitTemplate;
5 | import org.springframework.amqp.rabbit.support.CorrelationData;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.stereotype.Component;
8 |
9 | import java.util.UUID;
10 |
11 | /**
12 | * 可靠确认模式
13 | */
14 | @Slf4j
15 | @Component
16 | public class RabbitMQSender implements RabbitTemplate.ConfirmCallback{
17 |
18 | @Autowired
19 | private RabbitTemplate rabbitTemplate;
20 |
21 | public void send(String message) {
22 | rabbitTemplate.setConfirmCallback(this);
23 | CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
24 | rabbitTemplate.convertAndSend("seckillExchange", "seckillRoutingKey", message, correlationData);
25 | }
26 |
27 | @Override
28 | public void confirm(CorrelationData correlationData, boolean ack, String cause) {
29 | log.info("callbakck confirm: " + correlationData.getId());
30 | if (ack){
31 | log.info("插入record成功,更改库存成功");
32 | }else{
33 | log.info("cause:"+cause);
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/resources/dao/SecKillMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 | update product set stock=stock-1
10 | where id=#{id} and stock>0
11 |
12 |
13 |
14 | update product set stock=#{stock},version=version+1
15 | where id=#{id} AND version=#{version}
16 |
17 |
18 |
19 | update product set stock=stock-1 where id=#{id}
20 |
21 |
22 |
25 |
26 |
29 |
30 |
33 |
34 |
37 |
38 |
39 | insert into record(userId, productId, state, stateInfo, createTime)
40 | values(#{user.id}, #{product.id}, #{state}, #{stateInfo}, #{createTime})
41 |
42 |
43 |
--------------------------------------------------------------------------------
/src/main/java/com/scut/seckill/concurrent/AtomicStock.java:
--------------------------------------------------------------------------------
1 | package com.scut.seckill.concurrent;
2 |
3 | import com.scut.seckill.entity.Product;
4 | import com.scut.seckill.mapper.SecKillMapper;
5 | import lombok.Data;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.stereotype.Component;
8 |
9 | import javax.annotation.PostConstruct;
10 | import java.util.List;
11 | import java.util.concurrent.atomic.AtomicInteger;
12 |
13 | @Data
14 | @Component
15 | public class AtomicStock {
16 |
17 | private AtomicInteger samsungInteger = new AtomicInteger();
18 |
19 | private AtomicInteger huaweiInteger = new AtomicInteger();
20 |
21 | private AtomicInteger xiaomiInteger = new AtomicInteger();
22 |
23 | private AtomicInteger iphoneInteger = new AtomicInteger();
24 |
25 | @Autowired
26 | private SecKillMapper secKillMapper;
27 |
28 | @PostConstruct
29 | public void initAtomicInteger() {
30 | List productList = secKillMapper.getAllProduct();
31 | for (Product product : productList) {
32 | getAtomicInteger(product.getProductName()).set(product.getStock());
33 |
34 | }
35 | }
36 |
37 | public AtomicInteger getAtomicInteger(String productName) {
38 | AtomicInteger ai = null;
39 | if (productName != null && !productName.isEmpty()){
40 | switch (productName){
41 | case "iphone":
42 | ai = iphoneInteger;
43 | break;
44 | case "huawei":
45 | ai = huaweiInteger;
46 | break;
47 | case "samsung":
48 | ai = samsungInteger;
49 | break;
50 | case "xiaomi":
51 | ai = xiaomiInteger;
52 | break;
53 | }
54 | }
55 | return ai;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/main/resources/jmeter/param-repeat.txt:
--------------------------------------------------------------------------------
1 | 1,1
2 | 1,1
3 | 1,1
4 | 1,1
5 | 1,1
6 | 1,1
7 | 1,1
8 | 1,1
9 | 1,1
10 | 1,1
11 | 1,1
12 | 1,1
13 | 1,1
14 | 1,1
15 | 1,1
16 | 1,1
17 | 1,1
18 | 1,1
19 | 1,1
20 | 1,1
21 | 1,1
22 | 1,1
23 | 1,1
24 | 1,1
25 | 1,1
26 | 1,1
27 | 1,1
28 | 1,1
29 | 1,1
30 | 1,1
31 | 1,1
32 | 1,1
33 | 1,1
34 | 1,1
35 | 1,1
36 | 1,1
37 | 1,1
38 | 1,1
39 | 1,1
40 | 1,1
41 | 1,1
42 | 1,1
43 | 1,1
44 | 1,1
45 | 1,1
46 | 1,1
47 | 1,1
48 | 1,1
49 | 1,1
50 | 1,1
51 | 1,1
52 | 1,1
53 | 1,1
54 | 1,1
55 | 1,1
56 | 1,1
57 | 1,1
58 | 1,1
59 | 1,1
60 | 1,1
61 | 1,1
62 | 1,1
63 | 1,1
64 | 1,1
65 | 1,1
66 | 1,1
67 | 1,1
68 | 1,1
69 | 1,1
70 | 1,1
71 | 1,1
72 | 1,1
73 | 1,1
74 | 1,1
75 | 1,1
76 | 1,1
77 | 1,1
78 | 1,1
79 | 1,1
80 | 1,1
81 | 1,1
82 | 1,1
83 | 1,1
84 | 1,1
85 | 1,1
86 | 1,1
87 | 1,1
88 | 1,1
89 | 1,1
90 | 1,1
91 | 1,1
92 | 1,1
93 | 1,1
94 | 1,1
95 | 1,1
96 | 1,1
97 | 1,1
98 | 1,1
99 | 1,1
100 | 1,1
101 | 1,1
102 | 1,1
103 | 1,1
104 | 1,1
105 | 1,1
106 | 1,1
107 | 1,1
108 | 1,1
109 | 1,1
110 | 1,1
111 | 1,1
112 | 1,1
113 | 1,1
114 | 1,1
115 | 1,1
116 | 1,1
117 | 1,1
118 | 1,1
119 | 1,1
120 | 1,1
121 | 1,1
122 | 1,1
123 | 1,1
124 | 1,1
125 | 1,1
126 | 1,1
127 | 1,1
128 | 1,1
129 | 1,1
130 | 1,1
131 | 1,1
132 | 1,1
133 | 1,1
134 | 1,1
135 | 1,1
136 | 1,1
137 | 1,1
138 | 1,1
139 | 1,1
140 | 1,1
141 | 1,1
142 | 1,1
143 | 1,1
144 | 1,1
145 | 1,1
146 | 1,1
147 | 1,1
148 | 1,1
149 | 1,1
150 | 1,1
151 | 1,1
152 | 1,1
153 | 1,1
154 | 1,1
155 | 1,1
156 | 1,1
157 | 1,1
158 | 1,1
159 | 1,1
160 | 1,1
161 | 1,1
162 | 1,1
163 | 1,1
164 | 1,1
165 | 1,1
166 | 1,1
167 | 1,1
168 | 1,1
169 | 1,1
170 | 1,1
171 | 1,1
172 | 1,1
173 | 1,1
174 | 1,1
175 | 1,1
176 | 1,1
177 | 1,1
178 | 1,1
179 | 1,1
180 | 1,1
181 | 1,1
182 | 1,1
183 | 1,1
184 | 1,1
185 | 1,1
186 | 1,1
187 | 1,1
188 | 1,1
189 | 1,1
190 | 1,1
191 | 1,1
192 | 1,1
193 | 1,1
194 | 1,1
195 | 1,1
196 | 1,1
197 | 1,1
198 | 1,1
199 | 1,1
200 | 1,1
--------------------------------------------------------------------------------
/src/main/java/com/scut/seckill/config/RedisCacheConfig.java:
--------------------------------------------------------------------------------
1 | package com.scut.seckill.config;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import org.springframework.beans.factory.annotation.Qualifier;
5 | import org.springframework.beans.factory.annotation.Value;
6 | import org.springframework.context.annotation.Bean;
7 | import org.springframework.context.annotation.Configuration;
8 | import redis.clients.jedis.JedisPool;
9 | import redis.clients.jedis.JedisPoolConfig;
10 |
11 | /**
12 | * @author twc
13 | */
14 | @Configuration
15 | @Slf4j
16 | public class RedisCacheConfig {
17 |
18 | @Value("${spring.redis.host}")
19 | private String host;
20 |
21 | @Value("${spring.redis.port}")
22 | private int port;
23 |
24 | @Value("${spring.redis.pool.max-idle}")
25 | private int maxIdle;
26 |
27 | @Value("${spring.redis.pool.min-idle}")
28 | private int minIdle;
29 |
30 | @Value("${spring.redis.pool.max-wait}")
31 | private long maxWaitMillis;
32 |
33 | @Value("${spring.redis.pool.max-active}")
34 | private int maxActive;
35 |
36 | @Value("${spring.redis.timeout}")
37 | private int timeout;
38 |
39 | @Value("${spring.redis.database}")
40 | private int database;
41 |
42 | @Bean(name = "poolConfig")
43 | public JedisPoolConfig initJedisPoolConfig(){
44 | log.info("JedisPoolConfig注入开始:");
45 | JedisPoolConfig poolConfig = new JedisPoolConfig();
46 | poolConfig.setMaxTotal(maxActive);
47 | poolConfig.setMaxIdle(maxIdle);
48 | poolConfig.setMaxWaitMillis(maxWaitMillis);
49 | poolConfig.setMinIdle(minIdle);
50 | poolConfig.setTestOnBorrow(true);
51 | poolConfig.setTestOnReturn(true);
52 | poolConfig.setBlockWhenExhausted(true);
53 | return poolConfig;
54 | }
55 |
56 | @Bean
57 | public JedisPool initJedisPool(@Qualifier("poolConfig") JedisPoolConfig poolConfig){
58 | log.info("JedisPool注入开始:");
59 | JedisPool jedisPool = new JedisPool(poolConfig,host,port,timeout);
60 | return jedisPool;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | #上下文配置
2 | server.port=8080
3 | server.context-path=/SecKillDesign
4 |
5 | # 数据库访问配置
6 | # 主数据源,默认的
7 | spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
8 | spring.datasource.url=jdbc:mysql://localhost:3306/seckill?useUnicode=true&characterEncoding=utf8&useSSL=false
9 | spring.datasource.username=root
10 | spring.datasource.password=123456
11 | spring.datasource.driver-class-name=com.mysql.jdbc.Driver
12 |
13 | # 下面为连接池的补充设置,应用到上面所有数据源中
14 | # 初始化大小,最小,最大
15 | spring.datasource.initialSize=5
16 | #最小空闲数
17 | spring.datasource.minIdle=5
18 | #最大连接数
19 | spring.datasource.maxActive=40000
20 | # 配置获取连接等待超时的时间
21 | spring.datasource.maxWait=60000
22 | # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
23 | spring.datasource.timeBetweenEvictionRunsMillis=2000
24 | # 配置一个连接在池中最小生存的时间,单位是毫秒
25 | spring.datasource.minEvictableIdleTimeMillis=300000
26 | spring.datasource.validationQuery=SELECT 1 FROM DUAL
27 | spring.datasource.testWhileIdle=true
28 | spring.datasource.testOnBorrow=true
29 | spring.datasource.testOnReturn=true
30 | # 打开PSCache,并且指定每个连接上PSCache的大小
31 | spring.datasource.poolPreparedStatements=true
32 | spring.datasource.maxPoolPreparedStatementPerConnectionSize=20
33 | # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
34 | spring.datasource.filters=stat,wall,log4j
35 | # 通过connectProperties属性来打开mergeSql功能;慢SQL记录
36 | spring.datasource.connectionProperties=druid.stat.mergeSql=true;
37 | # 合并多个DruidDataSource的监控数据
38 | #spring.datasource.useGlobalDataSourceStat=true
39 |
40 | # REDIS (RedisProperties)
41 | # Redis数据库索引(默认为0)
42 | spring.redis.database=0
43 | # Redis服务器地址
44 | spring.redis.host=127.0.0.1
45 | # Redis服务器连接端口
46 | spring.redis.port=6379
47 | # Redis服务器连接密码(默认为空)
48 | #spring.redis.password=redis
49 | # 连接池最大连接数(使用负值表示没有限制)
50 | spring.redis.pool.max-active=3000
51 | # 连接池最大阻塞等待时间(使用负值表示没有限制)
52 | spring.redis.pool.max-wait=-1
53 | # 连接池中的最大空闲连接
54 | spring.redis.pool.max-idle=8
55 | # 连接池中的最小空闲连接
56 | spring.redis.pool.min-idle=0
57 | # 连接超时时间(毫秒)
58 | spring.redis.timeout=0
59 |
60 | #rabbitmq上下文配置
61 | spring.rabbitmq.host=127.0.0.1
62 | spring.rabbitmq.port=5672
63 | spring.rabbitmq.username=guest
64 | spring.rabbitmq.password=guest
65 | spring.rabbitmq.publisher-confirms=true
66 | spring.rabbitmq.virtual-host=/
67 |
68 | rabbitmq.config.exchangeName=seckillExchange
69 | rabbitmq.config.queueName=seckillQueue
70 | rabbitmq.config.routingKey=seckillRoutingKey
71 |
72 | #为entity包下的类起别名
73 | mybatis.type-aliases-package=com.scut.seckill.entity
74 | #mapper扫描位置
75 | mybatis.mapper-locations = classpath:dao/*.xml
76 |
--------------------------------------------------------------------------------
/src/main/java/com/scut/seckill/config/RabbitmqCallBackConfig.java:
--------------------------------------------------------------------------------
1 | package com.scut.seckill.config;
2 |
3 | import org.springframework.amqp.core.*;
4 | import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
5 | import org.springframework.amqp.rabbit.connection.ConnectionFactory;
6 | import org.springframework.amqp.rabbit.core.RabbitTemplate;
7 | import org.springframework.beans.factory.annotation.Qualifier;
8 | import org.springframework.beans.factory.annotation.Value;
9 | import org.springframework.beans.factory.config.ConfigurableBeanFactory;
10 | import org.springframework.context.annotation.Bean;
11 | import org.springframework.context.annotation.Configuration;
12 | import org.springframework.context.annotation.Primary;
13 | import org.springframework.context.annotation.Scope;
14 |
15 | @Configuration
16 | public class RabbitmqCallBackConfig {
17 |
18 | @Value("${spring.rabbitmq.host}")
19 | private String address;
20 |
21 | @Value("${spring.rabbitmq.port}")
22 | private String port;
23 |
24 | @Value("${spring.rabbitmq.username}")
25 | private String username;
26 |
27 | @Value("${spring.rabbitmq.password}")
28 | private String password;
29 |
30 | @Value("${spring.rabbitmq.virtual-host}")
31 | private String virtualHost;
32 |
33 | @Value("${spring.rabbitmq.publisher-confirms}")
34 | private boolean publisherConfirms;
35 |
36 | @Value("${rabbitmq.config.exchangeName}")
37 | private String exchangeName;
38 |
39 | @Value("${rabbitmq.config.queueName}")
40 | private String queueName;
41 |
42 | @Value("${rabbitmq.config.routingKey}")
43 | private String routingKey;
44 |
45 | @Bean
46 | public ConnectionFactory initConnectionFactory(){
47 | CachingConnectionFactory factory = new CachingConnectionFactory();
48 | factory.setAddresses(address+":"+port);
49 | factory.setUsername(username);
50 | factory.setPassword(password);
51 | factory.setVirtualHost(virtualHost);
52 | factory.setPublisherConfirms(publisherConfirms);
53 | return factory;
54 | }
55 |
56 | //必须是prototype类型
57 | @Bean
58 | @Primary
59 | @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
60 | public RabbitTemplate initRabbitTemplate(@Qualifier("initConnectionFactory") ConnectionFactory connectionFactory){
61 | return new RabbitTemplate(connectionFactory);
62 | }
63 |
64 | /**
65 | * 针对消费者配置
66 | * 1. 设置交换机类型
67 | * 2. 将队列绑定到交换机
68 | FanoutExchange: 将消息分发到所有的绑定队列,无routingkey的概念
69 | HeadersExchange :通过添加属性key-value匹配
70 | DirectExchange:按照routingkey分发到指定队列
71 | TopicExchange:多关键字匹配
72 | */
73 | @Bean
74 | public DirectExchange defaultExchange() {
75 | return new DirectExchange(exchangeName);
76 | }
77 | @Bean
78 | public Queue queue() {
79 | return new Queue(queueName);
80 | }
81 | @Bean
82 | public Binding binding() {
83 | return BindingBuilder.bind(queue()).to(defaultExchange()).with(routingKey);
84 | }
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | groupId
8 | SecKillDesign
9 | 1.0-SNAPSHOT
10 |
11 |
12 | org.springframework.boot
13 | spring-boot-starter-parent
14 | 1.4.1.RELEASE
15 |
16 |
17 |
18 |
19 | com.alibaba
20 | fastjson
21 | 1.2.31
22 |
23 |
24 |
25 | org.springframework.boot
26 | spring-boot-starter-redis
27 |
28 |
29 |
30 | org.springframework.boot
31 | spring-boot-starter-web
32 |
33 |
34 |
35 | org.springframework.boot
36 | spring-boot-starter-test
37 |
38 |
39 |
40 | org.springframework.boot
41 | spring-boot-starter-amqp
42 |
43 |
44 |
45 | junit
46 | junit
47 | 4.12
48 |
49 |
50 |
51 | org.projectlombok
52 | lombok
53 | 1.16.6
54 |
55 |
56 |
57 | org.slf4j
58 | slf4j-api
59 | 1.7.21
60 |
61 |
62 |
63 | com.alibaba
64 | druid
65 | 1.0.18
66 |
67 |
68 |
69 | mysql
70 | mysql-connector-java
71 | 5.1.39
72 |
73 |
74 |
75 | org.mybatis.spring.boot
76 | mybatis-spring-boot-starter
77 | 1.1.1
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 | src/main/java
86 |
87 | **/*.properties
88 | **/*.xml
89 |
90 | false
91 |
92 |
93 |
94 |
95 | org.apache.maven.plugins
96 | maven-compiler-plugin
97 |
98 | 1.7
99 | 1.7
100 |
101 |
102 |
103 |
104 |
105 |
--------------------------------------------------------------------------------
/src/main/java/com/scut/seckill/controller/SecKillController.java:
--------------------------------------------------------------------------------
1 | package com.scut.seckill.controller;
2 |
3 | import com.scut.seckill.cache.RedisCacheHandle;
4 | import com.scut.seckill.common.Message;
5 | import com.scut.seckill.common.SecKillEnum;
6 | import com.scut.seckill.service.SecKillService;
7 | import com.scut.seckill.web.req.SecKillRequest;
8 | import com.scut.seckill.web.vo.SecKillResponse;
9 | import org.junit.Test;
10 | import org.springframework.beans.factory.annotation.Autowired;
11 | import org.springframework.web.bind.annotation.*;
12 | import redis.clients.jedis.Jedis;
13 |
14 | import java.util.HashMap;
15 | import java.util.HashSet;
16 | import java.util.Map;
17 | import java.util.Set;
18 |
19 | @RequestMapping("/seckill")
20 | @RestController
21 | public class SecKillController {
22 |
23 | @Autowired
24 | private SecKillService secKillService;
25 |
26 | /**
27 | * MySQL悲观锁
28 | * @param requestMessage
29 | * @return
30 | */
31 | @RequestMapping(value = "/pessLockInMySQL",method = RequestMethod.POST)
32 | public Message pessLockInMySQL(@RequestBody Message requestMessage){
33 | Map paramMap = new HashMap<>();
34 | paramMap.put("userId",requestMessage.getBody().getUserId());
35 | paramMap.put("productId",requestMessage.getBody().getProductId());
36 | SecKillEnum secKillEnum = secKillService.handleByPessLockInMySQL(paramMap);
37 | Message responseMessage = new Message<>(secKillEnum,null);
38 | return responseMessage;
39 | }
40 |
41 | /**
42 | * MySQL乐观锁
43 | * @param requestMessage
44 | * @return
45 | */
46 | @RequestMapping(value = "/posiLockInMySQL",method = RequestMethod.POST)
47 | public Message posiLockInMySQL(@RequestBody Message requestMessage){
48 | Map paramMap = new HashMap<>();
49 | paramMap.put("userId",requestMessage.getBody().getUserId());
50 | paramMap.put("productId",requestMessage.getBody().getProductId());
51 | SecKillEnum secKillEnum = secKillService.handleByPosiLockInMySQL(paramMap);
52 | Message responseMessage = new Message<>(secKillEnum,null);
53 | return responseMessage;
54 | }
55 |
56 | /**
57 | * 利用redis的watch监控的特性
58 | * @throws InterruptedException
59 | */
60 | @RequestMapping(value = "/baseOnRedisWatch",method = RequestMethod.POST)
61 | public Message baseOnRedisWatch(@RequestBody Message requestMessage) throws InterruptedException {
62 | Map paramMap = new HashMap<>();
63 | paramMap.put("userId",requestMessage.getBody().getUserId());
64 | paramMap.put("productId",requestMessage.getBody().getProductId());
65 | SecKillEnum secKillEnum = secKillService.handleByRedisWatch(paramMap);
66 | Message responseMessage = new Message<>(secKillEnum,null);
67 | return responseMessage;
68 | }
69 |
70 | /**
71 | * 利用AtomicInteger的CAS机制特性
72 | * @param requestMessage
73 | * @return
74 | */
75 | @RequestMapping(value = "/baseOnAtomicInteger",method = RequestMethod.POST)
76 | public Message baseOnAtomicInteger(@RequestBody Message requestMessage){
77 | Map paramMap = new HashMap<>();
78 | paramMap.put("userId",requestMessage.getBody().getUserId());
79 | paramMap.put("productId",requestMessage.getBody().getProductId());
80 | SecKillEnum secKillEnum = secKillService.handleByAtomicInteger(paramMap);
81 | Message responseMessage = new Message<>(secKillEnum,null);
82 | return responseMessage;
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/src/main/java/com/scut/seckill/config/MyBatisConfig.java:
--------------------------------------------------------------------------------
1 | package com.scut.seckill.config;
2 |
3 | import com.alibaba.druid.pool.DruidDataSource;
4 | import lombok.extern.slf4j.Slf4j;
5 | import org.mybatis.spring.SqlSessionFactoryBean;
6 | import org.springframework.beans.factory.annotation.Qualifier;
7 | import org.springframework.beans.factory.annotation.Value;
8 | import org.springframework.context.annotation.Bean;
9 | import org.springframework.context.annotation.Configuration;
10 | import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
11 | import org.springframework.core.io.support.ResourcePatternResolver;
12 |
13 | import java.io.IOException;
14 | import java.sql.SQLException;
15 |
16 | @Configuration
17 | @Slf4j
18 | public class MyBatisConfig {
19 |
20 | @Value("${spring.datasource.url}")
21 | private String dbUrl;
22 |
23 | @Value("${spring.datasource.username}")
24 | private String username;
25 |
26 | @Value("${spring.datasource.password}")
27 | private String password;
28 |
29 | @Value("${spring.datasource.driver-class-name}")
30 | private String driverClassName;
31 |
32 | @Value("${spring.datasource.initialSize}")
33 | private int initialSize;
34 |
35 | @Value("${spring.datasource.minIdle}")
36 | private int minIdle;
37 |
38 | @Value("${spring.datasource.maxActive}")
39 | private int maxActive;
40 |
41 | @Value("${spring.datasource.maxWait}")
42 | private int maxWait;
43 |
44 | @Value("${spring.datasource.timeBetweenEvictionRunsMillis}")
45 | private int timeBetweenEvictionRunsMillis;
46 |
47 | @Value("${spring.datasource.minEvictableIdleTimeMillis}")
48 | private int minEvictableIdleTimeMillis;
49 |
50 | @Value("${spring.datasource.validationQuery}")
51 | private String validationQuery;
52 |
53 | @Value("${spring.datasource.testWhileIdle}")
54 | private boolean testWhileIdle;
55 |
56 | @Value("${spring.datasource.testOnBorrow}")
57 | private boolean testOnBorrow;
58 |
59 | @Value("${spring.datasource.testOnReturn}")
60 | private boolean testOnReturn;
61 |
62 | @Value("${spring.datasource.poolPreparedStatements}")
63 | private boolean poolPreparedStatements;
64 |
65 | @Value("${spring.datasource.maxPoolPreparedStatementPerConnectionSize}")
66 | private int maxPoolPreparedStatementPerConnectionSize;
67 |
68 | @Value("${spring.datasource.filters}")
69 | private String filters;
70 |
71 | @Value("${spring.datasource.connectionProperties}")
72 | private String connectionProperties;
73 |
74 | /**
75 | * mybatis
76 | */
77 | @Value("${mybatis.type-aliases-package}")
78 | private String typeAliasesPackage;
79 |
80 | @Value("${mybatis.mapper-locations}")
81 | private String mapperLocations;
82 |
83 | @Bean(name = "druidDataSource")
84 | public DruidDataSource dataSource(){
85 | DruidDataSource dataSource = new DruidDataSource();
86 |
87 | dataSource.setUrl(dbUrl);
88 | dataSource.setUsername(username);
89 | dataSource.setPassword(password);
90 | dataSource.setDriverClassName(driverClassName);
91 |
92 | //configuration
93 | dataSource.setInitialSize(initialSize);
94 | dataSource.setMinIdle(minIdle);
95 | dataSource.setMaxActive(maxActive);
96 | dataSource.setMaxWait(maxWait);
97 | dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
98 | dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
99 | dataSource.setValidationQuery(validationQuery);
100 | dataSource.setTestWhileIdle(testWhileIdle);
101 | dataSource.setTestOnBorrow(testOnBorrow);
102 | dataSource.setTestOnReturn(testOnReturn);
103 | dataSource.setPoolPreparedStatements(poolPreparedStatements);
104 | dataSource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
105 | try {
106 | dataSource.setFilters(filters);
107 | } catch (SQLException e) {
108 | log.error("druid configuration initialization filter", e);
109 | }
110 | dataSource.setConnectionProperties(connectionProperties);
111 |
112 | return dataSource;
113 | }
114 |
115 | @Bean
116 | public SqlSessionFactoryBean initSqlSessionFactoryBean(@Qualifier("druidDataSource") DruidDataSource dataSource) throws IOException {
117 | SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
118 | sessionFactoryBean.setDataSource(dataSource);
119 | sessionFactoryBean.setTypeAliasesPackage(typeAliasesPackage);
120 | //添加XML目录
121 | ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
122 | sessionFactoryBean.setMapperLocations(resolver.getResources(mapperLocations));
123 | return sessionFactoryBean;
124 | }
125 |
126 | }
127 |
--------------------------------------------------------------------------------
/src/test/java/JUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.scut.seckill;
2 |
3 | import com.alibaba.fastjson.JSON;
4 | import com.scut.seckill.cache.RedisCacheHandle;
5 | import com.scut.seckill.common.SecKillEnum;
6 | import com.scut.seckill.constant.RedisCacheConst;
7 | import com.scut.seckill.entity.Record;
8 | import com.scut.seckill.entity.User;
9 | import com.scut.seckill.mapper.SecKillMapper;
10 | import com.scut.seckill.utils.SecKillUtils;
11 | import org.junit.Test;
12 | import org.junit.runner.RunWith;
13 | import org.springframework.beans.factory.annotation.Autowired;
14 | import org.springframework.boot.test.context.SpringBootTest;
15 | import org.springframework.test.context.junit4.SpringRunner;
16 | import org.springframework.web.bind.annotation.RequestMapping;
17 | import org.springframework.web.bind.annotation.RequestParam;
18 | import redis.clients.jedis.Jedis;
19 | import redis.clients.jedis.Response;
20 | import redis.clients.jedis.Transaction;
21 | import sun.rmi.runtime.Log;
22 |
23 | import java.io.BufferedWriter;
24 | import java.io.File;
25 | import java.io.FileWriter;
26 | import java.io.IOException;
27 | import java.util.*;
28 | import java.util.concurrent.atomic.AtomicInteger;
29 |
30 | @RunWith(SpringRunner.class)
31 | @SpringBootTest
32 | public class JUnitTest {
33 |
34 | @Autowired
35 | private SecKillMapper secKillMapper;
36 |
37 | @Autowired
38 | private RedisCacheHandle redisCacheHandle;
39 |
40 | private Set set = new TreeSet<>();
41 |
42 | @Test
43 | public void test2() throws InterruptedException {
44 | Jedis jedis = redisCacheHandle.getJedis();
45 | boolean isBuy = jedis.sismember(RedisCacheConst.IPHONE_HAS_BOUGHT_SET, "1");
46 | System.out.println(isBuy);
47 | }
48 |
49 | @Test
50 | public void test3() throws InterruptedException, IOException {
51 | String[] array = {"1","2","3","4","5","6"};
52 | File file =new File("/usr/twc/gitProject/SecKillDesign/src/main/resources/jmeter/789.txt");
53 | FileWriter fileWritter = new FileWriter(file);
54 | BufferedWriter bufferWritter = new BufferedWriter(fileWritter);
55 | Random random = new Random();
56 | for (int i = 8483; i <= 10000; i++) {
57 | StringBuffer buffer = new StringBuffer("");
58 | buffer.append(i+",");
59 | int max=6;
60 | int min=0;
61 | int s = random.nextInt(max)%(max-min+1) + min;
62 | buffer.append(array[s]);
63 | System.out.println(buffer.toString());
64 | // bufferWritter.write(buffer.toString());
65 | // bufferWritter.newLine();//换行
66 | }
67 | }
68 |
69 | @Test
70 | public void createUserSQL() throws IOException {
71 | List list = new ArrayList<>();
72 | File file =new File("/usr/twc/gitProject/SecKillDesign/src/main/resources/sql/insert.sql");
73 | FileWriter fileWritter = new FileWriter(file);
74 | BufferedWriter bufferWritter = new BufferedWriter(fileWritter);
75 | for (int i=1001;i<=10000;i++){
76 | StringBuffer buffer = new StringBuffer("INSERT INTO `user` VALUES ('0', ");
77 | buffer.append("'"+"tom_"+i+"'"+",");
78 | buffer.append("'13855558888'"+",");
79 | buffer.append("current_date());");
80 | list.add(buffer.toString());
81 | }
82 | for (String string :list) {
83 | //INSERT INTO `user` VALUES ('0', 'tom_850','13855558888',current_date());
84 | System.out.println(string);
85 | bufferWritter.write(string);
86 | bufferWritter.newLine();//换行
87 | }
88 | bufferWritter.close();
89 | }
90 |
91 | @Test
92 | public void test4() throws InterruptedException {
93 | Jedis jedis = redisCacheHandle.getJedis();
94 | Transaction tx = jedis.multi();
95 |
96 | Response isBuy = tx.sismember("set", "2");
97 | System.out.println("isBuy------"+isBuy);
98 |
99 | Response decrResult = tx.hincrBy("product_1","stock",-1);
100 | System.out.println("decrResult------"+decrResult);
101 |
102 | tx.sadd("set","1");
103 |
104 | List