SpringCloud實現Redis秒殺功能,適合新手學習思路


我用的是IDEA,建的是SpringCloud分布式項目,添加的是Gradle依賴。

首先在自己的秒殺模塊添加所需StringRedisTemplate依賴,此依賴無需配置,簡單好用。

// https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-redis'
View Code

下面貼一下Controller代碼:

@Autowired
    private StringRedisTemplate redisTemplate;
//秒殺開始
    @RequestMapping("/wyh_begin_kill")
    public String message(@RequestParam(value = "phone") String phone, @RequestBody SeckillEntity seckillEntity) {
        String key = phone + "_" + seckillEntity.getSeckill_id();//設置redis的key值
        String state = redisTemplate.opsForValue().get(key);//根據用戶手機號從redis緩存中查詢是否預約
        if (null == state) {//第一次進redis查詢,為空,然后去數據庫查詢是否預約秒殺
            List<SuccessKillEntity> list = successKillMapper.wyh_select_state(phone);//根據用戶手機號從數據庫查詢是否有該用戶的預約信息
            if (null == list) {//沒查到數據說明沒有預約
                System.out.println("該用戶沒有預約");
            } else {
                synchronized (this) {//否則更改redis狀態,使下一次免查詢
                    redisTemplate.opsForValue().set(phone + "_" + seckillEntity.getSeckill_id(), String.valueOf(list.get(0).getState()), 300, TimeUnit.SECONDS);
                    state = String.valueOf(list.get(0).getState());//修改狀態
                }
            }
        }

        if (state.equals("-1")) {
            List values = redisTemplate.opsForHash().values(seckillEntity.getSeckill_id() + "");//從redis查詢秒殺商品信息:秒殺開始和結束時間以及商品數量,沒有查到就從數據庫查詢
            if (values.size() == 0) {
                List<SeckillEntity> list = seckillMapper.wyh_select_seckill(String.valueOf(seckillEntity.getSeckill_id()));//從數據庫查詢秒殺商品
                if (null == list) {//沒查到數據說明沒有此秒殺商品
                    System.out.println("沒有該秒殺商品信息");
                }
                synchronized (this) {//上鎖 - 把秒殺商品信息加入redis,下一次免查詢
                    if (!redisTemplate.opsForHash().hasKey(seckillEntity.getSeckill_id() + "", "number")) {
                        HashMap<String, String> productHash = new HashMap<>();
                        productHash.put("number", list.get(0).getNumber() + "");//放入商品數量進redis
                        productHash.put("start_time", list.get(0).getStart_time().getTime() + "");//換算開始時間為毫秒數
                        productHash.put("end_time", list.get(0).getEnd_time().getTime() + "");//換算結束時間為毫秒數
                        redisTemplate.opsForHash().putAll(list.get(0).getSeckill_id() + "", productHash);
                        redisTemplate.expire(list.get(0).getSeckill_id() + "", 300, TimeUnit.SECONDS);
                        values = redisTemplate.opsForHash().values(seckillEntity.getSeckill_id() + "");
                    }
                }
            }
            if (new Date(Long.valueOf((String) values.get(1))).after(new Date(System.currentTimeMillis()))) {//判斷秒殺開始時間 - 毫秒數
                System.out.println("搶購還沒有開始");
            } else if (new Date(Long.valueOf((String) values.get(2))).before(new Date(System.currentTimeMillis()))) {//判斷秒殺結束時間 - 毫秒數
                System.out.println("搶購已經結束");
            } else {
                Long number = redisTemplate.opsForHash().increment(seckillEntity.getSeckill_id() + "", "number", -1);//從redis減少本次搶購商品 - 為負值說明數量為空 - 駁回請求
                if (number >= 0) {//還有庫存
                    redisTemplate.opsForValue().increment(key, 1);//更改redis中此用戶的搶購狀態 - 本次搶購成功,以后不讓搶購 - 限量
                    // 服務器閑暇時間將數據提交到數據庫 - 盡量避免直接操作數據庫 - 使用redis速度快 
                } else {
                    System.out.println("商品已被搶完");
                }
            }
        } else {
            System.out.println("您已搶購過該產品");
        }
        return null;
    }
View Code

這里附上數據庫表數據:

這里附上項目結構圖:

這里附上我參考的源碼地址:https://blog.csdn.net/feibabm/article/details/78026186


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM