谷粒商城秒杀商品上架(四十六)

310-320秒杀商品上架

断断续续差不多敲了3个月,这个星期差不多可以把高级结束,集群还有30级,下周应该可以把谷粒商城全部完结。

代码已经上传:https://gitee.com/dalianpai/gulimall

/**
 * @author WGR
 * @create 2020/8/17 -- 22:08
 */
@Slf4j
@Service
public class SeckillSkuScheduled {

    @Autowired
    SeckillService seckillService;

    @Autowired
    RedissonClient redissonClient;

    private final String upload_lock = "seckill:upload:lock";

    @Scheduled(cron ="0 * 3 * * ?")
    public void uploadSeckillSkulatest3Days(){
        log.info("商品上架");
        RLock lock = redissonClient.getLock(upload_lock);
        lock.lock(10, TimeUnit.SECONDS);
        try{
            seckillService.uploadSeckillSkuLatest3Days();
        }finally {
            lock.unlock();
        }

    }

}

主要的service方法

/**
 * @author WGR
 * @create 2020/8/17 -- 22:09
 */
@Service
public class SeckillServiceImpl implements SeckillService {

   @Autowired
    CouponFeignService couponFeignService;

   @Autowired
    StringRedisTemplate redisTemplate;

   @Autowired
    ProductFeignService productFeignService;

   @Autowired
    RedissonClient redissonClient;

   private final String SESSIONS_CACHE_PREFIX ="seckill:sessions:";
   private final String SKUKILL_CACHE_PREDIX ="seckill:skus";

   private final String SKU_STOCK_SEMPHORE ="seckill:stock:";

    @Override
    public void uploadSeckillSkuLatest3Days() {
        R session = couponFeignService.lates3DaySession();
        if(session.getCode()==0){
            List<SeckillSessionsWithSkus> sessionData = session.getData(new TypeReference<List<SeckillSessionsWithSkus>>(){});
            System.out.println(sessionData);
            saveSessionInfos(sessionData);
            saveSessionSkuInfos(sessionData);
        }
    }

    @Override
    public List<SecKillSkuRedisTo> getCurrentSeckillSkus() {
        // 1.确定当前时间属于那个秒杀场次
        long time = new Date().getTime();

            Set<String> keys = redisTemplate.keys(SESSIONS_CACHE_PREFIX + "*");
            for (String key : keys) {

                String replace = key.replace("seckill:sessions:", "");
                String[] split = replace.split("_");
                long start = Long.parseLong(split[0]);
                long end = Long.parseLong(split[1]);
                if(time >= start && time <= end){
                    // 2.获取这个秒杀场次的所有商品信息
                    List<String> range = redisTemplate.opsForList().range(key, 0, 100);
                    BoundHashOperations<String, String, String> hashOps = redisTemplate.boundHashOps(SKUKILL_CACHE_PREDIX);
                    List<String> list = hashOps.multiGet(range);
                    if(list != null){
                        return list.stream().map(item -> {
                            SecKillSkuRedisTo redisTo = JSON.parseObject(item, SecKillSkuRedisTo.class);
                            return redisTo;
                        }).collect(Collectors.toList());
                    }
                    break;
                }
        }
        return null;
    }

    @Override
    public SecKillSkuRedisTo getSkuSeckillInfo(Long skuId) {
        BoundHashOperations<String, String, String> hashOps = redisTemplate.boundHashOps(SKUKILL_CACHE_PREDIX);
        Set<String> keys = hashOps.keys();
        if(keys != null && keys.size() > 0){
            String regx = "\d+_" + skuId;
            for (String key : keys) {
                if(Pattern.matches(regx, key)){
                    String json = hashOps.get(key);
                    SecKillSkuRedisTo to = JSON.parseObject(json, SecKillSkuRedisTo.class);
                    // 处理一下随机码
                    long current = new Date().getTime();

                    if(current <= to.getStartTime() || current >= to.getEndTime()){
                        to.setRandomCode(null);
                    }
                    System.out.println(to);
                    return to;
                }
            }
        }
        return null;
    }

    private void saveSessionInfos(List<SeckillSessionsWithSkus> sessions){
        sessions.stream().forEach(session ->{
            long startTime = session.getStartTime().getTime();
            long endTime = session.getEndTime().getTime();
            String key = SESSIONS_CACHE_PREFIX + startTime + "_" + endTime;
            Boolean hasKey = redisTemplate.hasKey(key);
            if(!hasKey){
                List<String> collect = session.getRelationSkus().stream().map(item -> item.getPromotionSessionId().toString()+"_"+item.getSkuId().toString()).collect(Collectors.toList());
                //缓存活动信息
                redisTemplate.opsForList().leftPushAll(key,collect);
            }
        });


    }

  private void saveSessionSkuInfos(List<SeckillSessionsWithSkus> sessions){
      sessions.stream().forEach(session ->{
          BoundHashOperations<String, Object, Object> ops = redisTemplate.boundHashOps(SKUKILL_CACHE_PREDIX);
          session.getRelationSkus().stream().forEach(seckillSkuVo -> {
              String token = UUID.randomUUID().toString().replace("-", "");
              if(!ops.hasKey(seckillSkuVo.getPromotionSessionId().toString()+"_"+seckillSkuVo.getSkuId().toString())){
                  SecKillSkuRedisTo redisTo = new SecKillSkuRedisTo();
                  R skuInfo = productFeignService.info(seckillSkuVo.getSkuId());

                  if(skuInfo.getCode() ==0){
                      SkuInfoVo info = skuInfo.getData("skuInfo", new TypeReference<SkuInfoVo>() {
                      });
                      redisTo.setSkuInfo(info);
                  }

                  //2.sku的秒杀信息
                  BeanUtils.copyProperties(seckillSkuVo,redisTo);

                  //3.设置上当前商品的秒杀时间信息
                  redisTo.setStartTime(session.getStartTime().getTime());
                  redisTo.setEndTime(session.getEndTime().getTime());


                  redisTo.setRandomCode(token);

                  String jsonString = JSON.toJSONString(redisTo);
                  ops.put( seckillSkuVo.getPromotionSessionId().toString()+"_"+seckillSkuVo.getSkuId().toString(),jsonString);

                  RSemaphore semaphore = redissonClient.getSemaphore(SKU_STOCK_SEMPHORE + token);
                  semaphore.trySetPermits(seckillSkuVo.getSeckillCount());
              }

          });
      });
  }

jdk8的时间新特性,博客之前也写过:https://www.cnblogs.com/dalianpai/p/12609438.html

 @Override
    public List<SeckillSessionEntity> lates3DaySession() {
        List<SeckillSessionEntity> list = this.list(new QueryWrapper<SeckillSessionEntity>().between("start_time", startTime(), endTime()));
        if(list!=null && list.size()>0){
            List<SeckillSessionEntity> collect = list.stream().map(session -> {
                Long id = session.getId();
                List<SeckillSkuRelationEntity> relationEntities = seckillSkuRelationService.list(new QueryWrapper<SeckillSkuRelationEntity>().eq("promotion_session_id",id));
                System.out.println(relationEntities);
                session.setRelationSkus(relationEntities);
                return session;
            }).collect(Collectors.toList());
            return collect;
        }
        return null;
    }

    public String startTime(){
        LocalDate now = LocalDate.now();
        LocalTime min = LocalTime.MIN;
        LocalDateTime start = LocalDateTime.of(now, min);
        String format = start.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        return format;
    }

    public String endTime(){
        LocalDate now = LocalDate.now();
        LocalDate localDate = now.plusDays(2);
        LocalDateTime of = LocalDateTime.of(localDate, LocalTime.MAX);
        String format = of.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        return format;
    }

image-20200819173201929

image-20200819173221001

原文地址:https://www.cnblogs.com/dalianpai/p/13530711.html