亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

redis樂觀鎖與悲觀鎖怎么使用

發布時間:2023-04-13 09:49:49 來源:億速云 閱讀:131 作者:iii 欄目:開發技術

本篇內容主要講解“redis樂觀鎖與悲觀鎖怎么使用”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“redis樂觀鎖與悲觀鎖怎么使用”吧!

概念

Redis是一個內存中的鍵值存儲系統,支持多種數據結構,如字符串、哈希、列表等。Redis提供了兩種鎖機制,即樂觀鎖和悲觀鎖。

樂觀鎖

樂觀鎖是一種樂觀的并發控制策略,它認為數據在大多數情況下不會被其他線程占用,因此每次需要修改數據時,都不會獲取鎖,而是直接進行修改。在Redis中,可以通過WATCH和CAS命令來實現樂觀鎖,WATCH命令用于監視一個或多個鍵,CAS命令用于檢查并更新鍵的值。

例如,假設有一個計數器鍵counter,多個客戶端都需要對其進行操作。使用樂觀鎖的方式,可以在每個客戶端執行操作之前,先通過WATCH命令監視counter鍵:

WATCH counter
current_count = GET counter
new_count = current_count + 1
MULTI
SET counter new_count
EXEC

然后,在EXEC命令執行之前,使用GET命令再次獲取counter鍵的值,并將其與之前獲取的值進行比較。如果值相等,就說明期間沒有其他客戶端對counter鍵進行了修改,此時可以使用CAS命令將新值設置到counter鍵中。如果值不相等,則說明期間有其他客戶端對counter鍵進行了修改,需要重新執行操作。

GET counter

悲觀鎖

悲觀鎖是一種悲觀的并發控制策略,它認為數據在大多數情況下都會被其他線程占用,因此每次需要修改數據時,都會先獲取鎖,確保在修改期間沒有其他線程可以訪問該數據。在Redis中,可以通過WATCH命令來實現悲觀鎖,該命令可以監視一個或多個鍵,如果在事務執行期間有任何被監視鍵的值發生了變化,整個事務會被回滾。

還是上文的例子

WATCH counter
current_count = GET counter
new_count = current_count + 1
MULTI
SET counter new_count
EXEC

如果在執行事務期間,有其他客戶端修改了counter鍵,那么整個事務會被回滾,需要重新執行。

悲觀鎖的優點在于它可以確保數據的一致性,但缺點在于它需要獲取鎖,可能會引起線程的阻塞,影響并發性能。

樂觀鎖示例

假設有一個電商平臺,用戶可以在平臺上購買商品。為了保證數據的一致性,我們可以使用Redis的樂觀鎖來實現商品庫存的扣減。

首先,我們需要在Redis中保存每個商品的庫存信息,使用hash數據結構來保存,例如:

然后,在業務邏輯中,當用戶購買一個商品時,需要執行以下步驟:

  • 使用WATCH命令監視商品庫存鍵,例如stock:sku001;

  • 使用GET命令獲取當前商品庫存數量;

  • 檢查商品庫存是否足夠,如果不足,直接返回錯誤信息;

  • 計算新的庫存數量,并使用MULTI命令開啟一個事務;

  • 使用HSET命令將新的庫存數量保存到Redis中;

  • 執行事務,如果在執行期間有其他客戶端修改了商品庫存,會回滾事務,需要重新執行。

下面是使用Spring Boot實現的示例代碼:

@Service
public class OrderService {
    private final RedisTemplate<String, Integer> redisTemplate;

    @Autowired
    public OrderService(RedisTemplate<String, Integer> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    public void placeOrder(String sku, int quantity) {
        String stockKey = "stock:" + sku;
        while (true) {
            // 監視商品庫存鍵,以便在事務開始前檢測是否有其他客戶端修改了庫存
            redisTemplate.watch(stockKey);
            // 獲取當前庫存數量
            int currentStock = redisTemplate.opsForHash().get(stockKey, sku);
            // 檢查庫存是否足夠
            if (currentStock < quantity) {
                // 庫存不足,放棄事務并拋出異常
                redisTemplate.unwatch();
                throw new RuntimeException("Out of stock");
            }
            // 計算新的庫存數量
            int newStock = currentStock - quantity;
            // 開始事務
            redisTemplate.multi();
            // 更新庫存數量
            redisTemplate.opsForHash().put(stockKey, sku, newStock);
            // 提交事務
            List<Object> results = redisTemplate.exec();
            // 如果事務執行成功,則退出循環
            if (results != null) {
                break;
            }
            // 如果事務執行失敗,則重試
        }
    }
}

在上面的代碼中,我們使用RedisTemplate來操作Redis,其中watch方法用于監視商品庫存鍵,opsForHash方法用于獲取和修改商品庫存的值,multi和exec方法用于開啟和提交事務。

悲觀鎖示例

除了樂觀鎖,Redis還支持悲觀鎖,可以通過設置NX(Not Exist)或XX(Exist)標志來實現。例如,當NX標志設置為true時,如果鎖不存在,會返回OK,并創建一個鎖;如果鎖已經存在,會返回null,表示獲取鎖失敗。反之,當XX標志設置為true時,如果鎖已經存在,會返回OK,表示獲取鎖成功;如果鎖不存在,會返回null,表示獲取鎖失敗。

下面是使用Spring Boot實現的悲觀鎖示例代碼:

@Service
public class OrderService {
    private final RedisTemplate<String, String> redisTemplate;

    @Autowired
    public OrderService(RedisTemplate<String, String> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    public void placeOrder(String sku, int quantity) {
        String lockKey = "lock:" + sku;
        // 嘗試獲取鎖,如果鎖已經存在,說明有其他線程正在執行相關操作
        Boolean locked = redisTemplate.opsForValue().setIfAbsent(lockKey, "locked");
        if (!locked) {
            // 獲取鎖失敗,拋出異常
            throw new RuntimeException("Unable to acquire lock");
        }
        // 設置鎖的過期時間,防止鎖被一直占用
        redisTemplate.expire(lockKey, 10, TimeUnit.SECONDS);
        try {
            // 執行訂單創建、扣減庫存等操作
        } finally {
            // 釋放鎖
            redisTemplate.delete(lockKey);
        }
    }
}

在上面的代碼中,我們使用setIfAbsent方法來嘗試獲取鎖,如果鎖已經存在,說明其他線程正在執行相關操作,此時會返回false,表示獲取鎖失敗;否則,會返回true,表示獲取鎖成功。如果獲取鎖成功,我們會設置鎖的過期時間,并執行相關操作,最后釋放鎖。

到此,相信大家對“redis樂觀鎖與悲觀鎖怎么使用”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

瓦房店市| 桑日县| 常山县| 随州市| 博白县| 河源市| 黄梅县| 万安县| 鄂伦春自治旗| 南木林县| 万年县| 泗洪县| 贵港市| 临汾市| 兴山县| 家居| 金门县| 尼木县| 大连市| 霍邱县| 永德县| 香河县| 本溪市| 鲁山县| 分宜县| 余干县| 大安市| 蒙阴县| 石城县| 鱼台县| 封开县| 东丰县| 桓仁| 新营市| 北票市| 洛浦县| 丽江市| 谢通门县| 天峨县| 灵山县| 台南县|