解決數據一致性方案(庫存問題)

解決數據一致性方案

本文只講述原理,均爲僞代碼,具體實現還得小夥伴實現。

Redis

Redis中第一種庫存存儲方式

  1. hset(key,value,goods) == set(key,goods)
  2. 秒殺業務下單

代碼:

		//查詢商品
        goods = redis.get(key);
        //判斷庫存
        if (goods.getStockCount <= 0) {
   
   
            //已售馨
        } else {
   
   
            //減redis庫存
            //下單業務
        }
問題:
在第一步執行,如果有多個線程一起進來,都會拿到相同數量庫存,會出現超賣現象。

Redis中第二種方式

  1. hset(key,value,goods) == set(key,goods)
  2. 庫存:hset(key, value, stockCount)
		//減庫存
		Long result = redis.increment(key, value, -1);
        if (result <= 0) {
   
   
            //已售馨
        }
        //下單業務

Redis中第三種方式

  1. hset(key,value,goods) == set(key,goods)
  2. lpush(key, ltemid) //使用隊列存儲商品id

在這裏插入圖片描述

隊列

扣減緩存庫存時候,發送消息通知數據庫庫存也進行扣減,從而到達緩存數據和數據庫數據一致性。

		//從redis扣減庫存
        Long increment = redisTemplate.opsForValue().increment(商品id, -1);
        //判斷扣減庫存是否成功
        if (increment > 0) {
   
   
            //發送下單信息
            boolean res = mq.send(商品id);
            if (!res) {
   
   
                //消息發送失敗,庫存回滾
                redisTemplate.opsForValue().increment(商品id, 1);
            }
        } else if (increment == 0) {
   
   
            //商品已售馨
        } else {
   
   
            //扣減庫存失敗,庫存回滾
            redisTemplate.opsForValue().increment(商品id, 1);
        }

        //下單業務

問題:

  1. 異步消息發送失敗——已解決(上述代碼)
  2. 扣減操作失敗——已解決(上述代碼)
  3. 下單失敗(數據無法正確回滾)發送事務型消息(半消息,提交)

事務消息

如果下單業務處理失敗,那麼數據庫庫存已經扣減,需要回滾消息。

		Long increment = redisTemplate.opsForValue().increment(商品id, -1);
        //判斷扣減庫存是否成功
        if (increment > 0) {
   
   
            //庫存扣減成功
        } else if (increment == 0) {
   
   
            //商品已售馨
        } else {
   
   
            //扣減庫存失敗,庫存回滾
            redisTemplate.opsForValue().increment(商品id, 1);
        }

        //下單業務

        //發送事務消息,沒有發送成功拋異常回滾事務
        boolean res = Mq.sendTransaction(消息);
        if (!res) {
   
   
            new RunnTimeException(“下單失敗”);
        }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章