java redis管道_java – 为什么在redis中使用管道时有100,000条记录这么慢?

在编写此类基准测试之前,您需要考虑几点(尤其是使用JVM的基准测试):

>在大多数(物理)机器上,当使用流水线时,Redis能够处理超过100K的操作数/秒.您的基准仅处理100K项目,因此它的持续时间不足以产生有意义的结果.此外,JIT的连续阶段没有时间进入.

>绝对时间不是一个非常相关的指标.在保持基准运行至少10秒的同时显示吞吐量(即每秒的操作次数)将是更好且更稳定的度量.

>你的内循环会产生大量垃圾.如果您计划对Jedis Redis进行基准测试,那么您需要将自己程序的开销保持在较低水平.

>因为你已经将所有内容都定义到main函数中,所以你的循环不会被JIT编译(取决于你使用的JVM).只有内部方法调用可能是.如果希望JIT高效,请确保将代码封装到可由JIT编译的方法中.

>可选地,您可能希望在执行实际测量之前添加预热阶段,以避免计算使用裸骨解释器运行第一次迭代的开销以及JIT本身的成本.

现在,关于Redis流水线,您的管道太长了.管道中的100K命令意味着Jedis必须在向Redis发送任何内容之前构建一个6MB的缓冲区.这意味着套接字缓冲区(在客户端,可能在服务器端)将饱和,并且Redis也必须处理6 MB通信缓冲区.

此外,您的基准测试仍然是同步的(使用管道并不会神奇地使其异步).换句话说,在您的管道的最后一个查询被发送到Redis之前,Jedis不会开始阅读回复.当管道太长时,它有可能阻塞事物.

考虑将管道的大小限制为100-1000个操作.当然,它会产生更多的往返,但通信栈的压力将降低到可接受的水平.例如,考虑以下程序:

import redis.clients.jedis.*;

import java.util.*;

public class TestPipeline {

/**

* @param args

*/

int i = 0;

Map map = new HashMap();

ShardedJedis jedis;

// Number of iterations

// Use 1000 to test with the pipeline, 100 otherwise

static final int N = 1000;

public TestPipeline() {

JedisShardInfo si = new JedisShardInfo("127.0.0.1", 6379);

List list = new ArrayList();

list.add(si);

jedis = new ShardedJedis(list);

}

public void push( int n ) {

ShardedJedisPipeline pipeline = jedis.pipelined();

for ( int k = 0; k < n; k++) {

map.put("id", "" + i);

map.put("name", "lyj" + i);

pipeline.hmset("m" + i, map);

++i;

}

pipeline.sync();

}

public void push2( int n ) {

for ( int k = 0; k < n; k++) {

map.put("id", "" + i);

map.put("name", "lyj" + i);

jedis.hmset("m" + i, map);

++i;

}

}

public static void main(String[] args) {

TestPipeline obj = new TestPipeline();

long startTime = System.currentTimeMillis();

for ( int j=0; j

// Use push2 instead to test without pipeline

obj.push(1000);

// Uncomment to see the acceleration

//System.out.println(obj.i);

}

long endTime = System.currentTimeMillis();

double d = 1000.0 * obj.i;

d /= (double)(endTime - startTime);

System.out.println("Throughput: "+d);

}

}

使用此程序,您可以使用或不使用流水线进行测试.使用流水线时,请务必增加迭代次数(N参数),以使其运行至少10秒.如果你在循环中取消注释println,你会发现程序在开始时很慢并且随着JIT开始优化而变得更快(这就是为什么程序应该运行至少几秒钟以产生有意义的结果).

在我的硬件(旧的Athlon盒子)上,当使用管道时,我可以获得8-9倍的吞吐量.通过优化内循环中的键/值格式化并添加预热阶段,可以进一步改进程序.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值