.NET Core 實現 Redis 批量查詢指定格式的Key


一. 問題場景

Redis 作為當前最流行的內存型 NoSQL 數據庫,被許多公司所使用,作為分布式緩存。我們在實際使用中一般都會為 key 帶上指定的前綴或者其他定義的格式。當由於我們程序出現bug,造成 redis 里面的存儲的值,與我們預期的不一致時,我們可以通過查詢指定格式的 key,來定位到我們具體的出現問題的key,從而方便我們解決問題。

二. 解決辦法

1.Keys 命令

Keys 命令用於查找所有符合給定模式 pattern 的 key 。要求 Redis 版本大於 1.0.0。keys在查詢大數量key時,會長時間阻塞Redis,由於Redis是單線程的,這就是一個突出的問題,需要注意。

2.Scan 命令

Scan 命令相對於 Keys 命令來說,優點就是不會阻塞服務器。要求 Redis 版本大於 2.8。

三. 代碼實現

這里采用的Redis驅動是 StackExchange.Redis。

在 StackExchange.Redis 里封裝 Redis 命令時分為了兩種,一種是針對於集群的命令,一種是針對於單個Redis服務器的命令,Keys 和 Scan 命令便是后者,我們在使用的時候必須在單獨的服務器上執行。

Keys 和 Scan 命令都支持模糊查詢,這里介紹三種匹配符:

  1. * 表示可以匹配多個任意字符
  2. ? 表示可以匹配單個任意字符
  3. [] 表示可以匹配指定范圍內的字符

因為我們的key可能分布在集群內多個Redis服務器上,所以我們需要在每台服務器上都執行命令。我們可以通過 ConnectionMultiplexer.GetEndPoints() 方法來獲取所有的終結點信息。

在 StackExchange.Redis 對於 keys 和 scan 命令統一封裝為了 IServer.Keys()方法,它會自動根據Redis服務器版本來決定使用keys命令還是scan命令。

為了方便測試,我在 Redis 里面准備了四個以 test 為前綴的key,放在序號為1的db里面:

1535608206837

1.遍歷所有前綴為 test 的key 代碼如下:

static async Task Main(string[] args)
{
    //創建連接
    var conn = await ConnectionMultiplexer.ConnectAsync("192.168.10.110");
    //獲取db
    var db = conn.GetDatabase(1);
    //遍歷集群內服務器
    foreach (var endPoint in conn.GetEndPoints())
    {
        //獲取指定服務器
        var server = conn.GetServer(endPoint);
        //在指定服務器上使用 keys 或者 scan 命令來遍歷key
        foreach (var key in server.Keys(1,"test.*"))
        {
            //獲取key對於的值
            var val = db.StringGet(key);
            Console.WriteLine($"key: {key}, value: {val}");
        }
    }
}

執行結果:

1535608290825

2.[]的用法

假設我要遍歷 key為 test.1-test.3 的數據,可以這樣寫:

static async Task Main(string[] args)
{
    //創建連接
    var conn = await ConnectionMultiplexer.ConnectAsync("192.168.10.110");
    //獲取db
    var db = conn.GetDatabase(1);
    //遍歷集群內服務器
    foreach (var endPoint in conn.GetEndPoints())
    {
        //獲取指定服務器
        var server = conn.GetServer(endPoint);
        //在指定服務器上使用 keys 或者 scan 命令來遍歷key
        foreach (var key in server.Keys(1,"test.[1-3]"))
        {
            //獲取key對於的值
            var val = db.StringGet(key);
            Console.WriteLine($"key: {key}, value: {val}");
        }
    }
}

執行結果:

1535608429827

假設我要遍歷 key為 test.1和test.4 的數據,可以這樣寫:

static async Task Main(string[] args)
{
    //創建連接
    var conn = await ConnectionMultiplexer.ConnectAsync("192.168.10.110");
    //獲取db
    var db = conn.GetDatabase(1);
    //遍歷集群內服務器
    foreach (var endPoint in conn.GetEndPoints())
    {
        //獲取指定服務器
        var server = conn.GetServer(endPoint);
        //在指定服務器上使用 keys 或者 scan 命令來遍歷key
        foreach (var key in server.Keys(1,"test.[1,4]"))
        {
            //獲取key對於的值
            var val = db.StringGet(key);
            Console.WriteLine($"key: {key}, value: {val}");
        }
    }
}

執行結果:

1535608506604

好了,關於 Redis 查詢指定格式的 key 的方法就介紹到這里了。

四. 參考資料

Where are KEYS, SCAN, FLUSHDB etc? by StackExchange.Redis


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM