文章目录
- 一、商品微服务改造
- 二、秒杀微服务改造
- 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 {
@Autowired
private RedisTemplate redisTemplate;
public static final String SKILL_GOODS_PHONE = "SKILL_GOODS_PHONE";
public static final String SKILL_GOODS_QUEUE = "SKILL_GOODS_QUEUE";
@Autowired
private 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";
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private SkillOrderRepository skillOrderRepository;
@Autowired
private ProductService productService;
@Autowired
private MutilThreadOrder mutilThreadOrder;
@Transactional
public 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 {
@Autowired
private ProductService productService;
@Autowired
private SkillOrderRepository skillOrderRepository;
@Autowired
private RedisTemplate redisTemplate;
@Async
public 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("结束异步抢单");
}
}