zoukankan      html  css  js  c++  java
  • 谷粒商城秒杀商品上架(四十六)

    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

  • 相关阅读:
    JQuery对象操作支持链式法则源码分析
    JQuery + JSON作为前后台数据交换格式实践
    JQuery html API支持解析执行Javascript脚本功能实现-代码分析
    跨域访问实践
    XP下安装MAC OS虚拟系统
    Android APP开发笔记
    CSS浮动与清浮动
    LUA 模块化编程例子
    JavaScript解决命名冲突的一种方法
    XML中文本节点存储任意字符的方法
  • 原文地址:https://www.cnblogs.com/dalianpai/p/13530711.html
Copyright © 2011-2022 走看看