Jedis 和lettcue的测试

 

Redis 3种Java客户端的比较(Jedis、lettuce、Redisson)

Jedis api 在线网址:http://tool.oschina.net/uploads/apidocs/redis/clients/jedis/Jedis.html

redisson 官网地址:https://redisson.org/

redisson git项目地址:https://github.com/redisson/redisson

lettuce 官网地址:https://lettuce.io/

lettuce git项目地址:https://github.com/lettuce-io/lettuce-core

 

概念:

  Jedis:是RedisJava实现客户端,提供了比较全面的Redis命令的支持,

  Redisson:实现了分布式和可扩展的Java数据结构。

  Lettuce:高级Redis客户端,用于线程安全同步,异步和响应使用,支持集群,Sentinel,管道和编码器。

优点:

  Jedis:比较全面的提供了Redis的操作特性

  Redisson:促使使用者对Redis的关注分离,提供很多分布式相关操作服务,例如,分布式锁,分布式集合,可通过Redis支持延迟队列

  Lettuce:主要在一些分布式缓存框架上使用比较多

可伸缩:

Jedis:使用阻塞的I/O,且其方法调用都是同步的,程序流需要等到sockets处理完I/O才能执行,不支持异步。Jedis客户端实例不是线程安全的,所以需要通过连接池来使用Jedis

Redisson:基于Netty框架的事件驱动的通信层,其方法调用是异步的。RedissonAPI是线程安全的,所以可以操作单个Redisson连接来完成各种操作

Lettuce:基于Netty框架的事件驱动的通信层,其方法调用是异步的。LettuceAPI是线程安全的,所以可以操作单个Lettuce连接来完成各种操作

 

结论:

建议使用:Jedis + Redisson

 

1.准备工作

本地需要安装Redis,使用JMH做基准测试的框架:

<dependency>
    <groupId>org.openjdk.jmh</groupId>
    <artifactId>jmh-core</artifactId>
    <version>1.21</version>
</dependency>
<dependency>
    <groupId>org.openjdk.jmh</groupId>
    <artifactId>jmh-generator-annprocess</artifactId>
    <version>1.21</version>
    <scope>provided</scope>
</dependency>

项目添加Jedis和Lettuce的依赖:

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.9.0</version>
</dependency>
<dependency>
    <groupId>io.lettuce</groupId>
    <artifactId>lettuce-core</artifactId>
    <version>5.0.3.RELEASE</version>
</dependency>

如果你对JMH不是很熟悉,建议你去看看Code Tools: jmh,和samples

2.编写测试代码

2.1 Jedis

@BenchmarkMode(Mode.Throughput)
@Warmup(iterations = 1)
@Threads(100)
@State(Scope.Thread)
@Measurement(iterations = 2, time = 600, timeUnit = TimeUnit.MILLISECONDS)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public class JedisStudy {
    private static final int LOOP = 1;
    private Jedis jedis;
    @Setup
    public void setup() {
        jedis = new Jedis("127.0.0.1", 6379);
    }
    @Benchmark
    public void get() {
        for (int i = 0; i < LOOP; ++i) {
            jedis.get("a");
        }
    }
}
public static void main(String[] args) throws RunnerException {
    Options options = new OptionsBuilder().include(JedisStudy.class.getSimpleName())
            .output("benchmark/jedis-Throughput.log").forks(1).build();
    new Runner(options).run();
}

这里用到的注解,其中@OutputTimeUnit(TimeUnit.MILLISECONDS)很容易理解,就是测试结果的单位,@Threads(100)是开启多少个线程测试;@Warmup(iterations = 1)是预热的循环次数;@BenchmarkMode(Mode.Throughput)是测试的模式,可以测试吞吐,延时等;@Measurement(iterations = 2, time = 600, timeUnit = TimeUnit.MILLISECONDS)是测试的循环次数,以及时长;其中比较难以理解的就是@State(Scope.Thread),这里我简单描述下吧,@State(Scope.Thread)和下面的@Setup配合使用,意思是每个测试线程,都会使用独立的一个变量,这个变量就是Jedis jedis,使用@Setup所修饰的方法来做初始化。

参考JMHSample_03_States JMHSample_04_DefaultState

其中因为Jedis是线程不安全的,所以每个线程使用的都是一个单独的Jedis对象,这里可以使用Pool来优化,读者如果感兴趣,可以尝试。

2.2 Lettuce

@BenchmarkMode(Mode.Throughput)
@Warmup(iterations = 1)
@Threads(100)
@State(Scope.Benchmark)
@Measurement(iterations = 2, time = 600, timeUnit = TimeUnit.MILLISECONDS)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public class LettuceAsyncStudy {
    private static final int LOOP = 1;
    private StatefulRedisConnection<String, String> connection;
    @Setup
    public void setup() {
        RedisClient client = RedisClient.create("redis://localhost");
        connection = client.connect();
    }
    @Benchmark
    public void get() throws ExecutionException, InterruptedException {
        RedisAsyncCommands<String, String> commands = connection.async();
        List<RedisFuture<String>> redisFutureList = new ArrayList<>();
        for (int i = 0; i < LOOP; ++i) {
            RedisFuture<String> future = commands.get("a");
            redisFutureList.add(future);
            future.get();
        }
        redisFutureList.forEach(f -> {
            try {
                f.get();
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }
}
public static void main(String[] args) throws RunnerException {
    Options options = new OptionsBuilder().include(LettuceAsyncStudy.class.getSimpleName())
            .output("benchmark/lettuceAsync-Throughput.log").forks(1).build();
    new Runner(options).run();
}

这里和上面Jedis的区别就是@State(Scope.Benchmark),其实就是StatefulRedisConnection<String, String> connection这个对象是所有测试线程共享的,因为Lettuce的StatefulRedisConnection是线程的安全的,所以可以这么用。

3.测试结果

Client线程数(并发数)每次测试方法里循环执行get的次数Throughput(ops/ms)
Jedis100146.628
Lettuce1001106.589
--------
Jedis100105.307
Lettuce1001014.802
--------
Jedis1001000.483
Lettuce1001001.599



作者:我是杨正
链接:https://www.jianshu.com/p/7a1f8c69a8cb
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值