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

Redis實現(xiàn)高效插入大量數(shù)據(jù)的三種方法

 更新時間:2026年04月13日 10:42:45   作者:身如柳絮隨風(fēng)揚  
在實際開發(fā)中,我們經(jīng)常需要向Redis批量寫入大量數(shù)據(jù),本文將詳細介紹三種基于管道的批量插入方案,文中的示例代碼講解詳細,感興趣的小伙伴可以了解下

一、引言

在實際開發(fā)中,我們經(jīng)常需要向Redis批量寫入大量數(shù)據(jù),例如初始化緩存、導(dǎo)入歷史數(shù)據(jù)、批量更新用戶狀態(tài)等。如果采用普通的SET命令逐條插入,每次命令都需要等待Redis服務(wù)器響應(yīng),會產(chǎn)生大量的網(wǎng)絡(luò)往返時間(RTT,Round-Trip Time),導(dǎo)致寫入效率極低。

為了解決這個問題,Redis提供了管道(Pipeline)技術(shù):客戶端可以將多個命令一次性發(fā)送到服務(wù)器,服務(wù)器依次執(zhí)行后,再批量返回結(jié)果。本文將詳細介紹三種基于管道的批量插入方案:

  1. Redis自帶的redis-cli --pipe(基于原生協(xié)議)
  2. Jedis客戶端的pipelined()方法
  3. Spring Data Redis的RedisTemplate管道批量操作

同時,我們還會剖析管道的工作原理、性能優(yōu)勢以及注意事項,幫助你根據(jù)實際場景選擇最合適的方案。

二、管道(Pipeline)原理簡介

在普通模式下,每個Redis命令的執(zhí)行步驟為:

  1. 客戶端發(fā)送命令 → 服務(wù)器接收 → 執(zhí)行 → 返回結(jié)果 → 客戶端等待。
  2. 多個命令串行執(zhí)行,每個命令都要經(jīng)歷一次RTT。

而在管道模式下:

  • 客戶端將多個命令連續(xù)寫入輸出緩沖區(qū),不等待每個命令的響應(yīng)。
  • 服務(wù)器收到所有命令后,依次執(zhí)行,并將結(jié)果一次性返回給客戶端。

管道模式可以減少網(wǎng)絡(luò)交互次數(shù),尤其適合批量寫入幾十萬甚至上百萬條數(shù)據(jù)的場景。需要注意的是,管道只是將多個命令打包發(fā)送,并不保證原子性(除非配合事務(wù)MULTI/EXEC),服務(wù)器仍然會依次執(zhí)行每個命令。

三、方案一:使用redis-cli --pipe(原生協(xié)議)

Redis自帶的命令行工具redis-cli提供了--pipe(或-pipe)選項,可以非常方便地批量插入數(shù)據(jù)。其底層采用Redis RESP協(xié)議格式,避免命令解析開銷,性能極高。

3.1 準(zhǔn)備數(shù)據(jù)文件

創(chuàng)建一個文本文件data.txt,每行一條Redis命令(采用RESP格式或普通命令格式)。

方式A:普通命令格式(推薦)

SET user:1000 "Alice"
SET user:1001 "Bob"
HSET user:1002 name "Charlie" age 25

注意:普通格式內(nèi)部會被redis-cli自動轉(zhuǎn)換成RESP協(xié)議。

方式B:原生RESP協(xié)議格式(更快但編寫復(fù)雜)

*3\r\n$3\r\nSET\r\n$9\r\nuser:1000\r\n$5\r\nAlice\r\n
*3\r\n$3\r\nSET\r\n$9\r\nuser:1001\r\n$3\r\nBob\r\n

3.2 執(zhí)行批量插入命令

cat data.txt | redis-cli --pipe -h 127.0.0.1 -p 6379 -a yourpassword

執(zhí)行后,會看到類似輸出:

All data transferred. Waiting for the last reply...
Last reply received from server.
errors: 0, replies: 1000000

3.3 優(yōu)點與局限

優(yōu)點局限
無需編寫代碼,適合一次性導(dǎo)入無法動態(tài)生成數(shù)據(jù)(需提前準(zhǔn)備文件)
性能極高(C語言實現(xiàn),原生協(xié)議)錯誤處理較弱,遇到錯誤命令會繼續(xù)執(zhí)行
支持壓縮傳輸(配合--pipe-timeout不支持事務(wù)、Lua等復(fù)雜邏輯

適用場景:數(shù)據(jù)遷移、初始化緩存、從其他數(shù)據(jù)庫導(dǎo)出后批量導(dǎo)入。

四、方案二:Jedis 管道(pipelined)

在Java應(yīng)用中,Jedis是最常用的Redis客戶端之一,它提供了Pipeline對象,可以輕松實現(xiàn)批量操作。

4.1 基礎(chǔ)代碼示例

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;
import redis.clients.jedis.Response;
public class JedisPipelineExample {
    public static void main(String[] args) {
        try (Jedis jedis = new Jedis("localhost", 6379)) {
            // 開啟管道
            Pipeline pipeline = jedis.pipelined();
            // 批量添加命令到管道
            for (int i = 0; i < 100000; i++) {
                pipeline.set("key:" + i, "value:" + i);
            }
            // 執(zhí)行所有命令并獲取結(jié)果
            List<Object> results = pipeline.syncAndReturnAll();
            // 可以檢查每個命令是否成功
            System.out.println("插入完成,共 " + results.size() + " 條");
        }
    }
}

4.2 結(jié)合事務(wù)使用

如果需要保證這批命令的原子性,可以在管道中開啟事務(wù):

pipeline.multi();
for (int i = 0; i < 1000; i++) {
    pipeline.set("key:" + i, "value:" + i);
}
pipeline.exec();
List<Object> results = pipeline.syncAndReturnAll();

4.3 性能對比

模式10萬次SET耗時(本地測試參考)
普通同步模式約 12 ~ 15 秒
管道模式(每次1000條)約 0.8 ~ 1.2 秒

實際性能取決于網(wǎng)絡(luò)延遲、命令復(fù)雜度、管道批量大小。

注意事項

  • 管道中命令數(shù)量不宜過多(建議每批5000~10000條),避免客戶端或服務(wù)器內(nèi)存溢出。
  • syncAndReturnAll()會阻塞直到所有命令返回,適合離線批量導(dǎo)入。
  • 如果只需要執(zhí)行不關(guān)心結(jié)果,可以使用pipeline.sync()。

五、方案三:RedisTemplate 批量保存

Spring Data Redis對管道做了封裝,RedisTemplate提供了executePipelined方法,方便與Spring生態(tài)集成。

5.1 基礎(chǔ)代碼示例

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class RedisBatchService {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    public void batchSetWithPipeline(List<KeyValue> dataList) {
        // executePipelined 會在管道中執(zhí)行回調(diào)內(nèi)的所有操作
        List<Object> results = redisTemplate.executePipelined(
            new SessionCallback<Object>() {
                @Override
                public Object execute(RedisOperations operations) throws DataAccessException {
                    for (KeyValue kv : dataList) {
                        operations.opsForValue().set(kv.getKey(), kv.getValue());
                    }
                    // 返回null即可,實際結(jié)果由executePipelined收集
                    return null;
                }
            }
        );
        // results 包含了每個set命令的執(zhí)行結(jié)果(OK字符串)
        System.out.println("批量插入完成,成功數(shù):" + results.size());
    }
}

5.2 使用opsForList().rightPushAll()等原生批量方法

除了管道,RedisTemplate也提供了一些原生的批量操作命令(如mSet、rightPushAll),這些命令本身就支持多個參數(shù),性能比管道更好,但適用范圍有限。

Map<String, String> map = new HashMap<>();
map.put("key1", "val1");
map.put("key2", "val2");
redisTemplate.opsForValue().multiSet(map);

multiSet(MSET)是原子操作,而管道不是原子的。

5.3 優(yōu)點與局限

優(yōu)點局限
與Spring無縫集成,代碼簡潔相比Jedis管道多了一層封裝,性能稍低(可忽略)
支持連接池、序列化配置回調(diào)內(nèi)部無法使用@Transactional等聲明式事務(wù)
自動處理連接的獲取與釋放結(jié)果類型需要手動轉(zhuǎn)換(因為序列化)

六、性能優(yōu)化建議

合理設(shè)置批量大?。?/strong>根據(jù)網(wǎng)絡(luò)MTU和Redis處理能力,建議每批5000~20000條命令。過小RTT占比高,過大可能阻塞Redis或?qū)е驴蛻舳藘?nèi)存溢出。

關(guān)閉AOF持久化(臨時):如果是在線大量導(dǎo)入,可以臨時關(guān)閉AOF和RDB快照,導(dǎo)入完成后再開啟,減少磁盤IO壓力。

使用UNIX域套接字:如果Redis和客戶端在同一臺機器,配置unixsocket可以進一步提升性能(繞過TCP協(xié)議棧)。

避免在管道中執(zhí)行耗時命令:KEYS *、HGETALL大Hash等,會阻塞Redis并拖慢整個管道。

考慮使用Redis的MSET/MSETNX/HMGET等原生多鍵命令:這些命令是原子的,且只需要一次網(wǎng)絡(luò)交互,比管道更高效。但受限于參數(shù)個數(shù)(通常不超過幾百)。

七、三種方案對比總結(jié)

方案適用語言/環(huán)境易用性性能靈活性推薦場景
redis-cli --pipe命令行、Shell★★★★★★★★★★★★數(shù)據(jù)遷移、初始化導(dǎo)入
Jedis PipelineJava★★★★★★★★★★★★通用Java應(yīng)用批量寫入
RedisTemplate PipelineSpring Boot★★★★★★★★★★★★Spring生態(tài)項目,需要與業(yè)務(wù)邏輯混合

性能星級為相對比較,實際差異與批次大小、網(wǎng)絡(luò)環(huán)境有關(guān)。

八、常見問題(FAQ)

Q1:管道和事務(wù)有什么區(qū)別?

管道只負責(zé)打包命令減少RTT,不保證原子性;事務(wù)(MULTI/EXEC)可以保證命令序列不被其他客戶端打斷,但也不能回滾。兩者可以結(jié)合使用。

Q2:管道模式會不會丟失數(shù)據(jù)?

不會。每個命令執(zhí)行成功后服務(wù)器仍會返回結(jié)果,只是客戶端批量接收。但如果網(wǎng)絡(luò)斷開,已發(fā)送但未執(zhí)行完的命令可能丟失(需要重試機制)。

Q3:使用redis-cli --pipe時如何生成RESP格式文件?

可以使用redis-cli --pipe自帶的普通命令格式,或者用腳本轉(zhuǎn)換。例如:

echo -e "SET key1 value1\nSET key2 value2" | redis-cli --pipe

Q4:管道中一個命令出錯,會影響其他命令嗎?

不會。管道中的命令相互獨立,一條失?。ㄈ珙愋湾e誤)不會影響后續(xù)命令的執(zhí)行。

九、完整實戰(zhàn):百萬數(shù)據(jù)插入對比

下面給出一個使用Jedis管道插入100萬條數(shù)據(jù)的示例,并統(tǒng)計耗時。

public class PipelineBenchmark {
    public static void main(String[] args) {
        Jedis jedis = new Jedis("localhost");
        jedis.flushAll(); // 清空測試環(huán)境
        long start = System.currentTimeMillis();
        Pipeline p = jedis.pipelined();
        for (int i = 0; i < 1_000_000; i++) {
            p.set("pipeline:" + i, "data");
            if (i % 10000 == 0) {
                p.sync(); // 每1萬條同步一次,防止緩沖區(qū)過大
            }
        }
        p.sync(); // 最后同步
        long end = System.currentTimeMillis();
        System.out.println("管道模式耗時: " + (end - start) + " ms");
        // 普通模式對比(少量數(shù)據(jù)測試,避免太慢)
        jedis.close();
    }
}

在本地開發(fā)機(Redis 7.0,千兆網(wǎng)絡(luò))測試結(jié)果:

  • 普通模式(1000條):~1200ms
  • 管道模式(1000條):~45ms
  • 管道模式(100萬條,每批1萬):~2.8秒

可見管道模式可以輕松達到普通模式的20~50倍性能提升。

十、總結(jié)

  • 管道是Redis批量插入數(shù)據(jù)的核心手段,通過減少RTT極大提升寫入吞吐量。
  • 根據(jù)使用場景選擇合適方案:
    • 一次性導(dǎo)入用redis-cli --pipe;
    • Java應(yīng)用內(nèi)用Jedis Pipeline;
    • Spring項目用RedisTemplate.executePipelined。
  • 注意控制批次大小、避免長耗時命令、合理配置持久化策略。
  • 如果需要原子性,考慮管道+事務(wù),或直接使用Lua腳本。

到此這篇關(guān)于Redis實現(xiàn)高效插入大量數(shù)據(jù)的三種方法的文章就介紹到這了,更多相關(guān)Redis插入大量數(shù)據(jù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • redis實現(xiàn)簡單隊列

    redis實現(xiàn)簡單隊列

    這篇文章主要為大家詳細介紹了redis實現(xiàn)簡單隊列的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-10-10
  • phpredis提高消息隊列的實時性方法(推薦)

    phpredis提高消息隊列的實時性方法(推薦)

    下面小編就為大家?guī)硪黄猵hpredis提高消息隊列的實時性方法(推薦)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-12-12
  • Redis+AOP+自定義注解實現(xiàn)限流

    Redis+AOP+自定義注解實現(xiàn)限流

    這篇文章主要為大家詳細介紹了如何利用Redis+AOP+自定義注解實現(xiàn)個小功能:自定義攔截器限制訪問次數(shù),也就是限流,感興趣的可以了解一下
    2022-06-06
  • redis性能優(yōu)化之生產(chǎn)中實際遇到的問題及排查總結(jié)

    redis性能優(yōu)化之生產(chǎn)中實際遇到的問題及排查總結(jié)

    這篇文章主要介紹了redis性能優(yōu)化之生產(chǎn)中實際遇到的問題及排查總結(jié),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • Redis exists命令bug分析(案例詳解)

    Redis exists命令bug分析(案例詳解)

    Redis EXISTS 命令用于檢查給定 key 是否存在,本文重點給大家介紹Redis exists命令bug分析,感興趣的朋友跟隨小編一起看看吧
    2022-02-02
  • 使用Ruby腳本部署Redis Cluster集群步驟講解

    使用Ruby腳本部署Redis Cluster集群步驟講解

    今天小編就為大家分享一篇關(guān)于使用Ruby腳本部署Redis Cluster集群步驟講解,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • Redis中的數(shù)據(jù)過期策略詳解

    Redis中的數(shù)據(jù)過期策略詳解

    這篇文章主要介紹了Redis中的數(shù)據(jù)過期策略,文中通過示例代碼介紹的很詳細,相信對大家的理解和學(xué)習(xí)具有一定的參考借鑒價值,有需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-01-01
  • Redis分布式鎖升級版RedLock及SpringBoot實現(xiàn)方法

    Redis分布式鎖升級版RedLock及SpringBoot實現(xiàn)方法

    這篇文章主要介紹了Redis分布式鎖升級版RedLock及SpringBoot實現(xiàn),本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-02-02
  • 如何使用redis的setnx實現(xiàn)分布式鎖

    如何使用redis的setnx實現(xiàn)分布式鎖

    Redis Setnx(SET if Not eXists) 命令在指定的 key 不存在時,為 key 設(shè)置指定的值,這篇文章主要介紹了使用redis的setnx實現(xiàn)分布式鎖,需要的朋友可以參考下
    2024-06-06
  • Redis優(yōu)惠券秒殺解決方案

    Redis優(yōu)惠券秒殺解決方案

    這篇文章主要介紹了Redis解決優(yōu)惠券秒殺應(yīng)用案例,本文先講了搶購問題,指出其中會出現(xiàn)的多線程問題,提出解決方案采用悲觀鎖和樂觀鎖兩種方式進行實現(xiàn),然后發(fā)現(xiàn)在搶購過程中容易出現(xiàn)一人多單現(xiàn)象,需要的朋友可以參考下
    2022-12-12

最新評論

防城港市| 邓州市| 沙坪坝区| 盱眙县| 唐山市| 玛多县| 阳高县| 乐昌市| 蓝山县| 墨竹工卡县| 千阳县| 阿勒泰市| 读书| 黑河市| 灵石县| 商南县| 仁怀市| 那曲县| 龙海市| 沁源县| 凯里市| 辽宁省| 黑山县| 揭西县| 宁化县| 广州市| 安塞县| 寿光市| 启东市| 梅州市| 武城县| 刚察县| 丹巴县| 微山县| 永泰县| 嘉善县| 汾阳市| 眉山市| 霍邱县| 左贡县| 郯城县|