Redis客戶端Lettuce源碼「一」Jedis vs Lettuce

@[toc]

基本實現對比


Jedis
Lettuce
支持JDK版本
JDK6+
JDK8+
IO模型
BIO
NIO(Netty)
連接複用
連接池
單一長連接
線程安全
Jedis線程不安全
StatefulRedisConnection線程安全


性能對比

Redis-Server測試環境:

  • 服務器配置:四核16G
  • Redis版本:5.0.5
  • Redis配置文件:默認配置

Redis-Client測試環境:

  • 服務器配置:四核16G
  • JDK版本:JDK8、基於Springboot 2.1.6.RELEASE版本的RedisTemplate測試
  • Jedis連接池配置:max:50,min:10
  • 測試工具:JMH(https://www.jianshu.com/p/2a83cc26d0e9)

如下圖所示,對於各種大小value的get、set測試,二者無論是響應時間還是吞吐量,都相差不大,沒有數量級的差異。(影響測試結果的因素有很多,存在一些偶然因素,所以這個結果不能說明Lettuce的響應性能就比Jedis好)同時也能看出來隨著value大小的增加,無論是吞吐量還是響應性能都急劇的下降,所以我們在開發過程中存入Redis中的數據要儘可能的小。

Redis客戶端Lettuce源碼「一」Jedis vs Lettuce

Jedis的基本用法

pom添加依賴

<code>    <dependencies>        <dependency>            <groupid>redis.clients/<groupid>            <artifactid>jedis/<artifactid>            <version>3.1.0/<version>        /<dependency>    /<dependencies>/<code>

使用Jedis的示例代碼

<code>public class JedisSimpleUse {    private String host = "localhost";    private int port = 6379;    private String password = "password";    /**     * 直接構建Jedis實例的方式使用Jedis     */    public void useJedis() {        //指定Redis服務Host和port, Jedis是非線程安全的,只能單個線程訪問,每個線程都要單獨構建Jedis對象        Jedis jedis = new Jedis(host, port);        try {            //如果Redis服務連接需要密碼,指定密碼            jedis.auth(password);            //訪問Redis服務            String value = jedis.get("key");        } finally {            //使用完關閉連接            jedis.close();        }    }    private JedisPool jedisPool;    /**     * 初始化JedisPool     */    public void initJedisPool() {        GenericObjectPoolConfig genericObjectPool = new GenericObjectPoolConfig();        jedisPool = new JedisPool(genericObjectPool, host, port, Protocol.DEFAULT_TIMEOUT, password);    }    /**     * 基於連接池的方式使用Jedis     */    public void useJedisPool() {        Jedis jedis = jedisPool.getResource();        try {            //訪問Redis服務            String value = jedis.get("key");        } finally {            //使用完關閉連接            jedis.close();        }    }    public static void main(String[] args) {        JedisSimpleUse jedisSimpleUse = new JedisSimpleUse();        //調用Jedis實例方法        jedisSimpleUse.useJedis();        // 初始化JedisPool,只需要初始化一次        jedisSimpleUse.initJedisPool();        // 多次基於JedisPool調用Redis        jedisSimpleUse.useJedisPool();        jedisSimpleUse.useJedisPool();    }}/<code>

Jedis配合Springboot RedisTemplate使用

pom添加依賴

<code><dependencymanagement>        <dependencies>            <dependency>                <groupid>org.springframework.boot/<groupid>                <artifactid>spring-boot-dependencies/<artifactid>                <version>2.1.6.RELEASE/<version>                <scope>import/<scope>                <type>pom/<type>            /<dependency>        /<dependencies>    /<dependencymanagement><dependencies>        <dependency>            <groupid>redis.clients/<groupid>            <artifactid>jedis/<artifactid>        /<dependency>        <dependency>            <groupid>org.springframework.boot/<groupid>            <artifactid>spring-boot-starter-data-redis/<artifactid>                        <exclusions>                <exclusion>                    <groupid>io.lettuce/<groupid>                    <artifactid>lettuce-core/<artifactid>                /<exclusion>            /<exclusions>        /<dependency>    /<dependencies>/<code>

application.properties配置文件

<code>spring.redis.host=localhostspring.redis.port=6379spring.redis.password=password/<code>

測試代碼

<code>@Component@SpringBootApplicationpublic class JedisWithRedisTemplate {    /**     * SpringBoot autoconfigure在classpath中發現Jedis class會自動注入StringRedisTemplate     */    @Autowired    StringRedisTemplate redisTemplate;    public void testRedisTemplate() {        //redisTemplate封裝了對Jedis的獲取和釋放、並使用JedisPool連接池        redisTemplate.opsForValue().set("key", "val123");        String value = redisTemplate.opsForValue().get("key");        System.out.println("get redis value with RedisTemplate, value is :" + value);        redisTemplate.delete("key");    }    public static void main(String[] args) {        // 創建SpringApplicationContext容器        ConfigurableApplicationContext applicationContext = SpringApplication.run(JedisWithRedisTemplate.class, args);        //從容器中獲取測試Bean        JedisWithRedisTemplate jedisWithRedisTemplate = applicationContext.getBean(JedisWithRedisTemplate.class);        jedisWithRedisTemplate.testRedisTemplate();    }}/<code>

Lettuce的基本用法

pom添加依賴

<code><dependencies>        <dependency>            <groupid>io.lettuce/<groupid>            <artifactid>lettuce-core/<artifactid>        /<dependency>    /<dependencies>/<code>

測試代碼

<code>public class LettuceSimpleUse {    private void testLettuce() throws ExecutionException, InterruptedException {        //構建RedisClient對象,RedisClient包含了Redis的基本配置信息,可以基於RedisClient創建RedisConnection        RedisClient client = RedisClient.create("redis://localhost");        //創建一個線程安全的StatefulRedisConnection,可以多線程併發對該connection操作,底層只有一個物理連接.        StatefulRedisConnection<string> connection = client.connect();        //獲取SyncCommand。Lettuce支持SyncCommand、AsyncCommands、ActiveCommand三種command        RedisStringCommands<string> sync = connection.sync();        String value = sync.get("key");        System.out.println("get redis value with lettuce sync command, value is :" + value);        //獲取SyncCommand。Lettuce支持SyncCommand、AsyncCommands、ActiveCommand三種command        RedisAsyncCommands<string> async = connection.async();        RedisFuture<string> getFuture = async.get("key");        value = getFuture.get();        System.out.println("get redis value with lettuce sync command, value is :" + value);    }public static void main(String[] args) throws ExecutionException, InterruptedException {        new LettuceSimpleUse().testLettuce();    }}/<string>/<string>/<string>/<string>/<code>

Lettuce配合Springboot RedisTemplate使用

pom配置文件

<code>    <dependencies>        <dependency>            <groupid>io.lettuce/<groupid>            <artifactid>lettuce-core/<artifactid>        /<dependency>        <dependency>            <groupid>org.springframework.boot/<groupid>            <artifactid>spring-boot-starter-data-redis/<artifactid>        /<dependency>    /<dependencies><dependencymanagement>        <dependencies>            <dependency>                <groupid>org.springframework.boot/<groupid>                <artifactid>spring-boot-dependencies/<artifactid>                <version>2.1.6.RELEASE/<version>                <scope>import/<scope>                <type>pom/<type>            /<dependency>        /<dependencies>    /<dependencymanagement>/<code>

application.properties

<code>spring.redis.host=localhostspring.redis.port=6379spring.redis.password=passwords/<code>

測試代碼

<code>@SpringBootApplicationpublic class LettuceWithRedisTemplate {    /**     * SpringBoot autoconfigure在classpath中發現Lettuce class會自動注入StringRedisTemplate     */    @Autowired    StringRedisTemplate redisTemplate;    public void testRedisTemplate() {        //redisTemplate封裝了對Lettuce StatefulRedisConnection的調用        redisTemplate.opsForValue().set("key", "val123");        String value = redisTemplate.opsForValue().get("key");        System.out.println("get redis value with RedisTemplate, value is :" + value);        redisTemplate.delete("key");    }    public static void main(String[] args) {        // 創建SpringApplicationContext容器        ConfigurableApplicationContext applicationContext = SpringApplication.run(LettuceWithRedisTemplate.class, args);        //從容器中獲取測試Bean        LettuceWithRedisTemplate lettuceWithRedisTemplate = applicationContext.getBean(LettuceWithRedisTemplate.class);        lettuceWithRedisTemplate.testRedisTemplate();    }}/<code>


分享到:


相關文章: