Redis(十七):一括操作Pipeline
5115 ワード
ほとんどの場合、リクエスト-対応するメカニズムによってredisを操作します.このモードのみを使用する一般的なステップは、jedisインスタンスを取得し、jedisのget/putメソッドを介してredisとインタラクティブになることである.redisは単一スレッドであるため、次のリクエストは、実行を続行する前のリクエストの実行が完了するまで待たなければなりません.しかし、Pipelineモードを使用すると、クライアントは、サービス側の返信を待つことなく、複数のコマンドを一度に送信することができる.これにより、ネットワーク往復時間が大幅に短縮され、システム性能が向上します.
この2つのモードの効率の違いを1つの例でテストします.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
出力結果:
1
2
テストの結果,pipelineの使用効率は通常のアクセス方式よりはるかに高いことが分かった.
では問題ですが、どのような場面でpipelineを使うのに適していますか?
信頼性に要求されるシステムもあるかもしれませんが、操作するたびに、今回の操作が成功したかどうか、データがredisに書き込まれているかどうかをすぐに知る必要があります.このようなシーンは適切ではありません.
また、システムでは、大量にデータをredisに書き込んで、一定の割合の書き込みに失敗することを許可する可能性があります.このようなシーンは使用できます.例えば、10000件がredisに入ると、2つが失敗する可能性があります.後期に補償メカニズムがあればいいです.例えば、メールグループでこのシーンを送信して、10000件をグループで送信して、第1のモードで実現すれば、この要求は、クライアントに応答するのに長い時間がかかります.この遅延は長すぎます.クライアントリクエストにタイムアウト時間が5秒設定されていると、異常が投げ出されるに違いありません.また、自分のグループでメールを送るのにリアルタイム性がそれほど高くないので、pipelineを使うのが一番です.
この2つのモードの効率の違いを1つの例でテストします.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public
class
PiplineTest {
private
static
int
count =
10000
;
public
static
void
main(String[] args){
useNormal();
usePipeline();
}
public
static
void
usePipeline(){
ShardedJedis jedis = getShardedJedis();
ShardedJedisPipeline pipeline = jedis.pipelined();
long
begin = System.currentTimeMillis();
for
(
int
i =
0
;i
pipeline.set(
"key_"
+i,
"value_"
+i);
}
pipeline.sync();
jedis.close();
System.out.println(
"usePipeline total time:"
+ (System.currentTimeMillis() - begin));
}
public
static
void
useNormal(){
ShardedJedis jedis = getShardedJedis();
long
begin = System.currentTimeMillis();
for
(
int
i =
0
;i
jedis.set(
"key_"
+i,
"value_"
+i);
}
jedis.close();
System.out.println(
"useNormal total time:"
+ (System.currentTimeMillis() - begin));
}
public
static
ShardedJedis getShardedJedis(){
JedisPoolConfig poolConfig =
new
JedisPoolConfig();
poolConfig.setMaxTotal(
2
);
poolConfig.setMaxIdle(
1
);
poolConfig.setMaxWaitMillis(
2000
);
poolConfig.setTestOnBorrow(
false
);
poolConfig.setTestOnReturn(
false
);
JedisShardInfo info1 =
new
JedisShardInfo(
"127.0.0.1"
,
6379
);
JedisShardInfo info2 =
new
JedisShardInfo(
"127.0.0.1"
,
6379
);
ShardedJedisPool pool =
new
ShardedJedisPool(poolConfig, Arrays.asList(info1,info2));
return
pool.getResource();
}
}
出力結果:
1
2
useNormal total time:
772
usePipeline total time:
112
テストの結果,pipelineの使用効率は通常のアクセス方式よりはるかに高いことが分かった.
では問題ですが、どのような場面でpipelineを使うのに適していますか?
信頼性に要求されるシステムもあるかもしれませんが、操作するたびに、今回の操作が成功したかどうか、データがredisに書き込まれているかどうかをすぐに知る必要があります.このようなシーンは適切ではありません.
また、システムでは、大量にデータをredisに書き込んで、一定の割合の書き込みに失敗することを許可する可能性があります.このようなシーンは使用できます.例えば、10000件がredisに入ると、2つが失敗する可能性があります.後期に補償メカニズムがあればいいです.例えば、メールグループでこのシーンを送信して、10000件をグループで送信して、第1のモードで実現すれば、この要求は、クライアントに応答するのに長い時間がかかります.この遅延は長すぎます.クライアントリクエストにタイムアウト時間が5秒設定されていると、異常が投げ出されるに違いありません.また、自分のグループでメールを送るのにリアルタイム性がそれほど高くないので、pipelineを使うのが一番です.