sql >> データベース >  >> NoSQL >> Redis

RedisClient LUA API

    IRedisClient redisサーバー側のLUAサポート用のAPIは、以下のよりユーザーフレンドリーなAPIにリファクタリングされています。

    public interface IRedisClient 
    {
        //Eval/Lua operations 
        T ExecCachedLua<T>(string scriptBody, Func<string, T> scriptSha1);
    
        RedisText ExecLua(string body, params string[] args);
        RedisText ExecLua(string luaBody, string[] keys, string[] args);
        RedisText ExecLuaSha(string sha1, params string[] args);
        RedisText ExecLuaSha(string sha1, string[] keys, string[] args);
    
        string ExecLuaAsString(string luaBody, params string[] args);
        string ExecLuaAsString(string luaBody, string[] keys, string[] args);
        string ExecLuaShaAsString(string sha1, params string[] args);
        string ExecLuaShaAsString(string sha1, string[] keys, string[] args);
        
        int ExecLuaAsInt(string luaBody, params string[] args);
        int ExecLuaAsInt(string luaBody, string[] keys, string[] args);
        int ExecLuaShaAsInt(string sha1, params string[] args);
        int ExecLuaShaAsInt(string sha1, string[] keys, string[] args);
    
        List<string> ExecLuaAsList(string luaBody, params string[] args);
        List<string> ExecLuaAsList(string luaBody, string[] keys, string[] args);
        List<string> ExecLuaShaAsList(string sha1, params string[] args);
        List<string> ExecLuaShaAsList(string sha1, string[] keys, string[] args);
    
        string CalculateSha1(string luaBody);
        
        bool HasLuaScript(string sha1Ref);
        Dictionary<string, bool> WhichLuaScriptsExists(params string[] sha1Refs);
        void RemoveAllLuaScripts();
        void KillRunningLuaScript();
        string LoadLuaScript(string body);
    }
    

    LUAでの効率的なSCAN#

    以下のC#APIは、key:*に一致する最初の10件の結果を返します。 パターン:

    var keys = Redis.ScanAllKeys(pattern: "key:*", pageSize: 10)
        .Take(10).ToList();
    

    ただし、上記のC#ストリーミングAPIでは、リクエストを完了するために、不明な数のRedis操作(Redisのキーの数に制限されます)が必要です。より高いpageSizeを選択することで、SCAN呼び出しの数を減らすことができます。 SCAN操作が呼び出されるたびにさらに多くのキーをスキャンするようにRedisに指示します。

    API呼び出しの数は、多数のRedis操作を引き起こす可能性があるため、複数の依存するリモートネットワーク呼び出しの遅延により、許容できない遅延が発生する可能性があります。簡単な解決策は、代わりに複数のSCAN呼び出しをRedisサーバーでインプロセスで実行し、複数のSCAN呼び出しのネットワーク遅延を排除することです。例:

    const string FastScanScript = @"
    local limit = tonumber(ARGV[2])
    local pattern = ARGV[1]
    local cursor = 0
    local len = 0
    local results = {}
    repeat
        local r = redis.call('scan', cursor, 'MATCH', pattern, 'COUNT', limit)
        cursor = tonumber(r[1])
        for k,v in ipairs(r[2]) do
            table.insert(results, v)
            len = len + 1
            if len == limit then break end
        end
    until cursor == 0 or len == limit
    return results";
    
    RedisText r = redis.ExecLua(FastScanScript, "key:*", "10");
    r.Children.Count.Print() //= 10
    

    ExecLua APIは、この複雑なLUAテーブルの応答をChildrenで返します RedisTextのコレクション 応答。

    Alternative Complex API Response#

    LUA操作で複雑なデータ構造を返す別の方法は、結果をJSONとしてシリアル化することです

    return cjson.encode(results)
    

    応答を次の文字列として解析することで、生のJSONとしてアクセスできます:

    string json = redis.ExecLuaAsString(FastScanScript, "key:*", "10");
    

    情報

    これは、RedisReactのRedisServicesで使用されているアプローチでもあります。

    ExecCachedLua#

    ExecCachedLuaは便利な高レベルAPIであり、RDBMSストアドプロシージャが抱える問題の多くに悩まされている高性能サーバーLUAスクリプトの実行に必要な簿記を排除します。これは、RDBMSの既存の状態に依存します。ストアドプロシージャの最新バージョン。

    Redis LUAを使用すると、呼び出されるたびにLUAスクリプト全体を送信、解析、ロードして実行するオプションがあります。または、スタートアップ時にLUAスクリプトをRedisにプリロードしてから、スクリプトのSHA1ハッシュを使用して実行することもできます。これに伴う問題は、Redisサーバーが誤ってフラッシュされた場合、存在しない既存のスクリプトに依存する壊れたアプリケーションが残ることです。新しいExecCachedLua APIは、コンパイルされたSHA1スクリプトを常に実行し、帯域幅とCPUを節約するだけでなく、LUAスクリプトが存在しなくなった場合は再作成するという、両方の長所を提供します。

    代わりに、上記のコンパイル済みLUAスクリプトをSHA1識別子で実行できます。この識別子は、存在しなかったか、実行時に削除されたかに関係なく機能し続けます。例:

    // #1: Loads LUA script and caches SHA1 hash in Redis Client
    r = redis.ExecCachedLua(FastScanScript, sha1 =>
        redis.ExecLuaSha(sha1, "key:*", "10"));
    
    // #2: Executes using cached SHA1 hash
    r = redis.ExecCachedLua(FastScanScript, sha1 =>
        redis.ExecLuaSha(sha1, "key:*", "10"));
    
    // Deletes all existing compiled LUA scripts 
    redis.ScriptFlush();
    
    // #3: Executes using cached SHA1 hash, gets NOSCRIPT Error, 
    //     re-creates then re-executes the LUA script using its SHA1 hash
    r = redis.ExecCachedLua(FastScanScript, sha1 =>
        redis.ExecLuaSha(sha1, "key:*", "10"));
    

    使用例#

    ZPOPを実装する方法は次のとおりです ソートされたセットからランクが最も低いアイテムを削除するには、Luaで:

    var luaBody = @"
        local val = redis.call('zrange', KEYS[1], 0, ARGV[1]-1)
        if val then redis.call('zremrangebyrank', KEYS[1], 0, ARGV[1]-1) end
        return val";
    
    var i = 0;
    var alphabet = 26.Times(c => ((char)('A' + c)).ToString());
    alphabet.ForEach(x => Redis.AddItemToSortedSet("zalphabet", x, i++));
    
    //Remove the letters with the lowest rank from the sorted set 'zalphabet'
    var letters = Redis.ExecLuaAsList(luaBody, keys: new[] { "zalphabet" }, args: new[] { "3" });
    letters.PrintDump(); //[A, B, C]
    

    そして、 ZREVPOPを実装する方法 並べ替えられたセットから最高ランクのアイテムを削除するには:

    var luaBody = @"
        local val = redis.call('zrange', KEYS[1], -ARGV[1], -1)
        if val then redis.call('zremrangebyrank', KEYS[1], -ARGV[1], -1) end
        return val";
    
    var i = 0;
    var alphabet = 26.Times(c => ((char)('A' + c)).ToString());
    alphabet.ForEach(x => Redis.AddItemToSortedSet("zalphabet", x, i++));
    
    //Remove the letters with the highest rank from the sorted set 'zalphabet'
    List<string> letters = Redis.ExecLuaAsList(luaBody, 
        keys: new[] { "zalphabet" }, args: new[] { "3" });
    
    letters.PrintDump(); //[X, Y, Z]
    

    その他の例#

    intを返す :

    int intVal = Redis.ExecLuaAsInt("return 123"); //123
    int intVal = Redis.ExecLuaAsInt("return ARGV[1] + ARGV[2]", "10", "20"); //30
    

    stringを返す :

    //Hello, Redis Lua!
    var strVal = Redis.ExecLuaAsString(@"return 'Hello, ' .. ARGV[1] .. '!'", "Redis Lua");
    

    Listを返す 文字列の数:

    Enum.GetNames(typeof(DayOfWeek)).ToList()
        .ForEach(x => Redis.AddItemToList("DaysOfWeek", x));
    
    var daysOfWeek = Redis.ExecLuaAsList("return redis.call('LRANGE', 'DaysOfWeek', 0, -1)");
    daysOfWeek.PrintDump(); //[Sunday, Monday, Tuesday, ...]
    

    その他の例は、RedisEvalLuaテストで見つけることができます


    1. Redisキー内のコロンの目的は何ですか

    2. IDセットで複数のドキュメントを更新します。マングース

    3. TwitterのストリーミングAPIからツイートを消費してmongodbに保存するにはどうすればよいですか?

    4. 文字列からutf-8以外のすべての記号を削除します