一.思路
将秒杀商品的信息存入redis中,减少对数据库在瞬发时的压力,读取商品信息及减少库存时运用缓存,当库存为0时再同步到数据库,产生的订单也是先存入缓存中,当用户支付成功后再存入数据库当中。

二.代码实现

public void getSecKill() {
        HashMap<Long,Production> linkedHashMap=secKillMapper.getSecKill()
                .stream()
                .collect(Collectors.toMap(Production::getGoods_id, v->v,(v1, v2)->v1,HashMap::new));
        for(Map.Entry<Long,Production> entry:linkedHashMap.entrySet()){
            redisUtils.putHashValue(Production.class.getSimpleName(),entry.getKey().toString(), entry.getValue());
            for(int i=0;i<entry.getValue().getStock_count();i++){
                String id= entry.getKey().toString();
                redisUtils.putListData(SECKILL_ID+id,id);
            }
        }
    }

说明:这里只是个demo所以我们用了固定的数据,正常情况下要根据各种条件筛选出符合商品进行储存
Production.class.getSimpleName():为商品信息队列,Key为商品的id,Value为商品的详细信息
SECKILL_ID:为一个final常量,在这里就用SECKILL_ID作为List名,一个商品有多少库存则存入多少个,key为商品固定前缀加id,value为id,这么设置是因为,redis的ListQuequ队列有个特性,就是此队列的size有多少则只能由多少个线程能拿到值,简单地说就是为了防止多卖,假设库存为5则只有5个线程能拿的到。

public void toOrder(String account, String good_id) {
        //判断该用户是否已下单(是否在缓存队列中)
        if (!redisUtils.hasSetKey(USER_RECORD_ID,account)){
            //判断是否还有商品(redis中的list的list.size是几就只能有几个线程拿到)
            if(null!=redisUtils.getListData(SECKILL_ID+good_id)){
                //将成功的秒杀成功的用户存入redis中
                redisUtils.setSetData(USER_RECORD_ID,account);
                //将订单存入redis中
                OrderRecord record=new OrderRecord(good_id,account);
                redisUtils.putListData(OrderRecord.class.getSimpleName(),record);
                executor.execute(orderCreate);
            } else {
                System.out.println("此商品已售完");
            }
        } else {
            System.out.println("你的订单正在等待支付。。");
        }
    }

USER_RECORD_ID:为redis中的setQueue,此队列的特点为不能存入相同的值,防止一个用户多次点击(无论点多少次在缓存中只有一次的值)
OrderRecord.class.getSimpleName():为订单队列,存入的为预订单,里面包含商品id及用户id
这里还运用了线程池:ThreadPoolTaskExecutor

@Component
public class OrderCreate implements Runnable{
    @Resource
    private RedisUtils redisUtils;
    @Resource
    private secKillMapper secKillMapper;

    @Override
    public void run() {
        OrderRecord record=redisUtils.getListData(OrderRecord.class.getSimpleName());
        if(null!=record){
            Production production= redisUtils.getHashData(Production.class.getSimpleName(),record.getId());
            Order order=new Order();
            order.setUser_id(record.getUserId());
            order.setSeller_id(production.getSeller_id());
            order.setMoney(production.getCost_price());
            order.setCreate_time(new Date());
            order.setStatus("0");
            redisUtils.putHashValue(Order.class.getSimpleName(),record.getUserId(),order);
            synchronized (OrderCreate.class){
                production= redisUtils.getHashData(Production.class.getSimpleName(),record.getId());
                production.setStock_count(production.getStock_count()-1);
                if(production.getStock_count()<=0){
                    secKillMapper.updateGood(record.getId());
                    redisUtils.deleteHashValue(Production.class.getSimpleName(),record.getId());
                } else {
                    redisUtils.putHashValue(Production.class.getSimpleName(),record.getId(),production);
                }
            }

        }

    }
}

总结代码思路
Production.class.getSimpleName():商品信息队列
SECKILL_ID:商品库存队列
USER_RECORD_ID:用户秒杀成功队列
OrderRecord.class.getSimpleName() :用户订单队列

首先将所有符合条件的商品信息存入 商品信息队列 ,根据每个商品的库存数量存入相应的 商品库存队列,当用户进行秒杀时先去 用户秒杀成功队列 查看是否有该用户存在,没有的话 去 商品库存队列 取想要秒杀的商品的id,如果还有的话,把用户信息及商品id 存入 用户订单队列