TWEMPROXY(NUTCRACKER).NET ServiceStack.redisクライアントによるパフォーマンス低下
-
21-12-2019 - |
質問
CentOS 6.4のRedisとNutCrackerを設定します。そしてservicestack.redisクライアントを使用して接続しようとしています。主要なパフォーマンスの問題が発生しました。
テストの場合は1 Redisインスタンス
beta:
listen: 0.0.0.0:22122
hash: fnv1a_64
distribution: ketama
auto_eject_hosts: true
#timeout: 5000
#server_retry_timeout: 2000
#server_failure_limit: 3
redis: true
servers:
#- 127.0.0.1:6379:1
- 127.0.0.1:6380:1
.
次のユニットテストでは、NutCrackerを介して100K文字列をRedisに送信しようとしています。
[TestClass]
public class RedisProxyTest
{
public string host = "192.168.56.112";
//public int port = 6379;
public int port = 22122;
[TestMethod]
public void TestMethod1()
{
var key = "l2";
var count = 100000;
using (var redisClient = new RedisClient(host, port))
{
var list = new List<string>();
for (int i = 0; i < count; i++)
{
list.Add(Guid.NewGuid().ToString());
}
Utils.TimeLog("Remove", () => redisClient.Remove(key));
Utils.TimeLog("AddRangeToList", () => redisClient.AddRangeToList(key, list));
}
using (var redisClient = new RedisClient(host, port))
{
redisClient.GetListCount(key);
Utils.TimeLog("GetRangeFromList", () =>
{
var ret = redisClient.GetRangeFromList(key, count / 2, count - 1);
Console.WriteLine(ret.Count);
});
}
}
}
.
Nutcrackerの再起動後の最初の数回の実行addrangeetolistは1~2秒で動作します。しかし、その後の実行では、AddRangeetoListのパフォーマンスは、20分以上の数分から大幅に低下します(タイムアウトが設定されていない場合)。Redisを直接使用するときは同じ再生できません。私はまだ他のクライアントを試していませんでした。なぜですか?
ユニットテストの実行後にコンソールで表示されるもの:
Test Name: TestMethod1
Test Outcome: Passed
Remove: 0.0331171
AddRangeToList: 806.8219166
50000
GetRangeFromList: 1.741737
. 解決
NutCrackerが数千の接続を加えたり、数千の鍵とのマルチGETリクエストを送信している場合は、MBUFサイズ512
を使用する必要があります。次のリンクは、MBUFサイズの解釈方法について話しますか? - https://github.com/twitter/twemproxy/issues/141
すべてのクライアント接続は少なくとも1つのMBUFを消費します。リクエストを処理するには、2つの接続が必要です(クライアントからプロキシへ、別のプロキシからサーバーへの別のものから1つ)。だから私たちは2つのMBUFSを必要とするでしょう。
「Foo Bar \ R \ N」のような断片的な要求は、BTWが「Get Foo \ R \ N」に断片化され、 'Get Bar \ R \ N'が要求のために2つのMBUFを消費し、応答のための2つのMBUFを消費します。 。そのため、Nフラグメントを持つ断片的な要求は、N * 2 MBUFS
を必要としています。MBUFについての良いことは、メモリが再利用プールから来ることです。 MBUFが割り当てられると解放されることはなく、再利用プールに戻すだけです。悪いことは、MBUFが割り当てられたら、解放されたMBUFが常に再利用プールに戻るからです。 https://github.com/twitter/twemproxy/blob/master/src/nc_mbuf.co.c.C.L23-L24 (これは、入れることで固定できます。再利用プールのしきい値パラメータ)
そのため、NutCrackerが1Kクライアント接続と100サーバ接続を処理している場合は、MBUF用のMAX(1000,100)* 2 * MBUFサイズ)メモリを消費します。クライアントが非パイプライン要求を送信していると仮定した場合は、デフォルトのMBUFサイズ16Kで、これは合計消費量32Mです。
さらに、あらゆる要求が10のフラグメントを持つ場合、メモリ消費量は320mになります。 1Kクライアント接続を処理する代わりに、10Kを処理していたとしましょう。その後、メモリ消費量は3.2gです。これで、デフォルトのMBUFサイズ16Kを使用するのではなく、512バイトを使用してから、同じシナリオに対するメモリ消費量が1000 * 2 * 512 * 10= 10M
に低下します。これが、512
のようなMBUFサイズの小さい値を選択したいのは、「大量」の接続の理由です。
他のヒント
問題は、そのデータ量を転送するときの高いメモリ使用量に関連しているように見えます。
デフォルトでは、NutCrackerは各キーに16Kバッファサイズを割り当てます。私の場合において、それは 16K * 100000= 1.5GB になるでしょう。Nutcrackerプロセスを見ているとき、私は約2GBのピークを見ました。My Cent OS VMが過負荷になり、そのスパイクを処理するのに十分なメモリがありませんでした。