Redis樂觀鎖詳解

一、樂觀鎖概述

樂觀鎖是一種並發控制機制,它假定在數據變更時不會有衝突發生,因此不會像悲觀鎖一樣在操作時先加鎖。

在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

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
ASBQA的頭像ASBQA
上一篇 2025-04-24 06:40
下一篇 2025-04-25 15:26

相關推薦

  • 在CentOS上安裝Redis

    Redis是一款非關係型資料庫,它支持多種數據結構,包括字元串、哈希、列表、集合、有序集合等。Redis運行內存內並且支持數據持久化,它還可以應用於緩存、消息隊列等場景。本文將介紹…

    編程 2025-04-28
  • 解析spring.redis.cluster.max-redirects參數

    本文將圍繞spring.redis.cluster.max-redirects參數進行詳細闡述,從多個方面解讀它的意義與作用,並給出相應的代碼示例。 一、基礎概念 在介紹sprin…

    編程 2025-04-27
  • Redis Bitmap用法介紹

    Redis是一款高性能的內存資料庫,支持多種數據類型,其中之一便是bitmap。Redis bitmap(點陣圖)是一種用二進位位來表示元素是否在集合中的數據結構。由於使用了二進位位…

    編程 2025-04-27
  • Linux sync詳解

    一、sync概述 sync是Linux中一個非常重要的命令,它可以將文件系統緩存中的內容,強制寫入磁碟中。在執行sync之前,所有的文件系統更新將不會立即寫入磁碟,而是先緩存在內存…

    編程 2025-04-25
  • 神經網路代碼詳解

    神經網路作為一種人工智慧技術,被廣泛應用於語音識別、圖像識別、自然語言處理等領域。而神經網路的模型編寫,離不開代碼。本文將從多個方面詳細闡述神經網路模型編寫的代碼技術。 一、神經網…

    編程 2025-04-25
  • 詳解eclipse設置

    一、安裝與基礎設置 1、下載eclipse並進行安裝。 2、打開eclipse,選擇對應的工作空間路徑。 File -> Switch Workspace -> [選擇…

    編程 2025-04-25
  • C語言貪吃蛇詳解

    一、數據結構和演算法 C語言貪吃蛇主要運用了以下數據結構和演算法: 1. 鏈表 typedef struct body { int x; int y; struct body *nex…

    編程 2025-04-25
  • Python輸入輸出詳解

    一、文件讀寫 Python中文件的讀寫操作是必不可少的基本技能之一。讀寫文件分別使用open()函數中的’r’和’w’參數,讀取文件…

    編程 2025-04-25
  • nginx與apache應用開發詳解

    一、概述 nginx和apache都是常見的web伺服器。nginx是一個高性能的反向代理web伺服器,將負載均衡和緩存集成在了一起,可以動靜分離。apache是一個可擴展的web…

    編程 2025-04-25
  • MPU6050工作原理詳解

    一、什麼是MPU6050 MPU6050是一種六軸慣性感測器,能夠同時測量加速度和角速度。它由三個感測器組成:一個三軸加速度計和一個三軸陀螺儀。這個組合提供了非常精細的姿態解算,其…

    編程 2025-04-25

發表回復

登錄後才能評論