jedis和lettuce的性能测试

参考文章:https://blog.csdn.net/u011499747/article/details/83055859
不过这里面的代码感觉不太对,所以按照这个思路自己写代码做了下测试

1、添加依赖

添加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>6.0.2.RELEASE</version>
</dependency>

开始lettuce用5.0版本,发现性能很差,改用6.0之后,性能提升很多,因此这里采用6.0版本进行对比(jedis升级前后性能相差不大)

2、代码编写

2.1 Jedis:

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPoolConfig;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@BenchmarkMode(Mode.Throughput)
@Warmup(iterations = 1)
@Threads(20)
@State(Scope.Benchmark)
@Measurement(iterations = 10, time = 60000, timeUnit = TimeUnit.MILLISECONDS)
@OutputTimeUnit(TimeUnit.SECONDS)
public class JedisJmhTest {

    private JedisCluster jc;

    @Setup
    public void setup() {
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(60);
        config.setMaxIdle(10);
        config.setMinIdle(2);
        config.setMaxWaitMillis(3000);

        Set<HostAndPort> jedisClusterNodes = new HashSet<>();
        jedisClusterNodes.add(new HostAndPort(redishost, port));
        jc = new JedisCluster(jedisClusterNodes, 2000, 2000, 5, password, config);
    }

    @Benchmark
    public void get() {
        jc.get("a");
    }

    public static void main(String[] args) throws RunnerException {
        Options options = new OptionsBuilder().include(JedisJmhTest.class.getSimpleName())
                .output("d:/data/logs/benchmark/jedis-Throughput.log").forks(1).build();
        new Runner(options).run();
    }

}

这里使用的redis集群,3主3从,因此maxTotal要设置大一点,太小的话会导致吞吐量上不来

2.2 Lettuce:

import io.lettuce.core.cluster.RedisClusterClient;
import io.lettuce.core.cluster.api.StatefulRedisClusterConnection;
import io.lettuce.core.cluster.api.sync.RedisAdvancedClusterCommands;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import java.util.concurrent.TimeUnit;

@BenchmarkMode(Mode.Throughput)
@Warmup(iterations = 1)
@Threads(20)
@State(Scope.Benchmark)
@Measurement(iterations = 10, time = 60000, timeUnit = TimeUnit.MILLISECONDS)
@OutputTimeUnit(TimeUnit.SECONDS)
public class LettuceSyncJmhTest {
    RedisClusterClient client;
    private StatefulRedisClusterConnection<String, String> connection;
    @Setup
    public void setup() {
        client = RedisClusterClient .create("redis://password@redishost:part/0");
        connection = client.connect();
    }

    @Benchmark
    public void get() {
        RedisAdvancedClusterCommands<String, String> commands = connection.sync();
        commands.get("a");
    }

    @TearDown
    public void tearDown() {
        connection.close();
        client.shutdown();
    }


    public static void main(String[] args) throws RunnerException {
        Options options = new OptionsBuilder().include(LettuceSyncJmhTest.class.getSimpleName())
                .output("d:/data/logs/benchmark/lettuce-Throughput.log").forks(1).build();
        new Runner(options).run();
    }

}

Lettuce主要测试同步调用的性能

3、测试结果

Jedis:

# Warmup Iteration   1: 2939.828 ops/s
Iteration   1: 3525.044 ops/s
Iteration   2: 3493.547 ops/s
Iteration   3: 3659.585 ops/s
Iteration   4: 3815.806 ops/s
Iteration   5: 3803.759 ops/s
Iteration   6: 3674.697 ops/s
Iteration   7: 3636.788 ops/s
Iteration   8: 3674.486 ops/s
Iteration   9: 3687.034 ops/s
Iteration  10: 3582.874 ops/s

Result "com.tianzy.JedisJmhTest.get":
  3655.362 ±(99.9%) 157.996 ops/s [Average]
  (min, avg, max) = (3493.547, 3655.362, 3815.806), stdev = 104.505
  CI (99.9%): [3497.366, 3813.358] (assumes normal distribution)

Jedis JVM监控

Lettuce:

# Warmup Iteration   1: 3332.678 ops/s
Iteration   1: 3378.788 ops/s
Iteration   2: 3363.920 ops/s
Iteration   3: 3346.096 ops/s
Iteration   4: 3271.721 ops/s
Iteration   5: 3134.163 ops/s
Iteration   6: 3145.072 ops/s
Iteration   7: 3268.907 ops/s
Iteration   8: 3242.946 ops/s
Iteration   9: 3194.674 ops/s
Iteration  10: 3464.621 ops/s

Result "com.tianzy.LettuceSyncJmhTest.get":
  3281.091 ±(99.9%) 162.177 ops/s [Average]
  (min, avg, max) = (3134.163, 3281.091, 3464.621), stdev = 107.270
  CI (99.9%): [3118.913, 3443.268] (assumes normal distribution)

Lettuce JVM监控

以上结果是本地执行的,两者性能看起来差不多,感觉受网络影响比较大,同一个类多次执行偏差都会比较大。

从JVM监控来看,lettuce对内存的使用更高。使用的jdk8默认JVM参数,自动调整堆内存,lettuce使用的堆内存和metaspace更大,GC也更频繁。不过相对来说,这点影响可以忽略不计。

单独从性能表现来看,lettuce并没有明显优势。
Lettuce主要优势在于:只需要跟每个redis节点保持一个连接即可,而jedis可能需要几十个。在实际生产场景,会有很多应用连接到同一个redis集群,使用jedis可能导致redis连接数过多,而lettuce则没有这个问题。
还有lettuce支持响应式编程,本次只是使用了同步api,所以性能优势不明显,在响应式编程的场景,会更有用武之地。



前面的测试结果是本地的,受网络等原因不够准确,试一下在服务器上执行

pom.xml文件中添加:

<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.0</version>
                <configuration>
                    <compilerVersion>1.8</compilerVersion>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>2.0</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <finalName>microbenchmarks</finalName>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>org.openjdk.jmh.Main</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

        </plugins>
    </build>

然后执行 mvn clean verify进行打包,target目录下会生成microbenchmarks.jar,上传到服务器

$ java -jar microbenchmarks.jar -l
Benchmarks: 
com.tianzy.JedisJmhTest.get
com.tianzy.LettuceSyncJmhTest.get

分别执行java -jar microbenchmarks.jar com.tianzy.LettuceSyncJmhTest.get、java -jar microbenchmarks.jar com.tianzy.JedisJmhTest.get,即可开启执行。

Jedis:

# Warmup Iteration   1: 35730.066 ops/s
Iteration   1: 37333.325 ops/s
Iteration   2: 36433.292 ops/s
Iteration   3: 36132.089 ops/s
Iteration   4: 37523.689 ops/s
Iteration   5: 35924.923 ops/s
Iteration   6: 35771.176 ops/s
Iteration   7: 36868.176 ops/s
Iteration   8: 33352.998 ops/s
Iteration   9: 35858.396 ops/s
Iteration  10: 34711.806 ops/s

Result "com.tianzy.JedisJmhTest.get":
  35990.987 ±(99.9%) 1872.209 ops/s [Average]
  (min, avg, max) = (33352.998, 35990.987, 37523.689), stdev = 1238.350
  CI (99.9%): [34118.778, 37863.196] (assumes normal distribution)

Lettuce:

# Warmup Iteration   1: 14142.306 ops/s
Iteration   1: 16096.286 ops/s
Iteration   2: 16054.059 ops/s
Iteration   3: 16509.278 ops/s
Iteration   4: 15447.965 ops/s
Iteration   5: 15807.480 ops/s
Iteration   6: 15885.412 ops/s
Iteration   7: 15649.933 ops/s
Iteration   8: 15680.563 ops/s
Iteration   9: 16211.962 ops/s
Iteration  10: 14812.771 ops/s

Result "com.tianzy.LettuceSyncJmhTest.get":
  15815.571 ±(99.9%) 706.501 ops/s [Average]
  (min, avg, max) = (14812.771, 15815.571, 16509.278), stdev = 467.307
  CI (99.9%): [15109.070, 16522.072] (assumes normal distribution)

惊呆了,Jedis性能有Lettuce的2倍多。经过多次测试,结论是Jedis确实比Lettuce快多了。

查看源码分析和推测:
Jedis直接采用阻塞模型,代码比较简单,也比较高效。
Lettuce采用的Netty,代码较复杂,使用了反射、异步,同步线程中调用异步线程,又要等待异步线程执行完,性能损耗反而比较大。

进一步跟踪Lettuce的代码发现,在使用同步调用时,是会auto flush的,即write完立刻flush。查看官网文档,这种模式是会影响性能的,但是同步调用又必须得这么做。

大概得出结论:Lettuce对于同步调用在性能上有劣势,优势在于响应式异步编程。

最后,我决定还是继续用Jedis吧。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值