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

SpringBoot使用Redis同時執(zhí)行多條命令的實現(xiàn)方法

 更新時間:2025年09月22日 09:56:58   作者:IT橘子皮  
在 Spring Boot 項目中高效、合理地使用 Redis 同時執(zhí)行多條命令,可以顯著提升應(yīng)用性能,下面我將為你介紹幾種主要方式、它們的典型應(yīng)用場景,以及如何在 Spring Boot 中實現(xiàn),需要的朋友可以參考下

在 Spring Boot 項目中高效、合理地使用 Redis 同時執(zhí)行多條命令,可以顯著提升應(yīng)用性能。下面我將為你介紹幾種主要方式、它們的典型應(yīng)用場景,以及如何在 Spring Boot 中實現(xiàn)。

首先,我們來通過一個表格快速了解這幾種方式的特點和適用場景:

方式原子性主要優(yōu)勢Spring Boot 中的典型應(yīng)用場景
?Pipeline (管道)??大幅提升批量操作效率,減少網(wǎng)絡(luò)往返次數(shù)緩存預(yù)熱、批量數(shù)據(jù)導(dǎo)入導(dǎo)出、無依賴關(guān)系的批量查詢
?事務(wù) (Transaction)??部分命令隊列化,保證連續(xù)執(zhí)行(但不支持回滾)簡單的原子操作序列,如庫存扣減、更新多個相關(guān)鍵
?Lua 腳本?復(fù)雜邏輯原子執(zhí)行,避免中間狀態(tài),性能高分布式鎖、秒殺、需要原子性的復(fù)雜業(yè)務(wù)邏輯

1. Pipeline (管道)

Pipeline 允許客戶端將多個命令打包后一次性發(fā)送給 Redis 服務(wù)器,服務(wù)器依次執(zhí)行后再次將所有結(jié)果一次性返回給客戶端。這能顯著減少網(wǎng)絡(luò)往返次數(shù)(RTT)?,從而大幅提升吞吐量,尤其在高延遲網(wǎng)絡(luò)環(huán)境下效果明顯。

?Spring Boot 實現(xiàn)示例:??

import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.stereotype.Service;
import java.util.List;

@Service
public class RedisPipelineService {

    private final StringRedisTemplate stringRedisTemplate;

    // 構(gòu)造器注入
    public RedisPipelineService(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }

    public void batchSetKeys(List<String> keys, List<String> values) {
        // 使用 executePipelined 方法執(zhí)行管道操作
        List<Object> results = stringRedisTemplate.executePipelined((RedisCallback<Object>) connection -> {
            for (int i = 0; i < keys.size(); i++) {
                connection.set(keys.get(i).getBytes(), values.get(i).getBytes());
            }
            return null; // 回調(diào)中返回 null
        });
        // results 包含每個命令的執(zhí)行結(jié)果
    }
}

?使用場景:??

  • ?緩存預(yù)熱?:應(yīng)用啟動時批量加載熱點數(shù)據(jù)到 Redis。
  • ?批量數(shù)據(jù)導(dǎo)入/導(dǎo)出?:例如從數(shù)據(jù)庫批量導(dǎo)入數(shù)據(jù)到 Redis,或從 Redis 批量獲取數(shù)據(jù)進(jìn)行處理。
  • ?批量查詢無關(guān)聯(lián)數(shù)據(jù)?:一次性獲取多個不相關(guān)鍵的值,減少網(wǎng)絡(luò)開銷。

?注意事項:??

  • Pipeline 中的命令不具備原子性。
  • 建議單次 Pipeline 命令數(shù)控制在合理范圍內(nèi)(如幾千條),避免服務(wù)器內(nèi)存壓力或客戶端長時間阻塞。
  • ?錯誤處理?:某個命令失敗不會影響 Pipeline 中其他命令的執(zhí)行,需要在客戶端解析結(jié)果列表時逐一檢查。

2. 事務(wù) (Transaction)

Redis 事務(wù)通過 MULTI, EXEC, DISCARD, WATCH等命令實現(xiàn)。它允許將多個命令放入一個隊列,然后通過 EXEC命令原子性地順序執(zhí)行這些命令。

?Spring Boot 實現(xiàn)示例:??

Spring Data Redis 提供了 SessionCallback接口來支持在同一個連接中執(zhí)行多個操作,這對于事務(wù)至關(guān)重要。

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.stereotype.Service;
import java.util.List;

@Service
public class RedisTransactionService {

    private final RedisTemplate<String, Object> redisTemplate;

    public RedisTransactionService(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    public List<Object> executeInTransaction() {
        // 使用 execute 方法并傳遞 SessionCallback 來執(zhí)行事務(wù)
        SessionCallback<List<Object>> sessionCallback = new SessionCallback<>() {
            @Override
            public List<Object> execute(org.springframework.data.redis.core.RedisOperations operations) {
                operations.multi(); // 開啟事務(wù)
                operations.opsForValue().set("key1", "value1");
                operations.opsForValue().increment("counter");
                operations.opsForSet().add("setKey", "member1");
                return operations.exec(); // 執(zhí)行事務(wù)并返回結(jié)果
            }
        };
        return redisTemplate.execute(sessionCallback);
    }
}

?使用場景:??

  • ?簡單的原子操作序列?:需要確保一系列命令連續(xù)執(zhí)行,不被其他命令打斷,但不要求所有命令必須全部成功?(例如,扣減庫存后增加銷量)。
  • ?結(jié)合 WATCH實現(xiàn)樂觀鎖?:監(jiān)控特定鍵,如秒殺場景中監(jiān)控庫存鍵,防止超賣。
// 結(jié)合 WATCH 的樂觀鎖示例
public boolean watchAndExecute(String key, String expectedValue, String newValue) {
    return redisTemplate.execute(new SessionCallback<Boolean>() {
        @Override
        public Boolean execute(RedisOperations operations) {
            operations.watch(key); // 監(jiān)視 key
            String currentValue = (String) operations.opsForValue().get(key);
            if (expectedValue.equals(currentValue)) {
                operations.multi();
                operations.opsForValue().set(key, newValue);
                List<Object> execResult = operations.exec(); // 如果 execResult 為空,表示事務(wù)執(zhí)行失敗(鍵被修改)
                return execResult != null && !execResult.isEmpty();
            }
            operations.unwatch();
            return false;
        }
    });
}

?注意事項:??

  • Redis 事務(wù)不支持回滾 (Rollback)?。如果在執(zhí)行過程中某個命令失敗,已執(zhí)行的命令不會回滾,后續(xù)命令仍會繼續(xù)執(zhí)行。
  • ?錯誤類型?:
    • ?入隊錯誤?(如命令語法錯誤):在執(zhí)行 EXEC前,Redis 可能會檢查出錯誤并放棄整個事務(wù)。
    • ?運行時錯誤?(如數(shù)據(jù)類型操作錯誤):在 EXEC后執(zhí)行中發(fā)生的錯誤,Redis 會記錄錯誤信息但不會中斷事務(wù)執(zhí)行。

3. Lua 腳本

Redis 支持執(zhí)行 ?Lua 腳本。腳本中的所有命令會作為一個整體原子性地執(zhí)行,期間不會被其他命令打斷,是原子性最強的方案,同時還能減少網(wǎng)絡(luò)往返。

?Spring Boot 實現(xiàn)示例:??

RedisTemplate提供了 execute方法用于執(zhí)行 Lua 腳本。

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import java.util.Arrays;

@Service
public class RedisLuaService {

    private final RedisTemplate<String, Object> redisTemplate;

    public RedisLuaService(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    public String useLuaScript() {
        // 定義 Lua 腳本字符串
        String luaScript = """
                local key1 = KEYS[1]
                local value1 = ARGV[1]
                redis.call('set', key1, value1)
                local value = redis.call('get', key1)
                redis.call('incr', 'counter')
                return value
                """;
        
        DefaultRedisScript<String> script = new DefaultRedisScript<>();
        script.setScriptText(luaScript);
        script.setResultType(String.class); // 設(shè)置返回值類型

        // 執(zhí)行腳本,傳入 keys 和 args 數(shù)組
        String result = redisTemplate.execute(script, Arrays.asList("myKey"), "myValue");
        return result; // 返回腳本執(zhí)行結(jié)果
    }
}

?使用場景:??

?釋放分布式鎖?:確保判斷鎖標(biāo)識和刪除鎖是一個原子操作。

-- KEYS[1] 是鎖的key,ARGV[1]是當(dāng)前持有者的標(biāo)識
if redis.call("get", KEYS[1]) == ARGV[1] then
    return redis.call("del", KEYS[1])
else
    return 0
end

?秒殺/搶購?:判斷庫存和扣減庫存需要原子性。

?復(fù)雜業(yè)務(wù)邏輯?:需要多個命令的中間結(jié)果進(jìn)行邏輯判斷。

?注意事項:??

  • ?腳本應(yīng)盡量簡單快速?:執(zhí)行 Lua 腳本會阻塞 Redis,長時間運行的腳本會影響性能。
  • ?注意腳本的復(fù)用?:Redis 會緩存編譯過的腳本,可以使用 EVALSHA通過腳本摘要來執(zhí)行,減少帶寬。DefaultRedisScript對象通常會被配置為單例,Spring 會智能地處理 EVALEVALSHA。

如何選擇?

  • ?追求極致性能,批量處理無關(guān)聯(lián)命令?:選擇 ?Pipeline。
  • ?需要保證一系列命令連續(xù)執(zhí)行(簡單原子性),且不介意無回滾?:選擇事務(wù)?(可配合 `WATCH**)。
  • ?需要保證復(fù)雜操作原子性,或操作依賴于中間結(jié)果?:選擇 ?Lua 腳本。

集群環(huán)境特別注意

在 Redis Cluster 模式下,使用事務(wù) (Transaction) 或 Lua 腳本時,?所有涉及的鍵必須在同一個哈希槽 (hash slot) 上,否則會報錯。 可以通過 ?hash tag? 確保不同的鍵分配到同一個槽。

以上就是SpringBoot使用Redis同時執(zhí)行多條命令的實現(xiàn)方法的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot Redis同時執(zhí)行多條命令的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • spark中使用groupByKey進(jìn)行分組排序的示例代碼

    spark中使用groupByKey進(jìn)行分組排序的示例代碼

    這篇文章主要介紹了spark中使用groupByKey進(jìn)行分組排序的實例代碼,本文通過實例代碼給大家講解的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-03-03
  • springboot項目不加端口號也可以訪問項目的方法步驟分析

    springboot項目不加端口號也可以訪問項目的方法步驟分析

    這篇文章主要介紹了springboot項目不加端口號也可以訪問項目的方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-04-04
  • Java中Volatile的作用實例解析

    Java中Volatile的作用實例解析

    本篇文章給大家通過實例分享了Java中Volatile的作用,有興趣的朋友可以學(xué)習(xí)參考下。
    2018-07-07
  • 一文搞懂MyBatis中TypeHandler機制

    一文搞懂MyBatis中TypeHandler機制

    本文介紹了MyBatis中的TypeHandler機制,用于處理Java類型與數(shù)據(jù)庫類型之間的轉(zhuǎn)換,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-08-08
  • Java_異常類(錯誤和異常,兩者的區(qū)別介紹)

    Java_異常類(錯誤和異常,兩者的區(qū)別介紹)

    下面小編就為大家?guī)硪黄狫ava_異常類(錯誤和異常,兩者的區(qū)別介紹) 。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-09-09
  • Graphics2D 寫圖片中文亂碼問題及解決

    Graphics2D 寫圖片中文亂碼問題及解決

    這篇文章主要介紹了Graphics2D 寫圖片中文亂碼問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • JavaWeb組件Servlet使用實例解析

    JavaWeb組件Servlet使用實例解析

    這篇文章主要介紹了JavaWeb組件Servlet使用實例解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-11-11
  • Mybatis執(zhí)行update失敗的解決

    Mybatis執(zhí)行update失敗的解決

    這篇文章主要介紹了Mybatis執(zhí)行update失敗的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • java對double數(shù)組排序示例分享

    java對double數(shù)組排序示例分享

    這篇文章主要介紹了java對double數(shù)組排序示例,代碼簡單,下面我們直接上代碼,需要的朋友可以參考下
    2014-03-03
  • Java實現(xiàn)將png格式圖片轉(zhuǎn)換成jpg格式圖片的方法【測試可用】

    Java實現(xiàn)將png格式圖片轉(zhuǎn)換成jpg格式圖片的方法【測試可用】

    這篇文章主要介紹了Java實現(xiàn)將png格式圖片轉(zhuǎn)換成jpg格式圖片的方法,涉及java文件讀寫及圖形創(chuàng)建等相關(guān)操作技巧,需要的朋友可以參考下
    2018-03-03

最新評論

老河口市| 江北区| 大姚县| 深州市| 根河市| 南投市| 阳西县| 黄梅县| 兰溪市| 牙克石市| 青铜峡市| 汤阴县| 青龙| 安国市| 泗水县| 托克托县| 涞源县| 鄂伦春自治旗| 古浪县| 梨树县| 西华县| 大埔县| 铜川市| 乐都县| 西畴县| 博罗县| 蒙阴县| 乐清市| 建昌县| 历史| 邢台县| 额敏县| 宜兰市| 理塘县| 滨州市| 抚顺县| 盐津县| 瑞昌市| 玛多县| 惠安县| 秦安县|