進階 Redis 技術與應用

程序员胡大圣發表於2024-05-08

目錄

1. Redis 高階資料結構

  • 1.1.HyperLogLog
  • 1.2.Bitmaps
  • 1.3.Geospatial 資料
  • 1.4.Pub/Sub(釋出/訂閱)

2. Redis 事務與持久化

  • 2.1.Redis 事務簡介
  • 2.2.持久化方式:RDB 和 AOF
  • 2.3.配置和管理持久化

3. Redis 高階功能

  • 3.1.分散式鎖
  • 3.2.Lua 指令碼
  • 3.3.客戶端連線和連線池
  • 3.4.記憶體管理與最佳化

1. Redis 高階資料結構

Redis作為一款強大的開源記憶體資料庫,除了常見的資料結構(如字串、列表、集合等)外,還提供了許多高階資料結構

1.1.HyperLogLog

1.1.1.什麼是Redis HyperLogLog高階資料結構?

HyperLogLog是一種用於近似計數的資料結構,它可以在極小的記憶體開銷下,對一個資料集的基數(不重複元素的數量)進行估算。在處理大規模資料時,HyperLogLog能夠以高效的方式提供準確的估算結果,從而節省記憶體資源。

1.1.2.如何工作?

HyperLogLog的工作原理非常巧妙。它利用雜湊函式將輸入的元素對映到一個固定長度的位元陣列中,並透過統計位元陣列中字首0的數量來估算元素的基數。透過這種方式,HyperLogLog能夠以非常小的記憶體消耗來進行近似計數,適用於大規模資料集的場景。

1.1.3.HyperLogLog的基本操作

1.1.3.1.新增元素

要向HyperLogLog資料結構中新增元素,我們可以使用PFADD命令。例如,將元素"hello"新增到名為"mylog"的HyperLogLog中:

PFADD mylog hello

1.1.3.2.獲取近似基數

要獲取HyperLogLog資料結構的近似基數,我們可以使用PFCOUNT命令。例如,獲取名為"mylog"的HyperLogLog的近似基數:

PFCOUNT mylog

1.1.3.3.合併多個HyperLogLog

要合併多個HyperLogLog資料結構,我們可以使用PFMERGE命令。例如,將名為"mylog1"和"mylog2"的兩個HyperLogLog合併成一個新的HyperLogLog"mylog3":

PFMERGE mylog3 mylog1 mylog2

1.1.4.HyperLogLog的優勢

  • 記憶體佔用低:HyperLogLog能夠以非常小的記憶體開銷來進行近似計數,比傳統的計數方法具有更高的記憶體利用率。

  • 高度可擴充套件:在大規模資料集的情況下,HyperLogLog能夠輕鬆處理數十億甚至數萬億的元素,而不會受到記憶體限制的影響。

  • 快速計算:由於HyperLogLog的演算法簡單高效,因此可以快速對大規模資料集進行近似計數,提高了資料處理的效率。

1.2.Bitmaps

1.2.1.什麼是Redis Bitmaps高階資料結構?

Bitmaps是一種點陣圖資料結構,它可以儲存大量的二進位制位,並提供了一系列位操作命令,用於對點陣圖進行操作。在實際應用中,Bitmaps通常被用來表示某種狀態或者標記,例如使用者線上狀態、使用者簽到記錄等。

1.2.2.如何工作?

Bitmaps的工作原理非常簡單直觀。它實際上就是一個由二進位制位組成的陣列,每個位代表一個狀態或者標記。我們可以透過位操作命令來對點陣圖進行設定、清除、查詢等操作,從而實現對資料的靈活管理。

1.2.3.Bitmaps的基本操作

1.2.3.1.設定位

要設定Bitmaps資料結構中的某一位,我們可以使用SETBIT命令。例如,設定名為"online_users"的Bitmaps中的第100號位為1:

SETBIT online_users 100 1

1.2.3.2.查詢位

要查詢Bitmaps資料結構中的某一位的值,我們可以使用GETBIT命令。例如,查詢名為"online_users"的Bitmaps中的第100號位的值:

GETBIT online_users 100

1.2.3.3.統計位

要統計Bitmaps資料結構中值為1的位的數量,我們可以使用BITCOUNT命令。例如,統計名為"online_users"的Bitmaps中值為1的位的數量:

BITCOUNT online_users

1.2.3.4.其他位操作

除了上述基本操作外,Bitmaps還提供了一系列位操作命令,如AND、OR、XOR、NOT等,用於對多個點陣圖進行位操作,實現複雜的邏輯運算。

1.2.4.Bitmaps的優勢

  • 高效的儲存和查詢:Bitmaps採用緊湊的二進位制位儲存資料,佔用極少的記憶體空間,並且提供了快速的位操作命令,使得儲存和查詢效率非常高。

  • 靈活的應用場景:Bitmaps可以用來表示各種狀態或者標記,如使用者線上狀態、使用者簽到記錄、文章閱讀記錄等,具有很高的靈活性和通用性。

  • 簡單直觀的操作:Bitmaps提供了簡單直觀的位操作命令,使得對點陣圖進行操作變得非常簡單易懂,即使對於初學者也能輕鬆上手。

1.3.Geospatial 資料

1.3.1.什麼是Redis Geospatial資料?

Geospatial資料是指地理位置資訊,包括經度和緯度等座標資訊。在Redis中,Geospatial資料透過使用ZSET(有序集合)資料結構來儲存,其中成員是地理位置的名稱或標識,而分數則是該地理位置的經緯度資訊。

1.3.2.如何工作?

Redis的Geospatial資料使用了一種叫做Geohash的編碼方式來表示地理位置的經緯度資訊。透過將地理位置的經緯度編碼成一個字串,然後將這個字串作為ZSET的成員,從而實現了對地理位置的快速儲存和檢索。

1.3.3.Geospatial資料的基本操作

1.3.3.1.新增地理位置

要向Geospatial資料結構中新增地理位置,我們可以使用GEOADD命令。例如,將經度為116.404、緯度為39.915的地理位置新增到名為"cities"的Geospatial集合中:

GEOADD cities 116.404 39.915 "Beijing"

1.3.3.2.查詢地理位置

要查詢地理位置的經緯度資訊,我們可以使用GEOPOS命令。例如,查詢名為"cities"的Geospatial集合中"Beijing"的經緯度資訊:

GEOPOS cities "Beijing"

1.3.3.3.查詢地理位置之間的距離

要計算兩個地理位置之間的距離,我們可以使用GEODIST命令。例如,計算名為"cities"的Geospatial集合中"Beijing"和"Shanghai"之間的距離:

GEODIST cities "Beijing" "Shanghai" km

1.3.3.4.查詢地理位置周圍的其他地理位置

要查詢某個地理位置周圍的其他地理位置,我們可以使用GEORADIUS命令。例如,查詢名為"cities"的Geospatial集合中距離經度116.404、緯度39.915不超過100公里的其他地理位置:

GEORADIUS cities 116.404 39.915 100 km

1.3.4.Geospatial資料的優勢

  • 快速儲存和檢索:Geospatial資料透過ZSET資料結構儲存,實現了對地理位置的快速儲存和檢索,使得對地理位置的操作非常高效。

  • 方便的地理位置計算:透過使用Geospatial資料,我們可以方便地進行地理位置之間的距離計算、周圍地理位置的查詢等操作,為地理位置相關的應用提供了便利。

  • 靈活的應用場景:Geospatial資料可以應用於很多場景,如位置服務、地圖應用、附近推薦等,具有很高的通用性和靈活性。

1.4.Pub/Sub(釋出/訂閱)

1.4.1.什麼是Redis Pub/Sub功能?

Pub/Sub(釋出/訂閱)是Redis提供的一種訊息傳遞模式,它允許訊息的釋出者(釋出訊息)和訂閱者(接收訊息)之間進行非同步通訊。在Pub/Sub模式下,訊息的釋出者將訊息傳送到指定的頻道(Channel),而訂閱者則可以訂閱一個或多個頻道,接收並處理相應的訊息。

1.4.2.如何工作?

Pub/Sub的工作原理非常簡單明瞭。首先,訊息的釋出者使用PUBLISH命令將訊息傳送到指定的頻道中。然後,訂閱者使用SUBSCRIBE命令訂閱感興趣的頻道,當有訊息釋出到被訂閱的頻道時,訂閱者將立即收到相應的訊息。這種非同步通訊模式非常適用於實時通知、事件驅動等場景。

1.4.3.Pub/Sub的基本操作

1.4.3.1.釋出訊息

要釋出訊息到指定的頻道,我們可以使用PUBLISH命令。例如,將訊息"Hello, world!"釋出到名為"news"的頻道中:

PUBLISH news "Hello, world!"

1.4.3.2.訂閱頻道

要訂閱感興趣的頻道,我們可以使用SUBSCRIBE命令。例如,訂閱名為"news"的頻道:

SUBSCRIBE news

1.4.3.3.接收訊息

訂閱者在訂閱了頻道後,將實時接收到釋出到該頻道的訊息。無需使用額外的命令來接收訊息,Redis會自動將訊息推送給訂閱者。

1.4.3.4.取消訂閱頻道

要取消訂閱某個頻道,我們可以使用UNSUBSCRIBE命令。例如,取消訂閱名為"news"的頻道:

UNSUBSCRIBE news

1.4.4.Pub/Sub的優勢

  • 實時通訊:Pub/Sub模式支援實時訊息傳遞,訊息的釋出者和訂閱者之間可以實現快速的非同步通訊,適用於實時通知、事件驅動等場景。

  • 解耦合:Pub/Sub模式將訊息的釋出者和訂閱者解耦合,使得系統中的各個元件可以獨立開發、部署和維護,提高了系統的靈活性和可擴充套件性。

  • 多對多通訊:Pub/Sub模式支援多個釋出者向多個訂閱者傳送訊息,實現了多對多的訊息傳遞,能夠滿足複雜的業務需求。

2. Redis 事務與持久化

2.1.Redis 事務簡介

Redis作為一款快速、高效的記憶體資料庫,不僅支援基本的資料儲存和讀取,還提供了強大的事務功能,可以幫助我們實現原子性操作,即要麼全部執行成功,要麼全部不執行。今天,讓我們一起來深入瞭解Redis事務,掌握其基本概念和使用方法。

2.1.1.什麼是Redis事務?

首先,我們來解釋一下什麼是事務。想象一下,你去銀行取錢,你要麼全額取出,要麼一分錢也取不到,中間沒有“摳門”的可能。對吧?那麼,Redis事務就是這麼個意思,一組操作要麼全部成功,要麼全部失敗,中間不允許摳腳。

Redis事務是一組命令的集合,這組命令要麼全部執行,要麼全部不執行,Redis會保證事務中的所有命令都是原子性的,即要麼全部執行成功,要麼全部失敗回滾。這樣可以確保資料的一致性,避免了中間狀態的出現。

2.1.2.為什麼需要Redis事務?

因為有些操作是需要一起完成的。比如,你要給你的朋友轉賬,你要麼扣掉你的錢,要麼給你的朋友加錢,如果中間有個操作失敗了,那你就糗大了。這時候,Redis事務就派上用場了,保證所有操作一氣呵成,不會半途而廢。

在實際應用中,有些操作需要多個命令組合才能完成,而且需要保證這些命令一起執行,要麼全部成功,要麼全部失敗。這時候,就可以使用Redis事務來保證這兩個命令的原子性執行。

2.1.3.如何使用Redis事務?

首先,你要開啟一個事務,就像開啟聚會一樣,嗨起來!然後,把你要做的事情都寫在一個清單上,一氣呵成,不要中途停下來。最後,等到一切準備就緒,就執行你的計劃,一舉成功!

Redis事務的使用非常簡單,一般包括以下幾個步驟:

  1. 使用MULTI命令開始一個事務。
  2. 在事務塊中依次執行需要執行的命令。
  3. 使用EXEC命令觸發事務執行,Redis會將事務中的所有命令一起執行。
  4. 如果需要取消事務,可以使用DISCARD命令取消事務。

2.1.4.事務的特點和注意事項

  • 事務中的所有命令都是原子性的,要麼全部執行成功,要麼全部失敗回滾。
  • Redis事務不支援回滾操作,即使事務中的某個命令執行失敗,後續命令仍然會被執行。
  • 事務中的命令不會立即執行,而是在執行EXEC命令時才會執行。

2.1.5.事務的應用場景

  • 批次操作:事務可以將多個命令打包成一個原子操作,用於實現批次讀寫操作。
  • 原子性操作:事務中的所有命令都是原子性的,可以確保多個命令的一致性和完整性。
  • 樂觀鎖:透過使用WATCH命令監視鍵,在事務執行前檢查鍵是否被修改,從而實現樂觀鎖機制。

2.2.持久化方式:RDB 和 AOF

Redis作為一款記憶體資料庫,它的資料預設是儲存在記憶體中的,但是一旦伺服器重啟或者斷電,記憶體中的資料就會丟失。為了解決這個問題,Redis提供了持久化機制,可以將資料儲存到硬碟上,保證資料的永續性。今天我們就來詳細瞭解一下Redis的兩種主要持久化方式:RDB和AOF。

2.2.1.RDB(Redis DataBase)持久化方式

RDB持久化方式是將Redis的資料以快照的形式週期性地儲存到硬碟上,形成一個時間點的資料快照。具體來說,當滿足一定條件(比如規定的時間間隔內,有一定數量的寫操作)時,Redis會fork出一個子程序,將當前記憶體中的資料寫入到一個臨時檔案中,待寫入完成後,再替換原來的RDB檔案。

RDB的優點在於:

  • 適用於大規模的資料恢復,因為資料以快照的形式儲存,恢復速度較快。
  • RDB檔案較小,佔用空間較少。

但是,RDB也有一些缺點:

  • 如果出現當機情況,可能會丟失一部分資料,因為RDB是定期儲存的,並非實時儲存。
  • RDB需要fork一個子程序來進行持久化操作,可能會影響伺服器的效能。

2.2.2.AOF(Append Only File)持久化方式

AOF持久化方式是將Redis的寫操作以追加的方式儲存到一個檔案中,這個檔案就是AOF檔案。Redis在執行寫操作時,會將命令追加到AOF檔案的末尾,以此來記錄資料庫狀態的變化。AOF檔案中記錄的是所有的寫操作命令,透過重新執行這些命令,可以完全恢復資料。

AOF的優點在於:

  • 資料的持久化是實時的,每一次寫操作都會立即被記錄到AOF檔案中,不會丟失資料。
  • AOF檔案是一個文字檔案,易於閱讀和理解。

但是,AOF也有一些缺點:

  • AOF檔案相比RDB檔案更大,佔用磁碟空間較多。
  • AOF檔案的恢復速度較慢,因為需要逐條執行檔案中的命令。

2.2.3.如何選擇持久化方式?

在實際應用中,我們可以根據自己的需求來選擇合適的持久化方式:

  • 如果對資料的實時性要求較高,可以選擇AOF持久化方式。
  • 如果對資料的恢復速度要求較高,可以選擇RDB持久化方式。
  • 也可以同時開啟RDB和AOF持久化方式,以實現資料的雙重保護。

持久化是保證Redis資料永續性的重要手段,透過選擇合適的持久化方式,可以保證資料的安全和可靠性。

2.3.配置和管理持久化

2.3.1.配置持久化方式

Redis提供了兩種主要的持久化方式:RDB和AOF。那麼,我們該如何配置持久化方式呢?

RDB持久化方式

  • 在Redis配置檔案(redis.conf)中,找到並修改save選項,設定自動觸發RDB持久化的條件,比如在一段時間內有一定數量的寫操作。
  • 可以透過設定stop-writes-on-bgsave-error選項來決定是否在RDB持久化過程中出現錯誤時停止寫操作。

AOF持久化方式

  • 在Redis配置檔案中,將appendonly選項設定為yes,即可開啟AOF持久化功能。
  • 可以透過設定appendfsync選項來控制AOF檔案何時進行同步寫入硬碟,有三種選項可供選擇:always(每次寫操作都進行同步寫入)、everysec(每秒進行一次同步寫入,預設選項)、no(由作業系統決定何時進行同步寫入)。

2.3.2.管理持久化

除了配置持久化方式,我們還需要了解如何管理持久化:

手動觸發持久化

  • 你可以在Redis命令列中執行相應的命令來手動觸發持久化操作,比如SAVE命令觸發RDB持久化、BGSAVE命令觸發後臺RDB持久化、BGREWRITEAOF命令觸發AOF重寫操作。

監控持久化過程

  • 你可以透過監控Redis的日誌檔案來了解持久化過程是否正常進行,同時可以藉助第三方監控工具來實時監控持久化的狀態和效能指標。

3. Redis 高階功能

3.1.分散式鎖

3.1.1.什麼是分散式鎖?

首先,瞭解一下什麼是分散式鎖。在分散式系統中,多個節點同時訪問共享資源時,為了避免資料混亂和衝突,我們需要一種機制來保證同一時刻只有一個節點能夠訪問資源,這就是分散式鎖。

3.1.2.Redis中的分散式鎖實現

Redis提供了一種簡單而有效的分散式鎖實現方式,即使用SETNX(SET if Not eXists)命令。具體實現如下:

  1. 使用SETNX命令設定一個特定的鍵作為鎖,值為某個唯一識別符號,表示鎖的持有者。

  2. 如果SETNX命令返回1,表示鎖設定成功,持有者為當前客戶端,即獲取到了鎖;如果返回0,表示鎖已經被其他客戶端持有,獲取鎖失敗。

  3. 當客戶端需要釋放鎖時,可以使用DEL命令刪除對應的鍵,釋放鎖。

3.1.3.分散式鎖的問題與解決方案

雖然Redis的分散式鎖實現非常簡單,但也存在一些問題,比如死鎖、鎖過期等。為了解決這些問題,我們可以採取以下方案:

  1. 設定鎖的過期時間:使用SET命令時,同時設定一個合理的過期時間,防止鎖長時間被佔用。

  2. 使用鎖續約:在獲取到鎖之後,定期更新鎖的過期時間,確保持有鎖的客戶端意外當機時,鎖可以自動釋放。

  3. 採用阻塞式獲取鎖:使用Redis的BLPOP、BRPOP等命令,當獲取鎖失敗時,進行阻塞等待,直到獲取到鎖為止。

3.1.4.Redis中的分散式鎖實現

Redis提供了一種簡單而有效的分散式鎖實現方式,即使用SETNX(SET if Not eXists)命令。下面我們來看一下具體的實現過程:

package main

import (
    "fmt"
    "time"

    "github.com/go-redis/redis/v8"
)

var ctx = context.Background()

func main() {
    // 連線Redis伺服器
    rdb := redis.NewClient(&redis.Options{
        Addr:     "localhost:6379",
        Password: "", // no password set
        DB:       0,  // use default DB
    })

    // 定義獲取分散式鎖的函式
    acquireLock := func(lockName string, acquireTimeout time.Duration) bool {
        // 設定鎖的過期時間,防止死鎖
        lockTimeout := 10 * time.Second
        endTime := time.Now().Add(acquireTimeout)
        for time.Now().Before(endTime) {
            // 嘗試獲取鎖
            setNX := rdb.SetNX(ctx, lockName, "locked", lockTimeout)
            if setNX.Val() {
                // 設定鎖的過期時間
                rdb.Expire(ctx, lockName, lockTimeout)
                return true
            }
            // 等待一段時間後重試
            time.Sleep(100 * time.Millisecond)
        }
        return false
    }

    // 定義釋放分散式鎖的函式
    releaseLock := func(lockName string) {
        rdb.Del(ctx, lockName)
    }

    // 使用分散式鎖
    if acquireLock("my_lock", 10*time.Second) {
        defer releaseLock("my_lock")
        // 執行需要加鎖的操作
        fmt.Println("成功獲取到分散式鎖,進行操作...")
        time.Sleep(5 * time.Second) // 模擬執行一些操作
        fmt.Println("成功釋放分散式鎖")
    } else {
        fmt.Println("獲取分散式鎖失敗,可能有其他程序正在使用鎖")
    }
}

3.2.Lua 指令碼

3.2.1.什麼是Lua指令碼?

Lua是一種輕量級的指令碼語言,被廣泛應用於嵌入式系統和遊戲開發領域。在Redis中,Lua指令碼可以透過EVALEVALSHA命令執行,允許使用者在Redis伺服器端執行自定義的Lua指令碼。

3.2.2.為什麼要使用Lua指令碼?

那麼,為什麼我們要使用Lua指令碼呢?Lua指令碼在Redis中有以下幾個優勢:

  1. 原子性操作:Lua指令碼可以保證在執行期間不被其他命令中斷,從而保證了原子性操作,避免了競態條件的發生。

  2. 減少網路開銷:將多個命令打包成Lua指令碼一次性執行,可以減少網路往返開銷,提高效能。

  3. 複雜邏輯支援:Lua指令碼可以執行復雜的邏輯操作,包括條件判斷、迴圈等,使得Redis能夠處理更多種類的業務需求。

3.2.3.如何在Redis中使用Lua指令碼?

接下來,我將向大家展示如何在Redis中使用Lua指令碼來實現一個簡單的計數器功能。我們將使用Lua指令碼來實現原子性的遞增操作。

-- 定義Lua指令碼
local key = KEYS[1]
local current = tonumber(redis.call('GET', key) or "0")
local step = tonumber(ARGV[1] or "1")
local result = current + step
redis.call('SET', key, result)
return result

在這個Lua指令碼中,我們首先獲取了傳入的鍵(key)和遞增步長(step),然後透過GET命令獲取當前值,對其進行遞增操作,並使用SET命令更新鍵的值,最後返回遞增後的結果。

3.3.客戶端連線和連線池

3.3.1.什麼是客戶端連線?

在與Redis進行通訊時,我們需要建立客戶端與Redis伺服器之間的連線,以便傳送命令和接收響應。這個連線就是客戶端連線。

3.3.2.為什麼需要連線池?

每次執行Redis命令時都建立新的連線是非常低效的,因為連線的建立和銷燬都會消耗資源。而連線池的作用就是在程式初始化時建立一定數量的連線,並在需要時從池中獲取連線,使用完畢後再將連線歸還給池,以減少連線的頻繁建立和銷燬,提高效能。

3.3.3.如何使用連線池?

接下來,我將向大家展示如何在不同的程式語言中使用連線池來連線Redis。

Go語言中,可以使用go-redis庫來連線Redis並使用連線池。以下是一個簡單的示例:

package main

import (
    "fmt"

    "github.com/go-redis/redis/v8"
)

func main() {
    // 建立連線池
    options := &redis.Options{
        Addr:     "localhost:6379",
        Password: "", // no password set
        DB:       0,  // use default DB
        PoolSize: 10, // 設定連線池大小
    }
    // 建立Redis客戶端
    rdb := redis.NewClient(options)

    // 使用連線池執行Redis命令
    err := rdb.Set(ctx, "foo", "bar", 0).Err()
    if err != nil {
        panic(err)
    }
    val, err := rdb.Get(ctx, "foo").Result()
    if err != nil {
        panic(err)
    }
    fmt.Println("foo:", val)
}

3.4.記憶體管理與最佳化

3.4.1.記憶體管理策略

Redis採用了多種策略來管理記憶體,主要包括以下幾點:

  1. 資料結構最佳化:選擇合適的資料結構來儲存資料,如使用雜湊表來儲存鍵值對資料,使用有序集合來儲存有序資料等。

  2. 過期策略:透過設定鍵的過期時間,自動刪除不再需要的資料,釋放記憶體空間。

  3. 記憶體淘汰策略:當記憶體不足時,根據一定的策略刪除一些資料以釋放記憶體,常見的淘汰策略包括LRU(最近最少使用)、LFU(最少使用頻率)等。

3.4.2.記憶體最佳化技巧

除了Redis自身的記憶體管理策略外,我們還可以透過一些最佳化技巧來進一步提升Redis的記憶體利用率和效能:

  1. 合併小鍵值對:將多個小鍵值對合併成一個大鍵值對,減少鍵的數量,降低記憶體開銷。

  2. 使用壓縮:對於儲存的大量文字資料,可以考慮使用壓縮演算法,如Gzip或LZF等,減少記憶體佔用。

  3. 限制資料大小:設定合理的資料大小限制,防止資料過大導致記憶體溢位。

  4. 定期清理無用資料:定期清理無用資料和過期資料,釋放記憶體空間。

3.4.3.實際操作示例

下面是一個簡單的Redis記憶體最佳化示例,我們將透過合併小鍵值對來減少記憶體佔用:

package main

import (
    "context"
    "fmt"

    "github.com/go-redis/redis/v8"
)

func main() {
    // 連線Redis伺服器
    rdb := redis.NewClient(&redis.Options{
        Addr:     "localhost:6379",
        Password: "", // no password set
        DB:       0,  // use default DB
    })

    // 設定小鍵值對
    _, err := rdb.MSet(ctx, "key1", "value1", "key2", "value2", "key3", "value3").Result()
    if err != nil {
        panic(err)
    }

    // 刪除原來的小鍵值對
    _, err = rdb.Del(ctx, "key1", "key2", "key3").Result()
    if err != nil {
        panic(err)
    }

    fmt.Println("合併小鍵值對完成")
}

相關文章