秒杀场景_解决秒杀超卖问题_04
生活随笔
收集整理的這篇文章主要介紹了
秒杀场景_解决秒杀超卖问题_04
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- 一、商品微服務改造
- 二、秒殺微服務改造
- 2.1. SkillGoodService 改造
- 2.2. MutilThreadOrder 改造
一、商品微服務改造
SkillGoodService改造
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 public class SkillGoodService {@Autowiredprivate RedisTemplate redisTemplate;public static final String SKILL_GOODS_PHONE = "SKILL_GOODS_PHONE";public static final String SKILL_GOODS_QUEUE = "SKILL_GOODS_QUEUE";@Autowiredprivate SkillGoodRepository skillGoodRepository;/*** 每五秒執行一次 將需要參與秒殺的商品列表加載到內存*/@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);redisTemplate.boundListOps(SKILL_GOODS_QUEUE+skillGood.getId()).leftPushAll(convertoArry(skillGood.getStockCount(),skillGood.getId()));}}// 查看當前緩存中所有的商品信息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());}}private Long[] convertoArry(Integer stockCount, Long id) {Long[] idslong=new Long[stockCount];for(int i=0;i<stockCount;i++){idslong[i]=id;}return idslong;}// 提供查詢商品信息的方法public SkillGood queryProduct(Long productId) {return (SkillGood) redisTemplate.boundHashOps(SKILL_GOODS_PHONE).get(productId);}// 更新商品信息public void update(SkillGood skillGood) {skillGoodRepository.save(skillGood);} }二、秒殺微服務改造
2.1. SkillGoodService 改造
package com.gblfy.service;import com.gblfy.dao.SkillOrderRepository; import com.gblfy.entity.SkillEntity; 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.UUID;@Service public class SkillGoodService {public static final String SKILL_GOODS_PHONE = "SKILL_GOODS_PHONE";public static final String SKILL_GOODS_LIST = "SKILL_GOODS_LIST";public static final String SKILL_GOODS_ONLY = "SKILL_GOODS_ONLY";public static final String SKILL_GOODS_QUEUE = "SKILL_GOODS_QUEUE";@Autowiredprivate RedisTemplate redisTemplate;@Autowiredprivate SkillOrderRepository skillOrderRepository;@Autowiredprivate ProductService productService;@Autowiredprivate MutilThreadOrder mutilThreadOrder;@Transactionalpublic void add(Long productId, String userId) throws Exception {//判斷這個用戶是否參加過搶單userId = UUID.randomUUID().toString();Long time = redisTemplate.boundHashOps(SKILL_GOODS_ONLY).increment(userId, 1L);if (time > 1) {throw new Exception("重復搶單,不要太貪心");}// 先封裝對象 并且放入redis 隊列SkillEntity skillEntity = new SkillEntity();skillEntity.setProductId(productId);skillEntity.setUserId(userId);redisTemplate.boundListOps(SKILL_GOODS_LIST).leftPush(skillEntity);mutilThreadOrder.createOrder();} }2.2. MutilThreadOrder 改造
package com.gblfy.service;import com.gblfy.dao.SkillOrderRepository; import com.gblfy.entity.SkillEntity; import com.gblfy.entity.SkillGood; import com.gblfy.entity.SkillOrder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component;import java.util.Date;@Component public class MutilThreadOrder {@Autowiredprivate ProductService productService;@Autowiredprivate SkillOrderRepository skillOrderRepository;@Autowiredprivate RedisTemplate redisTemplate;@Asyncpublic void createOrder() throws Exception {System.out.println("開始異步搶單");SkillEntity skillEntity = (SkillEntity) redisTemplate.boundListOps(SkillGoodService.SKILL_GOODS_LIST).rightPop();if (skillEntity == null) {return;}Long productId = skillEntity.getProductId();String userId = skillEntity.getUserId();SkillGood skillGood = productService.getGoodById(productId);if (skillGood == null) {throw new Exception("商品已經被搶光拉");}Long stockId = (Long) redisTemplate.boundListOps(SkillGoodService.SKILL_GOODS_QUEUE + productId).rightPop();if (stockId == null) {System.out.println("該商品已被秒殺完畢");redisTemplate.boundHashOps(SkillGoodService.SKILL_GOODS_ONLY).delete(userId);redisTemplate.boundHashOps(SkillGoodService.SKILL_GOODS_PHONE).delete(skillGood.getId());skillGood.setStockCount(0);productService.update(skillGood);return;}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);System.out.println("結束異步搶單");} }總結
以上是生活随笔為你收集整理的秒杀场景_解决秒杀超卖问题_04的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Nexus 3.31.1 maven 私
- 下一篇: ethercat 网卡不兼容_曾经的洋垃