欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Redis中管道操作pipeline的實(shí)現(xiàn)

 更新時(shí)間:2025年03月24日 09:57:55   作者:煙火纏過客  
RedisPipeline是一種優(yōu)化客戶端與服務(wù)器通信的技術(shù),通過批量發(fā)送和接收命令減少網(wǎng)絡(luò)往返次數(shù),提高命令執(zhí)行效率,本文就來介紹一下Redis中管道操作pipeline的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下

什么是pipeline

在 Redis 中,Pipeline(管道)是一種客戶端與服務(wù)器間通信的優(yōu)化機(jī)制,旨在減少網(wǎng)絡(luò)往返時(shí)間和提高命令執(zhí)行效率。以下是 Redis Pipeline 的具體定義和特點(diǎn):

1.批量發(fā)送與接收:

  • 使用 Pipeline 時(shí),客戶端不再逐條發(fā)送命令,而是將多個(gè)命令一次性打包成一個(gè)請(qǐng)求包發(fā)送給 Redis 服務(wù)器。相應(yīng)地,服務(wù)器在接收到這個(gè)請(qǐng)求包后,不是立即返回每條命令的執(zhí)行結(jié)果,而是先將所有命令依次執(zhí)行完畢,然后將所有結(jié)果打包成一個(gè)響應(yīng)包返回給客戶端。
  • 這種做法顯著減少了客戶端與服務(wù)器之間網(wǎng)絡(luò)通信的次數(shù),尤其是對(duì)于需要執(zhí)行大量命令的場景,能夠極大地降低網(wǎng)絡(luò)延遲帶來的影響。

2.異步執(zhí)行

  • 盡管 Redis Pipeline 中的所有命令是在服務(wù)器端按順序執(zhí)行的,但由于客戶端與服務(wù)器之間的通信是批量進(jìn)行的,客戶端可以在發(fā)送完一批命令后立刻開始處理其他任務(wù),而無需等待每個(gè)命令的單獨(dú)響應(yīng)。這種異步處理方式可以更好地利用客戶端的計(jì)算資源,提高整體應(yīng)用程序的并發(fā)性能。

3.命令隔離

  • 在 Pipeline 中,每個(gè)命令的執(zhí)行互不影響,即一個(gè)命令的執(zhí)行結(jié)果不會(huì)影響后續(xù)命令的執(zhí)行。這意味著即使某條命令執(zhí)行失敗,也不會(huì)阻止后續(xù)命令的執(zhí)行??蛻舳嗽诮馕鲰憫?yīng)包時(shí),可以根據(jù)響應(yīng)內(nèi)容判斷每條命令的執(zhí)行結(jié)果。

4.使用場景

  • Pipeline 主要適用于需要對(duì) Redis 執(zhí)行大量命令的操作,如數(shù)據(jù)批量導(dǎo)入、大規(guī)模數(shù)據(jù)更新、復(fù)雜查詢等。這些操作若不使用 Pipeline,可能會(huì)因?yàn)榫W(wǎng)絡(luò)延遲導(dǎo)致整體執(zhí)行時(shí)間顯著增加。
  • 對(duì)于涉及事務(wù)(transaction)的操作,雖然也可以使用 Pipeline 來打包命令,但需要注意的是,Pipeline 不提供事務(wù)的原子性和一致性保證。如果需要確保一組命令作為一個(gè)原子單位執(zhí)行,應(yīng)使用 Redis 的 MULTI/EXEC 命令來開啟事務(wù)。

5.注意事項(xiàng)

  • 雖然 Pipeline 能夠顯著提高命令執(zhí)行效率,但一次性發(fā)送的命令數(shù)量不宜過大,否則可能導(dǎo)致數(shù)據(jù)包過大,增加網(wǎng)絡(luò)傳輸壓力,甚至超過 Redis 服務(wù)器或客戶端的緩沖區(qū)限制,引發(fā)錯(cuò)誤。合理的命令打包大小需要根據(jù)實(shí)際環(huán)境和網(wǎng)絡(luò)狀況進(jìn)行調(diào)整
  • 在使用 Pipeline 時(shí),由于命令的響應(yīng)是延遲返回的,客戶端需要做好錯(cuò)誤處理和重試策略,尤其是在網(wǎng)絡(luò)不穩(wěn)定或服務(wù)器負(fù)載較高的情況下。

總結(jié)來說,Redis Pipeline 是一種客戶端與服務(wù)器間高效通信的技術(shù),通過批量發(fā)送和接收命令,減少網(wǎng)絡(luò)往返次數(shù),提高命令執(zhí)行效率,尤其適用于大量命令操作的場景。在使用時(shí)需注意命令打包大小的控制以及錯(cuò)誤處理。

場景一:我要向redis新增大批量的數(shù)據(jù)

Redis Pipeline允許一次性發(fā)送多個(gè)命令到Redis服務(wù)器,而無需等待每個(gè)命令的響應(yīng),顯著減少了網(wǎng)絡(luò)往返時(shí)間和潛在的延遲。在Spring Boot應(yīng)用中,可以使用RedisTemplate的executePipelined()方法實(shí)現(xiàn):

@Autowired
private StringRedisTemplate redisTemplate

public void batchInsertUsersWithPipeline(List<User> users, String keyPrefix, long ttlSeconds) {
    redisTemplate.executePipelined((RedisCallback<Object>) connection -> {
        for (User user : users) {
            String key = generateKey(keyPrefix, user.getId());
            String value = objectMapper.writeValueAsString(user);

            connection.setEx(key.getBytes(), (int) ttlSeconds, value.getBytes());
        }
        return null;
    });
}    

分批處理

盡管Pipeline提高了效率,但對(duì)于千萬級(jí)數(shù)據(jù),一次性發(fā)送所有命令可能導(dǎo)致內(nèi)存溢出或網(wǎng)絡(luò)阻塞。因此,建議將數(shù)據(jù)分批處理,每批包含適量的記錄(如1000條),逐批發(fā)送至Redis:

public void insertUsersInBatches(List<User> users, String keyPrefix, long ttlSeconds, int batchSize) {
    int start = 0;
    while (start < users.size()) {
        int end = Math.min(start + batchSize, users.size());
        List<User> batch = users.subList(start, end);
        batchInsertUsersWithPipeline(batch, keyPrefix, ttlSeconds);
        start = end;
    }
}

batchInsertUsersWithPipeline方法利用Redis Pipeline機(jī)制發(fā)送批量命令,可以在一定程度上提高插入操作的并發(fā)性,減少網(wǎng)絡(luò)往返時(shí)間和整體耗時(shí)。然而,Pipeline本身并不能嚴(yán)格保證所有命令同時(shí)成功或失敗,其主要特性如下:

1.原子性:

  • Redis命令在Pipeline內(nèi)部是原子性的,即單個(gè)命令的執(zhí)行不會(huì)被其他命令中斷。
  • 注意:這并不意味著整個(gè)Pipeline的所有命令作為一個(gè)整體具有原子性。Pipeline中的命令仍然是依次執(zhí)行的,只是客戶端與服務(wù)器之間的通信過程被優(yōu)化了。

2.響應(yīng)順序

  • Redis服務(wù)器會(huì)按接收到命令的順序返回結(jié)果。即使在Pipeline中并發(fā)發(fā)送多個(gè)命令,客戶端接收到的響應(yīng)也將按照命令發(fā)送的順序排列。

3.故障處理

  • 如果Pipeline中的某個(gè)命令執(zhí)行失?。ㄈ缯Z法錯(cuò)誤、key不存在等),后續(xù)命令通常仍會(huì)繼續(xù)執(zhí)行。
  • 錯(cuò)誤信息會(huì)包含在相應(yīng)命令的響應(yīng)中,客戶端可以根據(jù)這些信息判斷哪些命令執(zhí)行成功,哪些失敗。

綜上所述,batchInsertUsersWithPipeline方法不能嚴(yán)格保證所有命令同時(shí)成功或失敗。在實(shí)際使用中,如果需要確保一批數(shù)據(jù)要么全部成功插入,要么全部失敗回滾,可以采取以下策略:

事務(wù)( MULTI/EXEC/DISCARD ):

  • redis提供了事務(wù)(Transaction)功能,通過MULTI、EXEC和DISCARD等命令,可以將一組命令打包在一起執(zhí)行,只有當(dāng)所有命令都能成功執(zhí)行時(shí),整個(gè)事務(wù)才會(huì)提交;否則,任何命令失敗都將導(dǎo)致整個(gè)事務(wù)回滾。
  • 盡管Redis事務(wù)不支持回滾到某一特定狀態(tài)(即不保證隔離性),但在批量插入場景下,它可以滿足“全有或全無”的要求。

Lua腳本:

  • 使用Lua腳本編寫批量插入邏輯,腳本在Redis服務(wù)器端執(zhí)行,具備原子性。即使在網(wǎng)絡(luò)中斷或服務(wù)器重啟等異常情況下,腳本要么完全執(zhí)行,要么完全不執(zhí)行,不會(huì)出現(xiàn)部分成功部分失敗的情況。

batchInsertUsersWithPipeline方法中的connection中各個(gè)方法的區(qū)別是什么?

1.connection.setEx(key.getBytes(), (int) ttlSeconds, value.getBytes());

這一行調(diào)用了RedisConnection的setEx方法,用于設(shè)置一個(gè)帶有過期時(shí)間(Time To Live,TTL)的鍵值對(duì)。參數(shù)說明如下:

  • key.getBytes(): 將給定的鍵(字符串)轉(zhuǎn)換為字節(jié)數(shù)組,這是Redis底層通信協(xié)議所要求的格式。
  • (int) ttlSeconds: 將過期時(shí)間(以秒為單位)轉(zhuǎn)換為整數(shù)類型,表示鍵值對(duì)在指定秒數(shù)后自動(dòng)過期并被刪除。
  • value.getBytes(): 同樣將給定的值(用戶對(duì)象序列化后的JSON字符串)轉(zhuǎn)換為字節(jié)數(shù)組

setEx方法確保在設(shè)置鍵值對(duì)的同時(shí)為其設(shè)定一個(gè)過期時(shí)間。如果鍵已經(jīng)存在,該方法會(huì)更新鍵的值和過期時(shí)間。這個(gè)操作在Pipeline模式下是原子的,即在同一時(shí)刻只有一個(gè)setEx命令被執(zhí)行。

2.connection.multi(); 和 connection.exec();

這兩個(gè)方法涉及Redis的事務(wù)(Transaction)功能。在Pipeline模式下,由于我們希望保持較高的性能,一般不會(huì)使用這兩個(gè)方法。但如果確實(shí)需要保證一批命令的原子性,可以使用如下方式:

  • connection.multi(): 開啟一個(gè)事務(wù)塊,后續(xù)的所有命令都會(huì)被放入這個(gè)事務(wù)中,直到調(diào)用exec方法。在Pipeline模式下,調(diào)用multi方法可能會(huì)破壞原有的性能優(yōu)化效果。
  • connection.exec(): 提交并執(zhí)行事務(wù)中的所有命令。如果事務(wù)中有任何一個(gè)命令執(zhí)行失敗,其他命令也會(huì)被取消執(zhí)行,整個(gè)事務(wù)被視為失敗。

在您的batchInsertUsersWithPipeline方法中并沒有使用multi和exec,因?yàn)镻ipeline已經(jīng)提供了高效的批量執(zhí)行機(jī)制,而且這里的目的是提高插入性能,而不是實(shí)現(xiàn)嚴(yán)格的事務(wù)行為。

綜上所述,batchInsertUsersWithPipeline方法中直接使用了setEx方法,利用Pipeline來高效地批量插入帶有過期時(shí)間的鍵值對(duì)。如果需要實(shí)現(xiàn)更嚴(yán)格的事務(wù)控制,應(yīng)考慮使用Redis的事務(wù)(MULTI/EXEC)或Lua腳本,但這通常會(huì)犧牲一定的性能,并且與Pipeline機(jī)制不完全兼容。在實(shí)際應(yīng)用場景中,應(yīng)根據(jù)業(yè)務(wù)需求權(quán)衡選擇合適的操作方式。

3.connection.set()和connection.setNx有什么區(qū)別

connection.set() 和 connection.setNx() 都是Redis的鍵值對(duì)設(shè)置方法,它們的主要區(qū)別在于是否存在條件以及對(duì)已有鍵的處理方式:

1.connection.set(key, value)

這是最基礎(chǔ)的設(shè)置鍵值對(duì)的方法,無論鍵是否存在,都會(huì)直接覆蓋(或創(chuàng)建)對(duì)應(yīng)的鍵值對(duì)。參數(shù)說明如下:

  • key: 要設(shè)置的鍵。
  • value: 要關(guān)聯(lián)的值。

行為特點(diǎn):

  • 無條件設(shè)置:不論鍵是否存在,都會(huì)執(zhí)行設(shè)置操作。
  • 覆蓋已有鍵:如果鍵已存在,其原有值會(huì)被新的值覆蓋。
  • 創(chuàng)建新鍵:如果鍵不存在,會(huì)創(chuàng)建一個(gè)新的鍵值對(duì)。

2.connection.setNx(key, value)

這是帶有條件的設(shè)置鍵值對(duì)方法,僅當(dāng)鍵不存在時(shí)才會(huì)設(shè)置鍵值對(duì)。參數(shù)與set()相同:

  • key: 要設(shè)置的鍵
  • value: 要關(guān)聯(lián)的值。

行為特點(diǎn)

  • 有條件設(shè)置:僅在鍵不存在的情況下執(zhí)行設(shè)置操作。
  • 不覆蓋已有鍵:如果鍵已存在,該方法不會(huì)有任何動(dòng)作,既不會(huì)改變鍵的值,也不會(huì)拋出錯(cuò)誤。
  • 創(chuàng)建新鍵:如果鍵不存在,會(huì)創(chuàng)建一個(gè)新的鍵值對(duì)。

總結(jié)來說,connection.set()無條件地設(shè)置或更新鍵值對(duì),而connection.setNx()則是在鍵不存在時(shí)才設(shè)置鍵值對(duì),如果鍵已存在,則不會(huì)執(zhí)行任何操作。前者適用于常規(guī)的鍵值更新或插入,后者常用于實(shí)現(xiàn)鎖機(jī)制、唯一性檢查等場景,確保某個(gè)鍵的值只在首次設(shè)置時(shí)有效。在您的batchInsertUsersWithPipeline方法中,由于目標(biāo)是批量插入新數(shù)據(jù),所以使用了setEx方法(帶有過期時(shí)間的set),確保每個(gè)用戶數(shù)據(jù)作為一個(gè)新的鍵值對(duì)被添加到Redis中。如果您需要在插入前檢查鍵的唯一性,可以考慮使用setNx方法。不過,對(duì)于批量插入場景,通常假設(shè)數(shù)據(jù)是新的且鍵不存在,因此直接使用setEx更為常見。

場景二:大批量刪除redis中的數(shù)據(jù)

public void batchDeleteKeysWithPipeline(List<String> keys) {
    redisTemplate.executePipelined((RedisCallback<Object>) connection -> {
        for (String key : keys) {
            connection.del(key.getBytes());
        }
        return null;
    });
}
  • redisTemplate.executePipelined() 方法創(chuàng)建了一個(gè)Pipeline上下文,允許您在回調(diào)函數(shù)內(nèi)發(fā)送多個(gè)命令而不等待響應(yīng)。
  • 回調(diào)函數(shù)遍歷要?jiǎng)h除的鍵列表,對(duì)每個(gè)鍵調(diào)用 connection.del(key.getBytes())。del 方法用于刪除指定鍵,將鍵名轉(zhuǎn)換為字節(jié)數(shù)組后傳遞給Redis。
  • 所有del命令在Pipeline中被連續(xù)發(fā)送至Redis服務(wù)器,期間客戶端不會(huì)等待任何響應(yīng)。
  • 當(dāng)回調(diào)函數(shù)執(zhí)行完畢并返回時(shí),Pipeline中的命令會(huì)被一次性發(fā)送至Redis,并接收所有命令的響應(yīng)。由于命令是在一次網(wǎng)絡(luò)往返中批量發(fā)送的,因此比單獨(dú)執(zhí)行每個(gè)刪除命令效率更高。

場景三:刪除redis中千萬級(jí)別的數(shù)據(jù)

1.批量刪除策略

  • 使用 SCAN 命令結(jié)合 DEL 命令實(shí)現(xiàn)批量刪除。

    SCAN 命令用于增量式地迭代數(shù)據(jù)集,避免一次性獲取所有鍵導(dǎo)致內(nèi)存溢出。

    DEL 命令用于刪除單個(gè)或多個(gè)鍵。

2.并行處理

  • 利用多線程或異步任務(wù)將批量刪除操作分散到多個(gè)工作線程中,提高刪除效率。

3.Redis 客戶端優(yōu)化:

  • 選擇高性能、支持批量操作和管道(Pipeline)功能的 Redis 客戶端庫,如 Jedis 或 Lettuce。

4.監(jiān)控與故障恢復(fù):

  • 在執(zhí)行大規(guī)模刪除操作時(shí),密切關(guān)注 Redis 的性能指標(biāo)(如 CPU、內(nèi)存、網(wǎng)絡(luò)帶寬等)以及客戶端程序的狀態(tài)。
  • 準(zhǔn)備應(yīng)對(duì)可能的異常情況,如斷連重試、數(shù)據(jù)一致性檢查等。

基于Jedis客戶端實(shí)現(xiàn)

import redis.clients.jedis.Jedis;
import redis.clients.jedis.ScanParams;
import redis.clients.jedis.ScanResult;

public class RedisDataDeleter {

    private static final int SCAN_BATCH_SIZE = 1000; // 可根據(jù)實(shí)際情況調(diào)整
    private static final String MATCH_PATTERN = "*"; // 匹配所有鍵

    public void deleteAllKeys(Jedis jedis) {
        ScanParams scanParams = new ScanParams().count(SCAN_BATCH_SIZE).match(MATCH_PATTERN);

        String cursor = "0";
        while (true) {
            ScanResult<String> scanResult = jedis.scan(cursor, scanParams);
            cursor = scanResult.getCursor();

            List<String> keysToDelete = scanResult.getResult();
            if (!keysToDelete.isEmpty()) {
                // 使用 Pipeline 批量刪除鍵
                Pipeline pipeline = jedis.pipelined();
                for (String key : keysToDelete) {
                    pipeline.del(key);
                }
                pipeline.sync(); // 執(zhí)行批量命令
            }

            if ("0".equals(cursor)) {
                break; // 掃描完成
            }
        }
    }
}

注意

  • 請(qǐng)確保在生產(chǎn)環(huán)境中適當(dāng)調(diào)整 SCAN_BATCH_SIZE 參數(shù),使其既能充分利用系統(tǒng)資源,又不會(huì)對(duì) Redis 服務(wù)器造成過大壓力。
  • 在執(zhí)行大規(guī)模刪除操作前,最好先備份重要數(shù)據(jù),并在非高峰期進(jìn)行操作,以減少對(duì)業(yè)務(wù)的影響。

如果條件允許,建議升級(jí)到 Redis 6.x 版本,并啟用 activedefrag 配置項(xiàng),有助于在刪除大量數(shù)據(jù)后及時(shí)進(jìn)行碎片整理,保持 Redis 內(nèi)存的高效利用。同時(shí),監(jiān)控 Redis 的內(nèi)存使用情況和碎片率,必要時(shí)手動(dòng)觸發(fā) BGREWRITEAOF 或 BGSAVE 操作。

maven

<dependencies>
    <!-- ... 其他依賴 ... -->
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>3.7.0</version> <!-- 根據(jù)實(shí)際版本號(hào)調(diào)整 -->
    </dependency>
</dependencies>

jedis連接池配置

spring.redis.host=192.168.1.100
spring.redis.port=6379
spring.redis.password=mysecretpassword  # 如果有密碼,請(qǐng)?zhí)顚?

# Jedis 連接池配置
spring.redis.jedis.pool.max-active=10
spring.redis.jedis.pool.max-idle=6
spring.redis.jedis.pool.min-idle=2
spring.redis.jedis.pool.max-wait=2000ms

jedisConfig

@Configuration
public class JedisConfig {

    @Value("${spring.redis.host}")
    private String host;

    @Value("${spring.redis.port}")
    private int port;

    @Value("${spring.redis.password}")
    private String password;

    @Bean
    public JedisPool jedisPool() {
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxTotal(Integer.parseInt(env.getProperty("spring.redis.jedis.pool.max-active")));
        poolConfig.setMaxIdle(Integer.parseInt(env.getProperty("spring.redis.jedis.pool.max-idle")));
        poolConfig.setMinIdle(Integer.parseInt(env.getProperty("spring.redis.jedis.pool.min-idle")));
        poolConfig.setMaxWaitMillis(Long.parseLong(env.getProperty("spring.redis.jedis.pool.max-wait")));

        return new JedisPool(poolConfig, host, port, Protocol.DEFAULT_TIMEOUT, password);
    }
}

實(shí)現(xiàn) Redis 數(shù)據(jù)刪除服務(wù)

@Service
public class RedisDataDeleterService {

    @Autowired
    private JedisPool jedisPool;

    public void deleteAllKeys() {
        try (Jedis jedis = jedisPool.getResource()) {
            ScanParams scanParams = new ScanParams().match("*").count(1000);

            String cursor = "0";
            while (true) {
                ScanResult<String> scanResult = jedis.scan(cursor, scanParams);
                cursor = scanResult.getCursor();

                List<String> keysToDelete = scanResult.getResult();
                if (!keysToDelete.isEmpty()) {
                    Pipeline pipeline = jedis.pipelined();
                    for (String key : keysToDelete) {
                        pipeline.del(key);
                    }
                    pipeline.sync();
                }

                if ("0".equals(cursor)) {
                    break;
                }
            }
        }
    }
}

調(diào)用刪除服務(wù)

@RestController
@RequestMapping("/redis")
public class RedisController {

    @Autowired
    private RedisDataDeleterService redisDataDeleterService;

    @GetMapping("/delete-all-keys")
    public ResponseEntity<?> deleteAllKeys() {
        redisDataDeleterService.deleteAllKeys();
        return ResponseEntity.ok().build();
    }
}

基于Lettuce

maven

<dependencies>
    <!-- ... 其他依賴 ... -->
    <dependency>
        <groupId>io.lettuce</groupId>
        <artifactId>lettuce-core</artifactId>
        <version>6.2.?</version> <!-- 根據(jù)實(shí)際版本號(hào)調(diào)整 -->
    </dependency>
</dependencies>

配置Lettuce

Spring Boot 自動(dòng)配置會(huì)為 Lettuce 提供連接池支持。在 application.properties 或 application.yml 中配置 Redis 連接信息:

spring.redis.host=192.168.1.100
spring.redis.port=6379
spring.redis.password=mysecretpassword  # 如果有密碼,請(qǐng)?zhí)顚?

使用 Lettuce 客戶端執(zhí)行批量刪除操作:

@Service
public class RedisDataDeleterService {

    @Autowired
    private RedisConnectionFactory connectionFactory;

    public void deleteAllKeys() {
        RedisAsyncCommands<String, String> asyncCommands = connectionFactory.getConnection().async();

        ScanArgs scanArgs = ScanArgs.Builder.matches("*").count(1000);
        RedisFuture<ScanResult<String>> scanFuture = asyncCommands.scan(ScanCursor.INITIAL, scanArgs);

        AtomicBoolean isRunning = new AtomicBoolean(true);
        AtomicReference<ScanCursor> lastCursor = new AtomicReference<>(ScanCursor.INITIAL);

        // 異步處理掃描結(jié)果
        scanFuture.thenAccept(scanResult -> {
            lastCursor.set(scanResult.getCursor());
            List<String> keysToDelete = scanResult.getKeys();
            if (!keysToDelete.isEmpty()) {
                RedisFuture<Long> delFuture = asyncCommands.del(keysToDelete.toArray(new String[0]));
                delFuture.thenAccept(count -> {
                    if (isRunning.get()) {
                        // 如果仍在運(yùn)行,繼續(xù)掃描
                        deleteAllKeysRecursive(asyncCommands, scanArgs, lastCursor, isRunning);
                    }
                });
            } else {
                isRunning.set(false);
            }
        });

        // 設(shè)置超時(shí)時(shí)間(可根據(jù)實(shí)際情況調(diào)整)
        CompletableFuture.runAsync(() -> {
            try {
                Thread.sleep(120000); // 2分鐘超時(shí)
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            isRunning.set(false);
        });
    }

    private void deleteAllKeysRecursive(RedisAsyncCommands<String, String> asyncCommands,
                                       ScanArgs scanArgs,
                                       AtomicReference<ScanCursor> lastCursor,
                                       AtomicBoolean isRunning) {
        if (isRunning.get()) {
            asyncCommands.scan(lastCursor.get(), scanArgs).thenAccept(scanResult -> {
                lastCursor.set(scanResult.getCursor());
                List<String> keysToDelete = scanResult.getKeys();
                if (!keysToDelete.isEmpty()) {
                    asyncCommands.del(keysToDelete.toArray(new String[0])).thenAccept(count -> {
                        if (isRunning.get()) {
                            deleteAllKeysRecursive(asyncCommands, scanArgs, lastCursor, isRunning);
                        }
                    });
                } else {
                    isRunning.set(false);
                }
            });
        }
    }
}

調(diào)用

@RestController
@RequestMapping("/redis")
public class RedisController {

    @Autowired
    private RedisDataDeleterService redisDataDeleterService;

    @GetMapping("/delete-all-keys")
    public ResponseEntity<?> deleteAllKeys() {
        redisDataDeleterService.deleteAllKeys();
        return ResponseEntity.ok().build();
    }
}

到此這篇關(guān)于Redis中管道操作pipeline的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Redis管道操作pipeline內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Redis三種集群模式詳解

    Redis三種集群模式詳解

    redis有三種集群模式,其中主從是最常見的模式,今天通過本文給大家分享Redis三種集群模式介紹,感興趣的朋友一起看看吧
    2021-10-10
  • Redis連接池配置方式

    Redis連接池配置方式

    文章介紹了Redis連接池的配置方法,包括與數(shù)據(jù)庫連接時(shí)引入連接池的必要性、Java中使用Redis連接池的示例、jar包準(zhǔn)備、編寫配置代碼以及連接池參數(shù)的設(shè)置
    2024-12-12
  • Redis的Expire與Setex區(qū)別說明

    Redis的Expire與Setex區(qū)別說明

    這篇文章主要介紹了Redis的Expire與Setex區(qū)別說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • redis大key和大value的危害及解決

    redis大key和大value的危害及解決

    本文主要介紹了redis大key和大value的危害及解決
    2024-03-03
  • redis的兩種持久化方式RDB和AOF解讀

    redis的兩種持久化方式RDB和AOF解讀

    Redis提供了RDB和AOF兩種持久化方式,RDB是快照持久化,通過配置文件中的save指令開啟和配置,可以設(shè)置觸發(fā)快照的條件,AOF是日志持久化,每次寫操作都會(huì)追加到AOF文件中,并可以通過配置文件設(shè)置持久化頻率和重寫策略,RDB和AOF可以結(jié)合使用,以提高數(shù)據(jù)的安全性和恢復(fù)效率
    2025-03-03
  • Redis?搭建主從集群的操作指南

    Redis?搭建主從集群的操作指南

    單節(jié)點(diǎn)的?Redis?并發(fā)能力有限,要進(jìn)一步提高?Redis?的并發(fā)能力,就需要搭建主從集群,實(shí)現(xiàn)讀寫分離,這篇文章主要給大家介紹了Redis搭建主從集群的操作指南,需要的朋友可以參考下
    2023-08-08
  • 遠(yuǎn)程連接阿里云服務(wù)器上的redis報(bào)錯(cuò)的問題解決

    遠(yuǎn)程連接阿里云服務(wù)器上的redis報(bào)錯(cuò)的問題解決

    本文主要介紹了遠(yuǎn)程連接阿里云服務(wù)器上的redis報(bào)錯(cuò)的問題,出現(xiàn)?Redis Client On Error: Error: connect ECONNREFUSED 47.100.XXX.XX:6379?錯(cuò)誤,下面就來介紹一下解決方法,感興趣的可以了解一下
    2025-04-04
  • Redis序列化存儲(chǔ)及日期格式的問題處理

    Redis序列化存儲(chǔ)及日期格式的問題處理

    這篇文章主要介紹了Redis序列化存儲(chǔ)及其日期格式的問題處理方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • 解析高可用Redis服務(wù)架構(gòu)分析與搭建方案

    解析高可用Redis服務(wù)架構(gòu)分析與搭建方案

    我們按照由簡至繁的步驟,搭建一個(gè)最小型的高可用的Redis服務(wù)。 本文通過四種方案給大家介紹包含每種方案的優(yōu)缺點(diǎn)及詳細(xì)解說,具體內(nèi)容詳情跟隨小編一起看看吧
    2021-06-06
  • Redis鎖的過期時(shí)間小于業(yè)務(wù)的執(zhí)行時(shí)間如何續(xù)期

    Redis鎖的過期時(shí)間小于業(yè)務(wù)的執(zhí)行時(shí)間如何續(xù)期

    本文主要介紹了Redis鎖的過期時(shí)間小于業(yè)務(wù)的執(zhí)行時(shí)間如何續(xù)期,Redisson它能給Redis分布式鎖實(shí)現(xiàn)過期時(shí)間自動(dòng)續(xù)期,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-05-05

最新評(píng)論