一、樂觀鎖概述
樂觀鎖是一種並發控制機制,它假定在數據變更時不會有衝突發生,因此不會像悲觀鎖一樣在操作時先加鎖。
在Redis中,樂觀鎖常用於多線程、多用戶同時操作同一個數據的場景,例如秒殺、搶購、投票等。
二、Redis實現樂觀鎖的常用方法
1. WATCH/MULTI/EXEC
Redis通過 WATCH/MULTI/EXEC 指令實現樂觀鎖。這種方式基於事務,所以必須使用 Redis 2.0.0 版本以上才能使用。它的具體實現步驟如下:
// PHP代碼示例 $redis = new Redis(); $redis->connect('127.0.0.1', 6379); $key = 'goods_1001'; $quantity = 10; $redis->watch($key); // 監聽商品庫存 $currentQuantity = $redis->get($key); if ($currentQuantity unwatch(); // 取消監聽 echo '庫存不足'; } else { $redis->multi(); // 開啟事務 $redis->decrby($key, $quantity); // 減少商品庫存 $redis->exec(); // 提交事務 echo '扣減成功'; }
2. Redis分散式鎖
分散式鎖基於SETNX(SET if Not eXists)指令實現。使用 SETNX 可以在Redis中創建一個不存在的Key,如果該Key已存在,則設置失敗,返回0,設置成功返回1。
在使用Redis分散式鎖時,應該注意以下問題:
(1)由於每個客戶端都是獨立的,所以在執行一個操作時可能會有多個客戶端同時重複執行。我們需要解決相互之間的干擾。
(2)如果Redis分散式鎖的Key在SETNX後會因某種原因過期,那麼仍然存在多個進程同時競爭鎖的情況。
// PHP代碼示例 $redis = new Redis(); $redis->connect('127.0.0.1', 6379); $key = 'lock_key'; $value = uniqid(); // 生成唯一值作為鎖的值 $expire = 10; // 鎖過期時間,單位為秒 if ($redis->setnx($key, $value)) { // SETNX創建Key $redis->expire($key, $expire); // 設置Key過期時間 echo '加鎖成功'; // TODO:執行業務邏輯 $redis->del($key); // 釋放鎖 } else { echo '加鎖失敗'; }
三、實戰應用:Redis實現秒殺系統
下面結合Redis實現秒殺系統,以更形象地認識樂觀鎖。
假設有100個商品,每個用戶最多能夠購買3個,當庫存不足時不允許繼續購買。
系統的實現思路如下:
(1)使用 Redis 分散式鎖保證操作的同步。
(2)在 Redis 中存儲每個用戶的購買次數。
(3)通過 Redis 事務,先鎖定 Redis 中的庫存和用戶購買次數,再判斷庫存和用戶購買次數是否充足,若充足扣減庫存和購買次數。
// PHP代碼示例 $redis = new Redis(); $redis->connect('127.0.0.1', 6379); $key = 'goods_1001'; $quantity = 10; $user_id = 101; $user_key = "user_{$user_id}"; $user_limit = 3; $lock_key = 'lock_key'; $lock_expire = 10; // 獲取分散式鎖 while (!$redis->setnx($lock_key, uniqid())) { usleep(1000); // 暫停1ms再次嘗試 } $redis->expire($lock_key, $lock_expire); // 判斷商品庫存是否充足 $redis->watch($key, $user_key); $currentQuantity = $redis->get($key); $currentUserLimit = $redis->get($user_key) ?? 0; if ($currentQuantity >= $quantity && $currentUserLimit multi(); $redis->incrby($user_key, 1); // 記錄用戶購買次數+1 $redis->decrby($key, $quantity); // 商品庫存-10 // 執行Redis事務 $res = $redis->exec(); if ($res) { echo '購買成功'; } else { echo '購買失敗'; } } else { echo '購買失敗,庫存不足或購買次數已達上限'; } $redis->del($lock_key); // 釋放分散式鎖
總結
本文詳細介紹了Redis樂觀鎖的實現方式,其中包括使用 Redis 事務和 Redis 分散式鎖兩種方式。在實際應用中,需要根據具體業務場景選擇合適的方式來實現樂觀鎖。希望能對讀者有所幫助。
原創文章,作者:ASBQA,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/372658.html