最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Redis鎖與DB鎖的使用與區(qū)別小結(jié)

 更新時間:2026年03月06日 09:44:55   作者:AlbenXie  
本文主要介紹了Redis鎖與DB鎖的使用與區(qū)別小結(jié),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

一、Redis 鎖與 DB 鎖的對比

Redis 鎖(分布式鎖)和 DB 鎖(數(shù)據(jù)庫鎖)是分布式場景下控制并發(fā)的核心手段,二者在實現(xiàn)方式、性能、可靠性、適用場景上差異顯著:

維度

Redis 鎖(如 SETNX/Redlock)

DB 鎖(如行鎖 / 表鎖 / 唯一索引)

實現(xiàn)方式

1. 基礎(chǔ)版:SETNX key value EX 過期時間(單節(jié)點)

2. 高級版:Redlock(多節(jié)點 Redis 集群)

1. 行鎖:SELECT FOR UPDATE(悲觀鎖)、版本號(樂觀鎖)

2. 表鎖:LOCK TABLES

3. 唯一索引:通過唯一約束實現(xiàn)分布式鎖

性能

極高(內(nèi)存操作,QPS 可達 10 萬 +),加鎖 / 解鎖耗時微秒級

較低(磁盤 IO + 事務(wù)開銷),加鎖 / 解鎖耗時毫秒級,高并發(fā)下易成為瓶頸

可靠性

1. 單節(jié)點:Redis 宕機則鎖失效(需設(shè)置過期時間兜底)

2. Redlock:多節(jié)點降低宕機風險,但仍存在時鐘漂移問題

高(數(shù)據(jù)庫事務(wù) ACID 保障,宕機后恢復數(shù)據(jù)不丟失),鎖由數(shù)據(jù)庫事務(wù)機制保障

鎖粒度

粗粒度(按 key 鎖,可自定義粒度,如用戶 ID、訂單號)

細粒度(行鎖可鎖定單條記錄,表鎖粒度最粗)

過期機制

支持自動過期(EX 參數(shù)),可防止死鎖

1. 悲觀鎖:依賴事務(wù)提交 / 回滾釋放,若事務(wù)卡住則死鎖

2. 樂觀鎖:無過期,靠版本號控制

分布式支持

天然支持分布式(Redis 集群),跨服務(wù) / 跨機器

支持分布式(數(shù)據(jù)庫主從 / 集群),但跨庫鎖需額外處理(如 XA 事務(wù))

死鎖風險

低(過期時間自動釋放),但可能出現(xiàn)鎖過期導致并發(fā)問題(如業(yè)務(wù)處理時間超過過期時間)

高(悲觀鎖),需依賴數(shù)據(jù)庫死鎖檢測機制自動解除,或人工干預

適用場景

1. 高并發(fā)場景(如秒殺、支付)

2. 非核心數(shù)據(jù)的并發(fā)控制

3. 短期鎖(業(yè)務(wù)處理時間短)

1. 低并發(fā)場景

2. 核心數(shù)據(jù)的并發(fā)控制(如資金變動)

3. 長期鎖(業(yè)務(wù)處理時間長)

4. 需要事務(wù)保障的場景

實現(xiàn)復雜度

中等(需處理鎖過期、重入、釋放別人的鎖等問題,可使用 Redisson 框架)

低(悲觀鎖直接用 SELECT FOR UPDATE,唯一索引只需建表)

二、舉例說明

我們通過電商秒殺場景金融資金扣減場景兩個典型案例,結(jié)合代碼實現(xiàn)和問題分析,深入對比 Redis 鎖與 DB 鎖的差異、適用場景及坑點。

先明確核心概念

  • Redis 鎖:基于 Redis 的內(nèi)存操作實現(xiàn)的分布式鎖,核心是SETNX(SET if Not Exists)指令,本質(zhì)是非持久化的分布式鎖(單節(jié)點),可通過 Redlock/Redisson 實現(xiàn)高可用。
  • DB 鎖:基于數(shù)據(jù)庫的鎖機制,常見的有悲觀行鎖(SELECT FOR UPDATE)樂觀鎖(版本號)、唯一索引鎖,本質(zhì)是持久化的鎖,依賴數(shù)據(jù)庫事務(wù) ACID 保障。

案例 1:電商秒殺場景(高并發(fā)、短事務(wù))

業(yè)務(wù)背景

某電商平臺秒殺 iPhone,庫存只有 100 臺,每秒有 10 萬 + 請求,需要控制并發(fā)下單,防止超賣。

方案 1:使用 Redis 鎖實現(xiàn)

1. 核心實現(xiàn)(基于 Redisson,解決原生 Redis 鎖的坑)

Redisson 是 Redis 的 Java 客戶端,封裝了分布式鎖的實現(xiàn),自動處理鎖過期、重入、釋放別人的鎖、集群高可用等問題。

@Service
public class SeckillService {
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private SeckillMapper seckillMapper;
    @Autowired
    private RedisTemplate<String, Integer> redisTemplate;
 
    // 秒殺核心方法
    public String seckill(String productId, String userId) {
        // 1. 定義Redis鎖key(粒度:商品ID,確保同一商品的秒殺串行)
        String lockKey = "seckill_lock:" + productId;
        RLock lock = redissonClient.getLock(lockKey);
 
        try {
            // 2. 獲取鎖(等待時間10秒,鎖自動過期30秒,防止死鎖)
            boolean lockSuccess = lock.tryLock(10, 30, TimeUnit.SECONDS);
            if (!lockSuccess) {
                return "秒殺太火爆了,請稍后重試!";
            }
 
            // 3. 業(yè)務(wù)邏輯:先查Redis庫存(緩存),再扣減,最后同步到DB
            Integer stock = redisTemplate.opsForValue().get("seckill_stock:" + productId);
            if (stock == null || stock <= 0) {
                return "秒殺已結(jié)束!";
            }
            // 扣減Redis庫存
            redisTemplate.opsForValue().decrement("seckill_stock:" + productId);
            // 生成訂單(異步寫入DB,提升性能)
            seckillMapper.createOrder(productId, userId);
            return "秒殺成功!";
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return "秒殺失敗,請重試!";
        } finally {
            // 4. 釋放鎖(只有持有鎖的線程才能釋放)
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }
}

2. Redis 鎖在秒殺場景的優(yōu)勢

  • 性能極高:Redis 是內(nèi)存數(shù)據(jù)庫,tryLock/unlock操作耗時微秒級,能支撐 10 萬 + QPS 的并發(fā)請求,而 DB 鎖在高并發(fā)下會因磁盤 IO 和事務(wù)開銷導致性能瓶頸。
  • 鎖粒度靈活:按商品 ID 作為鎖 key,只鎖定當前秒殺的商品,其他商品的秒殺不受影響(細粒度鎖),而 DB 表鎖會鎖定整個庫存表,導致所有商品秒殺阻塞。
  • 自動過期防死鎖:設(shè)置鎖過期時間,即使秒殺服務(wù)宕機,鎖也會自動釋放,不會導致死鎖;而 DB 悲觀鎖若事務(wù)卡住,會一直持有鎖,直到數(shù)據(jù)庫超時。

3. Redis 鎖的坑點及解決

  • 鎖過期問題:若秒殺業(yè)務(wù)處理時間超過 30 秒(如 DB 寫入卡頓),鎖會提前過期,導致其他線程獲取鎖,可能出現(xiàn)超賣。
    • 解決:Redisson 的自動續(xù)期機制(看門狗),持有鎖的線程會每隔 10 秒自動將鎖過期時間延長至 30 秒,直到線程釋放鎖。
  • Redis 單節(jié)點宕機:若 Redis 主節(jié)點宕機,鎖數(shù)據(jù)丟失,多個線程同時獲取鎖,導致超賣。
    • 解決:使用Redlock 算法(部署多個 Redis 節(jié)點,線程需獲取半數(shù)以上節(jié)點的鎖才算成功)或Redis 主從 + 哨兵(主節(jié)點宕機后從節(jié)點自動切換,減少鎖丟失概率)。

方案 2:使用 DB 鎖(SELECT FOR UPDATE)實現(xiàn)

1. 核心實現(xiàn)

@Service
public class SeckillService {
    @Autowired
    private SeckillMapper seckillMapper;
 
    // 秒殺核心方法(事務(wù)內(nèi)執(zhí)行)
    @Transactional(rollbackFor = Exception.class)
    public String seckill(String productId, String userId) {
        // 1. 獲取DB行鎖(根據(jù)商品ID鎖定庫存記錄,悲觀鎖)
        SeckillStock stock = seckillMapper.selectStockByProductIdForUpdate(productId);
        if (stock == null || stock.getStock() <= 0) {
            return "秒殺已結(jié)束!";
        }
 
        // 2. 扣減庫存
        seckillMapper.decrementStock(productId);
        // 3. 生成訂單
        seckillMapper.createOrder(productId, userId);
        return "秒殺成功!";
    }
}
 
// Mapper接口
public interface SeckillMapper {
    @Select("SELECT * FROM seckill_stock WHERE product_id = #{productId} FOR UPDATE")
    SeckillStock selectStockByProductIdForUpdate(String productId);
 
    @Update("UPDATE seckill_stock SET stock = stock - 1 WHERE product_id = #{productId}")
    int decrementStock(String productId);
 
    @Insert("INSERT INTO seckill_order (product_id, user_id) VALUES (#{productId}, #{userId})")
    void createOrder(String productId, String userId);
}

2. DB 鎖在秒殺場景的劣勢

  • 性能極低:每秒僅能支撐幾千 QPS,10 萬 + 并發(fā)下會出現(xiàn)大量請求阻塞,數(shù)據(jù)庫連接池被占滿,甚至導致數(shù)據(jù)庫宕機。
    • 原因:SELECT FOR UPDATE是磁盤 IO 操作,且事務(wù)需要等待鎖釋放,高并發(fā)下產(chǎn)生大量鎖競爭。
  • 死鎖風險:若多個線程同時鎖定多個商品的庫存記錄(如用戶同時秒殺 iPhone 和華為),可能出現(xiàn)死鎖。
    • 示例:線程 A 鎖定商品 1,等待商品 2 的鎖;線程 B 鎖定商品 2,等待商品 1 的鎖,導致死鎖。
    • 解決:數(shù)據(jù)庫會自動檢測死鎖并回滾其中一個事務(wù),但會增加業(yè)務(wù)失敗率。
  • 鎖粒度問題:若product_id沒有索引,SELECT FOR UPDATE會升級為表鎖,導致所有商品的秒殺都被阻塞,性能進一步下降。

3. 結(jié)論:秒殺場景優(yōu)先用 Redis 鎖

Redis 鎖的性能和并發(fā)支撐能力遠優(yōu)于 DB 鎖,適合高并發(fā)、短事務(wù)的場景,即使存在少量鎖過期風險,也可通過業(yè)務(wù)兜底(如庫存最終一致性校驗)解決。

案例 2:金融資金扣減場景(低并發(fā)、核心數(shù)據(jù)、長事務(wù))

業(yè)務(wù)背景

某銀行 APP 的用戶轉(zhuǎn)賬功能,用戶 A 向用戶 B 轉(zhuǎn)賬 1 萬元,需要扣減 A 的余額,增加 B 的余額,要求資金絕對不能出錯(不能多扣、少扣、重復扣)。

方案 1:使用 DB 鎖(SELECT FOR UPDATE)實現(xiàn)

1. 核心實現(xiàn)

@Service
public class TransferService {
    @Autowired
    private AccountMapper accountMapper;
 
    // 轉(zhuǎn)賬核心方法(事務(wù)內(nèi)執(zhí)行,保證原子性)
    @Transactional(rollbackFor = Exception.class)
    public String transfer(String fromUserId, String toUserId, BigDecimal amount) {
        // 1. 校驗金額
        if (amount.compareTo(BigDecimal.ZERO) <= 0) {
            return "轉(zhuǎn)賬金額必須大于0!";
        }
 
        // 2. 獲取用戶A的行鎖(扣減余額前加鎖,防止并發(fā)扣減)
        Account fromAccount = accountMapper.selectByUserIdForUpdate(fromUserId);
        if (fromAccount == null) {
            return "轉(zhuǎn)出賬戶不存在!";
        }
        // 校驗余額
        if (fromAccount.getBalance().compareTo(amount) < 0) {
            return "余額不足!";
        }
 
        // 3. 獲取用戶B的行鎖(防止并發(fā)更新)
        Account toAccount = accountMapper.selectByUserIdForUpdate(toUserId);
        if (toAccount == null) {
            return "轉(zhuǎn)入賬戶不存在!";
        }
 
        // 4. 扣減用戶A的余額
        accountMapper.decrementBalance(fromUserId, amount);
        // 5. 增加用戶B的余額
        accountMapper.incrementBalance(toUserId, amount);
 
        return "轉(zhuǎn)賬成功!";
    }
}
 
// Mapper接口
public interface AccountMapper {
    @Select("SELECT * FROM account WHERE user_id = #{userId} FOR UPDATE")
    Account selectByUserIdForUpdate(String userId);
 
    @Update("UPDATE account SET balance = balance - #{amount} WHERE user_id = #{userId}")
    int decrementBalance(String userId, BigDecimal amount);
 
    @Update("UPDATE account SET balance = balance + #{amount} WHERE user_id = #{userId}")
    int incrementBalance(String userId, BigDecimal amount);
}

2. DB 鎖在資金扣減場景的優(yōu)勢

  • 數(shù)據(jù)絕對安全:依賴數(shù)據(jù)庫事務(wù)的 ACID 特性,扣減和增加余額的操作要么全成,要么全敗,不會出現(xiàn)中間狀態(tài)(如 A 的余額扣減了,但 B 的余額沒增加)。
  • 鎖的持久性:即使服務(wù)宕機,數(shù)據(jù)庫的鎖和事務(wù)狀態(tài)會被持久化,恢復后數(shù)據(jù)一致;而 Redis 鎖若宕機,鎖數(shù)據(jù)丟失,可能導致并發(fā)扣減。
  • 無鎖過期風險:資金扣減的業(yè)務(wù)處理時間可能較長(如需要校驗用戶身份、風控規(guī)則),Redis 鎖的過期時間難以設(shè)置(設(shè)置太短會提前釋放,設(shè)置太長會導致死鎖),而 DB 鎖只要事務(wù)不提交,就會一直持有鎖(可通過數(shù)據(jù)庫超時機制兜底)。
  • 易于審計:所有資金操作都在數(shù)據(jù)庫事務(wù)中,可通過日志追溯,滿足金融合規(guī)要求;而 Redis 的操作日志難以審計。

3. DB 鎖的優(yōu)化點

  • 鎖粒度:必須為user_id創(chuàng)建主鍵索引,確保SELECT FOR UPDATE是行鎖,而非表鎖。
  • 死鎖處理:按用戶 ID 的字典序加鎖(如先鎖定 user_id 小的賬戶,再鎖定大的),避免死鎖。
    • 示例:用戶 A(ID:1001)向用戶 B(ID:1002)轉(zhuǎn)賬,先鎖定 1001,再鎖定 1002;用戶 B 向用戶 A 轉(zhuǎn)賬,同樣先鎖定 1001,再鎖定 1002,避免死鎖。

方案 2:使用 Redis 鎖實現(xiàn)

1. 核心實現(xiàn)

@Service
public class TransferService {
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private AccountMapper accountMapper;
 
    public String transfer(String fromUserId, String toUserId, BigDecimal amount) {
        // 1. 定義Redis鎖key(粒度:用戶ID,按字典序加鎖)
        String lockKey1 = "transfer_lock:" + (fromUserId.compareTo(toUserId) < 0 ? fromUserId : toUserId);
        String lockKey2 = "transfer_lock:" + (fromUserId.compareTo(toUserId) > 0 ? fromUserId : toUserId);
        RLock lock1 = redissonClient.getLock(lockKey1);
        RLock lock2 = redissonClient.getLock(lockKey2);
 
        try {
            // 2. 批量獲取鎖(等待時間10秒,鎖過期30秒)
            boolean lockSuccess = RedissonMultiLock(lock1, lock2).tryLock(10, 30, TimeUnit.SECONDS);
            if (!lockSuccess) {
                return "轉(zhuǎn)賬請求處理中,請稍后重試!";
            }
 
            // 3. 業(yè)務(wù)邏輯(扣減+增加余額,無事務(wù)保障)
            Account fromAccount = accountMapper.selectByUserId(fromUserId);
            if (fromAccount == null || fromAccount.getBalance().compareTo(amount) < 0) {
                return "余額不足或賬戶不存在!";
            }
            Account toAccount = accountMapper.selectByUserId(toUserId);
            if (toAccount == null) {
                return "轉(zhuǎn)入賬戶不存在!";
            }
 
            // 4. 扣減余額(無事務(wù),可能出現(xiàn)扣減成功但增加失?。?
            accountMapper.decrementBalance(fromUserId, amount);
            // 模擬網(wǎng)絡(luò)異常:此處若服務(wù)宕機,A的余額被扣減,B的余額未增加,資金丟失
            // int a = 1 / 0;
            accountMapper.incrementBalance(toUserId, amount);
 
            return "轉(zhuǎn)賬成功!";
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return "轉(zhuǎn)賬失敗,請重試!";
        } finally {
            // 5. 釋放鎖
            if (lock1.isHeldByCurrentThread()) {
                lock1.unlock();
            }
            if (lock2.isHeldByCurrentThread()) {
                lock2.unlock();
            }
        }
    }
}

2. Redis 鎖在資金扣減場景的致命問題

  • 數(shù)據(jù)一致性無法保障:Redis 鎖只能控制并發(fā),但無法保證扣減和增加余額的原子性。若扣減 A 的余額后,服務(wù)宕機,B 的余額未增加,會導致資金丟失,這在金融場景中是絕對不允許的。
    • 解決:需引入分布式事務(wù)(如 TCC、本地消息表),但會增加系統(tǒng)復雜度,且性能進一步下降。
  • 鎖過期風險:若資金扣減的業(yè)務(wù)處理時間超過 30 秒(如風控校驗耗時較長),鎖會提前過期,其他線程獲取鎖后,會再次扣減 A 的余額,導致重復扣減。
  • 審計困難:Redis 的鎖操作日志無法與資金操作日志關(guān)聯(lián),難以滿足金融合規(guī)的審計要求。

3. 結(jié)論:資金扣減場景優(yōu)先用 DB 鎖

DB 鎖結(jié)合事務(wù)的 ACID 特性,能保證核心數(shù)據(jù)的一致性和安全性,即使性能較低,也符合金融場景的核心需求(數(shù)據(jù)安全 > 性能)。

總結(jié):Redis 鎖與 DB 鎖的選擇指南

場景特征推薦使用原因
高并發(fā)、短事務(wù)、非核心數(shù)據(jù)Redis 鎖性能高,能支撐高并發(fā),少量異??赏ㄟ^業(yè)務(wù)兜底解決
低并發(fā)、長事務(wù)、核心數(shù)據(jù)DB 鎖(SELECT FOR UPDATE)事務(wù) ACID 保障數(shù)據(jù)安全,無鎖過期風險,滿足合規(guī)審計要求
冪等性控制(如重復支付)DB 鎖(唯一索引)無需鎖等待,性能高于悲觀鎖,能有效防止重復寫入
分布式系統(tǒng)、跨服務(wù)并發(fā)Redis 鎖天然支持分布式,跨服務(wù) / 跨機器的鎖控制更簡單
單服務(wù)、本地并發(fā)本地鎖(synchronized)比 Redis 鎖和 DB 鎖更輕量,性能更高

補充:Redis 鎖與 DB 鎖的混合使用場景

在實際項目中,可結(jié)合兩者的優(yōu)勢:

  • 秒殺場景:Redis 鎖控制并發(fā)下單 + DB 唯一索引防止超賣(兜底)。
    • 流程:Redis 鎖扣減 Redis 庫存 → 異步寫入 DB → DB 唯一索引(訂單號)防止重復下單,若 Redis 庫存扣減成功但 DB 寫入失敗,通過定時任務(wù)回滾 Redis 庫存。
  • 訂單支付場景:Redis 鎖控制并發(fā)支付 + DB 事務(wù)保證資金變動原子性。
    • 流程:Redis 鎖防止重復支付 → DB 事務(wù)扣減余額 + 生成支付記錄 → 支付完成后釋放 Redis 鎖。

擴展補充:

一、為什么會有 Redis 鎖的存在?為什么還會有 DB 鎖的存在?

Redis 鎖和 DB 鎖的誕生,本質(zhì)是不同業(yè)務(wù)場景對 “并發(fā)控制” 的需求存在本質(zhì)差異,二者分別解決了對方無法高效解決的問題,是分布式系統(tǒng)中針對 “性能” 和 “數(shù)據(jù)安全” 的不同選擇。

1. Redis 鎖的誕生:為解決高并發(fā)分布式場景下的性能型并發(fā)控制問題

在 Redis 鎖出現(xiàn)之前,處理分布式并發(fā)的方案有:

  • 本地鎖(synchronized/Lock):僅能控制單服務(wù)內(nèi)的并發(fā),分布式集群下多個服務(wù)節(jié)點無法共享鎖,會導致并發(fā)安全問題(如秒殺場景中多個節(jié)點同時扣減庫存,引發(fā)超賣);
  • DB 鎖:能解決分布式并發(fā),但性能極低(磁盤 IO + 事務(wù)開銷),無法支撐高并發(fā)場景(如秒殺、電商促銷的 10 萬 + QPS)。

而 Redis 作為內(nèi)存數(shù)據(jù)庫,具備高性能、分布式部署、輕量易擴展的特性,基于它實現(xiàn)的分布式鎖,恰好彌補了上述方案的缺陷:

  • 面對高并發(fā)請求,Redis 鎖的加鎖 / 解鎖操作是內(nèi)存級別的,耗時微秒級,能支撐超高 QPS;
  • Redis 天然支持分布式部署,跨服務(wù)、跨機器的節(jié)點能共享鎖狀態(tài),完美解決分布式集群的并發(fā)控制問題;
  • 支持靈活的過期機制,能有效防止死鎖,且鎖粒度可自定義(如按商品 ID、用戶 ID 鎖),適配不同業(yè)務(wù)場景。

總結(jié):Redis 鎖的存在,是為了滿足分布式系統(tǒng)中高并發(fā)、短事務(wù)、非核心數(shù)據(jù)場景對 “高性能并發(fā)控制” 的需求,是性能優(yōu)先的選擇。

2. DB 鎖的誕生:為解決核心數(shù)據(jù)場景下的安全型并發(fā)控制問題

在 DB 鎖出現(xiàn)之前,僅靠應(yīng)用層的邏輯控制并發(fā),會面臨以下問題:

  • 應(yīng)用層邏輯無法保證數(shù)據(jù)操作的原子性(如扣減余額時,查余額和更新余額的兩步操作之間,可能被其他請求插入,導致余額計算錯誤);
  • 分布式場景下,應(yīng)用層的臨時狀態(tài)(如內(nèi)存中的標記)無法持久化,服務(wù)宕機后會丟失,導致數(shù)據(jù)不一致;
  • 核心數(shù)據(jù)(如資金、訂單狀態(tài))需要事務(wù)級別的安全保障,應(yīng)用層方案無法滿足 ACID 特性。

而數(shù)據(jù)庫作為持久化存儲,具備事務(wù) ACID 特性、數(shù)據(jù)持久化、鎖與事務(wù)強綁定的特性,基于它實現(xiàn)的鎖,恰好解決了上述問題:

  • DB 鎖與事務(wù)深度融合,能保證鎖范圍內(nèi)的操作要么全成、要么全敗,從底層杜絕數(shù)據(jù)中間態(tài);
  • 數(shù)據(jù)和鎖狀態(tài)都持久化到磁盤,即使服務(wù)或數(shù)據(jù)庫宕機,恢復后數(shù)據(jù)和鎖狀態(tài)依然一致,無數(shù)據(jù)丟失風險;
  • 支持細粒度的行鎖、表鎖,能精準控制核心數(shù)據(jù)的并發(fā)訪問,滿足金融、電商等場景的合規(guī)和數(shù)據(jù)安全要求。

總結(jié):DB 鎖的存在,是為了滿足核心數(shù)據(jù)場景(資金、訂單)、低并發(fā)、長事務(wù)對 “數(shù)據(jù)安全與一致性” 的需求,是安全優(yōu)先的選擇。

二、Redis 鎖與 DB 鎖最根本、最本質(zhì)的區(qū)別

二者的本質(zhì)區(qū)別,源于底層存儲介質(zhì)和設(shè)計目標的不同,最終體現(xiàn)為 **“性能與臨時態(tài)” vs “安全與持久態(tài)”** 的核心差異:

維度本質(zhì)特征(Redis 鎖)本質(zhì)特征(DB 鎖)
存儲介質(zhì)內(nèi)存(臨時存儲,非持久化優(yōu)先)磁盤(持久化存儲,數(shù)據(jù)落地優(yōu)先)
設(shè)計目標高性能處理并發(fā),犧牲部分數(shù)據(jù)安全的容錯性高安全保障數(shù)據(jù)一致性,犧牲部分性能
鎖的本質(zhì)分布式協(xié)調(diào)的 “臨時標記”:鎖是內(nèi)存中的一個 key-value,僅用于標記資源是否被占用,與數(shù)據(jù)操作無強綁定數(shù)據(jù)操作的 “原子性保障”:鎖是事務(wù)的一部分,與數(shù)據(jù)操作強綁定,確保操作的 ACID 特性
一致性保障最終一致性(依賴應(yīng)用層補償機制,如重試、對賬)強一致性(依賴數(shù)據(jù)庫事務(wù)的 ACID 特性)
故障恢復鎖狀態(tài)可能丟失(如 Redis 宕機),需依賴過期時間、集群(Redlock)兜底鎖狀態(tài)與數(shù)據(jù)一起持久化,宕機恢復后狀態(tài)不變

一句話總結(jié)本質(zhì)區(qū)別:Redis 鎖是基于內(nèi)存的、松耦合的、性能導向的分布式并發(fā)協(xié)調(diào)工具;DB 鎖是基于磁盤的、強耦合的、安全導向的事務(wù)內(nèi)數(shù)據(jù)操作保障工具。

三、Redis 鎖解決的最核心問題?DB 鎖解決的最核心問題?

1. Redis 鎖解決的最核心問題

在分布式集群環(huán)境下,以極致的性能解決 “高并發(fā)場景中資源的并發(fā)訪問控制” 問題,具體拆解為:

  • 分布式并發(fā)控制:突破單服務(wù)本地鎖的限制,讓跨服務(wù)、跨機器的節(jié)點共享鎖狀態(tài),避免分布式場景下的并發(fā)安全問題(如秒殺場景中多個節(jié)點同時扣減庫存);
  • 高性能并發(fā)處理:內(nèi)存級別的加鎖 / 解鎖操作,支撐 10 萬 + QPS 的高并發(fā)請求,解決 DB 鎖在高并發(fā)下的性能瓶頸;
  • 靈活的資源隔離:通過自定義鎖 key 的粒度(如商品 ID、用戶 ID),實現(xiàn)細粒度的資源隔離,避免全局鎖導致的性能浪費。

典型場景驗證:秒殺活動中,Redis 鎖能控制 10 萬 + 并發(fā)請求對 100 臺庫存的訪問,確保不超賣,且系統(tǒng)不會因并發(fā)壓力崩潰 —— 這是 Redis 鎖核心價值的體現(xiàn)。

2. DB 鎖解決的最核心問題

在數(shù)據(jù)操作過程中,以事務(wù)的 ACID 特性解決 “核心數(shù)據(jù)的一致性與安全性保障” 問題,具體拆解為:

  • 數(shù)據(jù)操作的原子性:確保一組數(shù)據(jù)操作(如扣減用戶余額 + 增加商戶余額)要么全部完成,要么全部回滾,杜絕數(shù)據(jù)中間態(tài)(如用戶余額扣減了但商戶余額沒增加,導致資金丟失);
  • 核心數(shù)據(jù)的強一致性:鎖與數(shù)據(jù)存儲強綁定,并發(fā)操作下數(shù)據(jù)的讀取和寫入都是準確的,無需依賴應(yīng)用層補償;
  • 數(shù)據(jù)的持久化安全:鎖狀態(tài)和數(shù)據(jù)一起持久化到磁盤,即使系統(tǒng)宕機,恢復后數(shù)據(jù)依然一致,滿足金融、電商等核心場景的合規(guī)要求。

典型場景驗證:銀行轉(zhuǎn)賬場景中,DB 鎖(SELECT FOR UPDATE)能保證用戶 A 扣減 1 萬元與用戶 B 增加 1 萬元的操作原子性,無論發(fā)生何種故障,都不會出現(xiàn)資金丟失或賬實不符 —— 這是 DB 鎖核心價值的體現(xiàn)。

補充:為何二者無法相互替代?

  • Redis 鎖無法替代 DB 鎖:Redis 鎖缺乏事務(wù)的原子性保障,核心數(shù)據(jù)操作(如資金變動)若僅用 Redis 鎖,會出現(xiàn)數(shù)據(jù)不一致且無法兜底,這在金融場景中是致命的;
  • DB 鎖無法替代 Redis 鎖:DB 鎖的性能瓶頸無法突破,高并發(fā)場景(如秒殺)下,DB 鎖會導致大量請求阻塞,甚至數(shù)據(jù)庫宕機,無法支撐業(yè)務(wù)需求。

二者的共存,是分布式系統(tǒng)中 **“性能” 與 “安全” 平衡 ** 的必然結(jié)果。

到此這篇關(guān)于Redis鎖與DB鎖的使用與區(qū)別小結(jié)的文章就介紹到這了,更多相關(guān)Redis鎖與DB鎖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Redis實現(xiàn)高效內(nèi)存管理的示例代碼

    Redis實現(xiàn)高效內(nèi)存管理的示例代碼

    Redis內(nèi)存管理是其核心功能之一,為了高效地利用內(nèi)存,Redis采用了多種技術(shù)和策略,如優(yōu)化的數(shù)據(jù)結(jié)構(gòu)、內(nèi)存分配策略、內(nèi)存回收、數(shù)據(jù)壓縮等,下面就來詳細的介紹一下
    2025-08-08
  • 淺談redission鎖的默認失效時間

    淺談redission鎖的默認失效時間

    Redisson是一個基于Redis的Java駐留庫,提供了許多分布式對象和服務(wù),包括分布式鎖,本文主要介紹了淺談redission鎖的默認失效時間, 具有一定的參考價值,感興趣的可以了解一下
    2024-02-02
  • redis GEO數(shù)據(jù)結(jié)構(gòu)、實現(xiàn)附近商鋪功能實踐

    redis GEO數(shù)據(jù)結(jié)構(gòu)、實現(xiàn)附近商鋪功能實踐

    文章介紹了Redis中的GEO命令及其用途,包括地理坐標存儲、距離計算、坐標轉(zhuǎn)換和位置搜索等功能,還分享了如何使用Redis實現(xiàn)查詢附近商鋪的功能,包括導入商鋪信息和根據(jù)類型及距離進行搜索
    2025-12-12
  • redis配置文件中常用配置詳解

    redis配置文件中常用配置詳解

    這篇文章主要介紹了redis配置文件中常用配置詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-04-04
  • redis?手機驗證碼實現(xiàn)示例

    redis?手機驗證碼實現(xiàn)示例

    本文主要介紹了redis?手機驗證碼實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • Redis之RedisTemplate配置方式(序列和反序列化)

    Redis之RedisTemplate配置方式(序列和反序列化)

    這篇文章主要介紹了Redis之RedisTemplate配置方式(序列和反序列化),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Redis獲取某個前綴的key腳本實例

    Redis獲取某個前綴的key腳本實例

    這篇文章主要給大家介紹了關(guān)于Redis獲取某個前綴的key腳本的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用Redis具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。
    2018-04-04
  • 基于setnx,lua腳本和Redisson詳解Redis分布式鎖實現(xiàn)的三種方式

    基于setnx,lua腳本和Redisson詳解Redis分布式鎖實現(xiàn)的三種方式

    分布式鎖是解決分布式系統(tǒng)中多節(jié)點并發(fā)訪問共享資源的核心方案,本文從原理層面拆解Redis分布式鎖的核心邏輯,并詳細分析三種常見實現(xiàn)方式的代碼邏輯、優(yōu)缺點及生產(chǎn)環(huán)境注意事項,感興趣的朋友跟隨小編一起看看吧
    2026-03-03
  • Redis?常見緩存問題總結(jié)

    Redis?常見緩存問題總結(jié)

    這篇文章主要給大家總結(jié)了一些Redis?常見緩存問題,并介紹了解決辦法,文中的圖文示例介紹的非常仔細,感興趣的同學可以參考閱讀下
    2023-06-06
  • redis如何設(shè)置key的有效期

    redis如何設(shè)置key的有效期

    這篇文章主要介紹了redis如何設(shè)置key的有效期方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01

最新評論

双桥区| 隆林| 沧州市| 高台县| 肇州县| 颍上县| 德庆县| 宕昌县| 丰城市| 镇巴县| 泽库县| 呈贡县| 手游| 阳新县| 上林县| 崇州市| 灵川县| 南安市| 和林格尔县| 申扎县| 贵定县| 攀枝花市| 南充市| 锡林浩特市| 镇原县| 伊春市| 临澧县| 寿阳县| 古浪县| 皋兰县| 佛冈县| 赣榆县| 武胜县| 彰化县| 固始县| 五常市| 昭平县| 河北区| 万年县| 华宁县| 通道|