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

RedisサーバーのCPU使用率を改善するにはどうすればよいですか?

    RedisのCPU使用率を最大化することが、バックエンドの設計に役立つとは思えません。正しい質問は、Redisが特定のレイテンシでスループットを維持するのに十分効率的かどうかということです。 Redisはシングルスレッドサーバーです。CPU消費率が80%の場合、レイテンシは非常に悪くなる可能性があります。

    Redis-benchmarkが機能している間にレイテンシーを測定して、RedisのCPU消費量を増やす前に、ニーズに適しているかどうかを確認することをお勧めします。これには、redis-cliの--latencyオプションを使用できます:

    • redis-serverを起動
    • redis-cli --latencyを試して、平均値をメモし、停止します
    • 別のウィンドウでベンチマークを開始し、しばらくの間実行されることを確認します
    • redis-cli --latencyを試して、平均値をメモし、停止します
    • ベンチマークを停止する
    • 2つの平均値を比較します

    ここで、RedisのCPU消費量を本当に増やしたい場合は、複数の接続を同時に処理できる効率的なクライアントプログラム(redis-benchmarkなど)、またはクライアントプログラムの複数のインスタンスが必要です。

    Luaは高速インタプリタ言語ですが、それでもインタプリタ言語です。 Cコードよりも1桁または2桁遅くなります。 Redisは、lua-redisよりもプロトコルの解析/生成がはるかに高速であるため、一意のLuaクライアントでRedisを飽和させることはできません(O(n)Redisコマンドを使用する場合を除く-後述)。

    webdisは効率的なクライアントライブラリを使用してCで実装されていますが、Redisプロトコルよりも冗長で複雑なhttp/jsonプロトコルを解析する必要があります。ほとんどの操作で、Redis自体よりも多くのCPUを消費する可能性があります。繰り返しになりますが、単一のwebdisインスタンスでRedisを飽和させることはありません。

    複数のLuaクライアントでRedisを飽和させるいくつかの例を次に示します。

    まだ完了していない場合は、最初にRedisベンチマークページを確認することをお勧めします。

    Redisと同じボックスでベンチマークを実行する場合:

    重要な点は、コアをRedis専用にし、他のコアでクライアントプログラムを実行することです。 Linuxでは、これにtasksetコマンドを使用できます。

    # Start Redis on core 0
    taskset -c 0 redis-server redis.conf
    
    # Start Lua programs on the other cores
    for x in `seq 1 10` ; do taskset -c 1,2,3 luajit example.lua & done
    

    Luaプログラムは、スループットを最大化し、システムアクティビティを削減するために、パイプラインを使用する必要があります。

    local redis = require 'redis'
    local client = redis.connect('127.0.0.1', 6379)
    for i=1,1000000 do
        local replies = client:pipeline(function(p)
        for j=1,1000 do
                local key = 'counter:'..tostring(j)
                p:incrby(key,1)
            end
        end)
    end
    

    私のシステムでは、LuaプログラムはRedisのCPUの4倍以上を使用するため、この方法でRedisを飽和させるには4コア以上が必要です(6コアボックスで十分です)。

    Redisとは別のボックスでベンチマークを実行する場合:

    CPUが不足している仮想マシンで実行している場合を除いて、その場合のボトルネックはネットワークである可能性があります。 1GbEリンク未満でRedisを飽和させることはできないと思います。

    ネットワーク遅延のボトルネックを回避し、CPUでのネットワーク割り込み(イーサネットパケットの充填)のコストを削減するために、クエリを可能な限りパイプライン化してください(前のLuaプログラムを参照)。ネットワークカードにバインドされていない(そしてネットワーク割り込みを処理する)コアでRedisを実行してみてください。 htopなどのツールを使用して、この最後のポイントを確認できます。

    可能であれば、ネットワークの他のさまざまなマシンでLuaクライアントを実行してみてください。ここでも、Redisを飽和させるためにかなりの数のLuaクライアントが必要になります(6〜10で十分です)。

    場合によっては、独自のLuaプロセスで十分です:

    現在、各クエリが十分に高価な場合は、単一のLuaクライアントでRedisを飽和させることができます。次に例を示します:

    local redis = require 'redis'
    local client = redis.connect('127.0.0.1', 6379)
    
    for i=1,1000 do
        local replies = client:pipeline(function(p)
            for j=1,1000 do
                p:rpush("toto",i*1000+j)
            end
        end)
    end
    
    N = 500000
    for i=1,100000 do
        local replies = client:pipeline(function(p)
            for j=1,10 do
                p:lrange("toto",N, N+10)
            end
        end)
    end
    

    このプログラムは、リストに100万個のアイテムを入力し、lrangeコマンドを使用してリストの中央から10個のアイテムをフェッチします(Redisの場合は最悪の場合)。したがって、クエリが実行されるたびに、500Kのアイテムがサーバーによってスキャンされます。返されるアイテムは10個だけなので、CPUを消費しないlua-redisによる解析が高速です。この状況では、すべてのCPU消費はサーバー側で発生します。

    最後の言葉

    おそらくredis-luaよりも高速なRedisクライアントがあります:

    • https://github.com/agladysh/lua-hiredis(hiredisに基づく)
    • https://github.com/agladysh/ljffi-hiredis(hiredisに基づき、luajit FFIを使用)

    試してみてください。




    1. MongoEngineとPyMongoを一緒に使用する

    2. js内に別のファイルを含むmongodbでjavascriptスクリプト(.jsファイル)を実行します

    3. ドキュメントベースのデータベースとキー/値ベースのデータベースの違いは?

    4. DjangoのデータベースとしてPostgreSQLを使用しているのにRedisを使用する必要があるのはなぜですか?