日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

秒杀场景_同步秒杀分析和实战_01

發布時間:2024/9/27 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 秒杀场景_同步秒杀分析和实战_01 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

          • 一、應用部署準備
            • 1. mysql安裝部署
            • 2. redis安裝部署
            • 3. nacos安裝部署
          • 二、數據庫準備
            • 2.1. 創建數據庫
            • 2.2. 初始化表結構
            • 2.3. 搭建微服務父工程
          • 三、商品模塊微服務
            • 3.1. 搭建product-serv模塊
            • 3.2. 配置yml
            • 3.3. 實體
            • 3.4. 接口
            • 3.5. service
            • 3.6. controller
            • 3.7. 啟動類
          • 四、秒殺模塊微服務
            • 4.1. 搭建skill-serv模塊
            • 4.2. 配置yml
            • 4.3. 實體
            • 4.4. 接口
            • 4.5. service
            • 4.6. controller
            • 4.7. 啟動類

前言:為什么單獨搭建秒殺微服務呢?
為什么不對訂單微服務和庫存為負進行復用呢?

  • 與正常業務服務隔離避免因秒殺影響主營業務
  • 可根據秒殺流量單獨擴容和設置參數
一、應用部署準備
1. mysql安裝部署

windows 環境
MySQL 8.0.26 簡易配置安裝教程 (windows 64位)

Linux 環境
Mysql 8.0 安裝教程 Linux Centos7

2. redis安裝部署

windows 環境
windows下載、安裝運行redis

Linux 環境
(單機)Linux環境安裝最新版Redis-6.2.0
linux環境下redis5.0的安裝配置

3. nacos安裝部署

版本選擇
畢業版本依賴關系(推薦使用)

Spring Cloud VersionSpring Cloud Alibaba VersionSpring Boot VersionNacos Version
Spring Cloud Hoxton.SR92.2.6.RELEASE2.3.2.RELEASE1.4.2

nacos官網:
https://nacos.io/zh-cn/docs/quick-start.html

下載對用版本的nacos
https://github.com/alibaba/nacos/tags

啟動nacos

# 啟動命令(standalone代表著單機模式運行,非集群模式): # linux sh startup.sh -m standalone# Windows startup.cmd -m standalone

二、數據庫準備
2.1. 創建數據庫

創建一個名稱為skill的數據庫

2.2. 初始化表結構
-- ---------------------------- -- Table structure for skill_goods -- ---------------------------- DROP TABLE IF EXISTS `skill_goods`; CREATE TABLE `skill_goods` (`id` bigint NOT NULL AUTO_INCREMENT,`name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '標題',`price` decimal(10, 2) NULL DEFAULT NULL COMMENT '原價格',`cost_price` decimal(10, 2) NULL DEFAULT NULL COMMENT '秒殺價格',`status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '審核狀態,0未審核,1審核通過,2審核不通過',`num` int NULL DEFAULT NULL COMMENT '秒殺商品數',`stock_count` int NULL DEFAULT NULL COMMENT '剩余庫存數',`introduction` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '描述',PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC;-- ---------------------------- -- Table structure for skill_order -- ---------------------------- DROP TABLE IF EXISTS `skill_order`; CREATE TABLE `skill_order` (`id` bigint NOT NULL AUTO_INCREMENT,`skill_id` bigint NULL DEFAULT NULL COMMENT '秒殺商品ID',`money` decimal(10, 2) NULL DEFAULT NULL COMMENT '支付金額',`user_id` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用戶',`create_time` datetime NULL DEFAULT NULL COMMENT '創建時間',`pay_time` datetime NULL DEFAULT NULL COMMENT '支付時間',`status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '狀態0-未支付, 1-已支付',PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC;
2.3. 搭建微服務父工程

由于很多依賴都是一樣的,因此,搭建一個父工程引入依賴,子模塊集成依賴即可
創建eshop-parent父工程
引入依賴

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.2.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.gblfy</groupId><artifactId>eshop-parent</artifactId><version>1.0-SNAPSHOT</version><!--https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E--><properties><java.version>1.8</java.version><spring.cloud-version>Hoxton.SR9</spring.cloud-version></properties><dependencies><!--redis--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!--Lombok引入--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!--mysql--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!-- Spring Boot JPA 依賴 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><!--mvc--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--服務注冊發現--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!--配置中心--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency></dependencies><dependencyManagement><dependencies><!--spring-cloud 版本控制--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring.cloud-version}</version><type>pom</type><scope>import</scope></dependency><!--spring-cloud-alibaba 版本控制--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>2.2.6.RELEASE</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement> </project>
三、商品模塊微服務
3.1. 搭建product-serv模塊

集成父工程

<parent><artifactId>eshop-parent</artifactId><groupId>com.gblfy</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>product-serv</artifactId>
3.2. 配置yml
server:port: 9000 spring:cloud:nacos:discovery:service: product-servserver-addr: localhost:8848datasource:url: jdbc:mysql://localhost:3306/skill?characterEncoding=UTF-8&serverTimezone=GMT%2B8username: rootpassword: 123456redis:host: localhostport: 6379
3.3. 實體
package com.gblfy.entity;import lombok.Data;import javax.persistence.*; import java.io.Serializable; import java.math.BigDecimal;@Data @Entity @Table(name="skill_goods") public class SkillGood implements Serializable {public SkillGood() {}@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;/*** 標題*/@Column(name = "name")private String name;/*** 原價格*/@Column(name = "price")private BigDecimal price;/*** 秒殺價格*/@Column(name = "cost_price")private BigDecimal costPrice;/*** 審核狀態*/@Column(name = "status")private String status;/*** 秒殺商品數*/@Column(name = "num")private Integer num;/*** 剩余庫存數*/@Column(name = "stock_count")private Integer stockCount;/*** 描述*/@Column(name = "introduction")private String introduction;private static final long serialVersionUID = 1L;}
3.4. 接口
package com.gblfy.dao;import com.gblfy.entity.SkillGood; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository;import java.util.List;@Repository public interface SkillGoodRepository extends JpaRepository<SkillGood,Long> {@Query(value="select * from skill_goods where status=1 and num>0 and stock_count>0 and id not in (?1)",nativeQuery = true)List<SkillGood> findSkill(List<Long> ids);@Query(value="select * from skill_goods where status=1 and num>0 and stock_count>0",nativeQuery = true)List<SkillGood> findSkillAll(); }
3.5. service
package com.gblfy.service;import com.gblfy.dao.SkillGoodRepository; import com.gblfy.entity.SkillGood; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils;import java.util.ArrayList; import java.util.List; import java.util.Set;@Component @RequiredArgsConstructor(onConstructor_ = @Autowired) public class SkillGoodService {private final RedisTemplate redisTemplate;private final SkillGoodRepository skillGoodRepository;public static final String SKILL_GOODS_PHONE = "SKILL_GOODS_PHONE";/*** 每五秒執行一次 將需要參與秒殺的商品列表加載到內存*/@Scheduled(cron = "0/5 * * * * ?")public void prepareGood() {System.out.println("開始加載商品");//獲取所有已經在內存當中的商品ID列表Set<Long> set = redisTemplate.boundHashOps(SKILL_GOODS_PHONE).keys();List<Long> ids = new ArrayList<>();for (Long id : set) {ids.add(id);}List<SkillGood> list = null;//只查詢出不在內存當中的商品信息,并加載到內存if (CollectionUtils.isEmpty(ids)) {list = skillGoodRepository.findSkillAll();} else {list = skillGoodRepository.findSkill(ids);}if (!CollectionUtils.isEmpty(list)) {for (SkillGood skillGood : list) {redisTemplate.boundHashOps(SKILL_GOODS_PHONE).put(skillGood.getId(), skillGood);}}// 查看當前緩存中所有的商品信息Set keys = redisTemplate.boundHashOps(SKILL_GOODS_PHONE).keys();for (Object s : keys) {SkillGood skillGood = (SkillGood) redisTemplate.boundHashOps(SKILL_GOODS_PHONE).get(s);System.out.println(skillGood.getName() + " 庫存剩余:" + skillGood.getStockCount());}}// 提供查詢商品信息的方法public SkillGood queryProduct(Long productId) {return (SkillGood) redisTemplate.boundHashOps(SKILL_GOODS_PHONE).get(productId);}public void update(SkillGood skillGood) {skillGoodRepository.save(skillGood);} }
3.6. controller
package com.gblfy.controller;import com.gblfy.entity.SkillGood; import com.gblfy.service.SkillGoodService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*;@RestController public class ProductController {@Autowiredprivate SkillGoodService skillGoodService;@GetMapping("/product/{productId}")@ResponseBodypublic SkillGood getProduct(@PathVariable Long productId){System.out.println("調用商品服務");SkillGood skillGood=skillGoodService.queryProduct(productId);return skillGood;}@PostMapping("/product")public String update(@RequestBody SkillGood skillGood){System.out.println("更新庫存");skillGoodService.update(skillGood);return "更新庫存成功";} }
3.7. 啟動類
package com.gblfy;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.StringRedisSerializer; import org.springframework.scheduling.annotation.EnableScheduling;@SpringBootApplication @EnableScheduling public class ProductAplication {public static void main(String[] args) {SpringApplication.run(ProductAplication.class);}@Beanpublic RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {RedisTemplate<Object, Object> template = new RedisTemplate<>();template.setConnectionFactory(redisConnectionFactory);//采用普通的key 為 字符串template.setKeySerializer(new StringRedisSerializer());return template;} }
四、秒殺模塊微服務
4.1. 搭建skill-serv模塊

集成父工程

<parent><artifactId>eshop-parent</artifactId><groupId>com.gblfy</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>skill-serv</artifactId>
4.2. 配置yml
server:port: 13000 spring:cloud:nacos:discovery:service: skill-servserver-addr: localhost:8848datasource:url: jdbc:mysql://localhost:3306/skill?characterEncoding=UTF-8&serverTimezone=GMT%2B8username: rootpassword: 123456redis:host: localhostport: 6379
4.3. 實體
package com.gblfy.entity;import javax.persistence.*; import java.io.Serializable; import java.math.BigDecimal;@Entity @Table(name = "skill_goods") @Data public class SkillGood implements Serializable {public SkillGood() {}@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;/*** 標題*/@Column(name = "name")private String name;/*** 原價格*/@Column(name = "price")private BigDecimal price;/*** 秒殺價格*/@Column(name = "cost_price")private BigDecimal costPrice;/*** 審核狀態*/@Column(name = "status")private String status;/*** 秒殺商品數*/@Column(name = "num")private Integer num;/*** 剩余庫存數*/@Column(name = "stock_count")private Integer stockCount;/*** 描述*/@Column(name = "introduction")private String introduction;private static final long serialVersionUID = 1L; package com.gblfy.entity;import javax.persistence.*; import java.io.Serializable; import java.math.BigDecimal; import java.util.Date;@Entity @Table(name = "skill_order") @Data public class SkillOrder implements Serializable {/*** 主鍵*/@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;/*** 秒殺商品ID*/@Column(name = "skill_id")private Long skillId;/*** 支付金額*/@Column(name = "money")private BigDecimal money;/*** 用戶*/@Column(name = "user_id")private String userId;/*** 創建時間*/@Column(name = "create_time")private Date createTime;/*** 支付時間*/@Column(name = "pay_time")private Date payTime;/*** 狀態*/@Column(name = "status")private String status;private static final long serialVersionUID = 1L;
4.4. 接口
package com.gblfy.dao;import com.gblfy.entity.SkillOrder; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository;@Repository public interface SkillOrderRepository extends JpaRepository<SkillOrder,Long> { }
4.5. service
package com.gblfy.service;import com.gblfy.entity.SkillGood; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate;@Service @RequiredArgsConstructor(onConstructor_ = @Autowired) public class ProductService {private final RestTemplate restTemplate;public SkillGood getGoodById(Long productId) {return restTemplate.getForObject("http://product-serv/product/" + productId, SkillGood.class);}public void update(SkillGood skillGood) {ResponseEntity<String> result= restTemplate.postForEntity("http://product-serv/product/",skillGood,String.class);System.out.println(result.getBody());} } package com.gblfy.service;import com.gblfy.dao.SkillOrderRepository; import com.gblfy.entity.SkillGood; import com.gblfy.entity.SkillOrder; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service;import javax.transaction.Transactional; import java.util.Date;@Service @RequiredArgsConstructor(onConstructor_ = @Autowired) public class SkillGoodService {public static final String SKILL_GOODS_PHONE = "SKILL_GOODS_PHONE";private final RedisTemplate redisTemplate;private final SkillOrderRepository skillOrderRepository;private final ProductService productService;@Transactionalpublic void add(Long productId, String userId) throws Exception {SkillGood skillGood = productService.getGoodById(productId);if (skillGood == null) {throw new Exception("商品已經被搶光拉");}if (skillGood.getStockCount() > 0) {SkillOrder skillOrder = new SkillOrder();skillOrder.setMoney(skillGood.getCostPrice());skillOrder.setPayTime(new Date());skillOrder.setStatus("0");skillOrder.setUserId(userId);skillOrder.setCreateTime(new Date());skillOrder.setSkillId(productId);skillOrderRepository.save(skillOrder);skillGood.setStockCount(skillGood.getStockCount() - 1);redisTemplate.boundHashOps(SKILL_GOODS_PHONE).put(skillGood.getId(), skillGood);System.out.println("成功秒殺 剩余庫存:" + skillGood.getStockCount());}if (skillGood.getStockCount() <= 0) {System.out.println("庫存已經是負數了:" + skillGood.getStockCount());redisTemplate.boundHashOps(SKILL_GOODS_PHONE).delete(skillGood.getId());productService.update(skillGood);}} }
4.6. controller
package com.gblfy.controller;import com.gblfy.service.SkillGoodService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController;@RestController public class SkillController {@Autowiredprivate SkillGoodService skillGoodService;@GetMapping("/skill")public String add(Long productId,String userId) {try{skillGoodService.add(productId,userId);return "搶單成功";}catch (Exception e){return "商品已經搶光";}} }
4.7. 啟動類
package com.gblfy;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.StringRedisSerializer; import org.springframework.web.client.RestTemplate;@SpringBootApplication @EnableDiscoveryClient public class SkillServApplication {public static void main(String[] args) {SpringApplication.run(SkillServApplication.class, args);}@Beanpublic RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {RedisTemplate<Object, Object> template = new RedisTemplate<>();template.setConnectionFactory(redisConnectionFactory);//采用普通的key 為 字符串template.setKeySerializer(new StringRedisSerializer());return template;}@Bean@LoadBalancedpublic RestTemplate create() {return new RestTemplate();} }

總結

以上是生活随笔為你收集整理的秒杀场景_同步秒杀分析和实战_01的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。