RedisTemplate与Jedis和Lettuce对比以及简单示例

RedisTemplate与Jedis和Lettuce对比以及简单示例

前言
  • Lettuce 和 Jedis 都是Redis的client.
  • Redis官方推荐使用Jedis操作Redis, Jedis的方法和Redis的指令一一对应.
  • Jedis在实现为直连RedisServer, 多线程环境下线程不安全, 每个线程持有各自的Jedis实例, 当连接数量增多时资源消耗大, 连接成本高.
  • Jedis可以采用JedisPool避免多线程问题, 但不支持异步.
  • Lettuce基于Netty(StatefulRedisConnection), 是一个多线程、事件驱动的IO框架, 可在多个线程间并发访问, 线程安全.
  • Lettuce充分利用异步的优势, 减少IO阻塞时间
  • RedisTemplate是Spring对Jedis和Lettuce的高度封装, 让spring框架体系更方便接入redis功能.
  • RedisTemplate提供连接池自动管理, 同时将事务封装操作,交由容器进行处理.
  • RedisTemplate提供多种序列化策略(RedisSerializer)

Jedis

引入maven依赖

<dependency>
     <groupId>redis.clients</groupId>
     <artifactId>jedis</artifactId>
</dependency>

创建Jedis工具类

public class JedisUtil {
    private  static final JedisPool jedisPool;
    static {
        //设置基本属性
        GenericObjectPoolConfig<Jedis> poolConfig = new JedisPoolConfig();
        //最大连接数
        poolConfig.setMaxTotal(50);
        //最大空闲数
        poolConfig.setMaxIdle(10);
        jedisPool = new JedisPool(poolConfig, "XXX", 6379, 2000, "XXX");
    }
    public static Jedis getJedis(){
        return jedisPool.getResource();
    }

Jedis简单使用

@Test
void test03(){
    Jedis jedis = JedisUtil.getJedis();
    jedis.lpush("lol","abc");
    jedis.lpush("lol","def");
    jedis.lpush("lol","ghj");
    System.out.println(jedis.lrange("lol", 0, -1));
}

Lettuce

引入maven依赖

<dependency>
     <groupId>io.lettuce</groupId>
     <artifactId>lettuce-core</artifactId>
</dependency>

简单使用

RedisClient client = new RedisClient("localhost")
RedisConnection<String, String> connection = client.connect()
String value = connection.get("key")

lettuce的异步API

StatefulRedisConnection<String, String> connection = client.connect();
RedisStringAsyncCommands<String, String> async = connection.async();
RedisFuture<String> set = async.set("key", "value")
RedisFuture<String> get = async.get("key")

async.awaitAll(set, get) == true
set.get() == "OK"
get.get() == "value"

RedisTemplate基本用法

引入maven依赖, 版本继承SpringBoot版本即可

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

因为默认JDK二进制序列化, 不能跨平台使用, 需要配置RedisTemplate序列化器

package com.ctsi.ssdc.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;

/**
 * @author zhangyl
 * redis的key/value序列化配置
 * 序列化后的key/value不再是这种类型:
 * \xAC\xED\x00\x05sr\x00\x11cn.zack.pojo.User\xEE.\x92\xAE
 * 可读性更好
 */
@Configuration
public class RedisConfiguration {

    @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
        // 关联
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        // 设置key序列化器
        redisTemplate.setKeySerializer(RedisSerializer.string());
        // value序列化器(序列化为json)
        redisTemplate.setValueSerializer(RedisSerializer.json());
        // 设置hashKey序列化器
        redisTemplate.setHashKeySerializer(RedisSerializer.string());
        // 设置hashValue序列化器
        redisTemplate.setHashValueSerializer(RedisSerializer.json());
        return redisTemplate;
    }
}

常用String和Hash API

// 注入redisTemplate
@Autowired
private RedisTemplate redisTemplate;

...

/**
 * String--API
 */
// 存储K:V
redisTemplate.opsForValue().set("testKey", "testValue");
// 获取K对应的V
redisTemplate.opsForValue().get("testKey");
// 删除
redisTemplate.delete("aaa");
// K是否存在
redisTemplate.hasKey("a");
// TTL
redisTemplate.getExpire("a", TimeUnit.SECONDS);
// expire
redisTemplate.expire("a", 100,TimeUnit.SECONDS);

/**
 * Hash--API
 */
// hset
redisTemplate.opsForHash().put("num", "k1", "v1");
redisTemplate.opsForHash().put("num", "k2", "v2");
// hget
redisTemplate.opsForHash().get("num", "k1");
// hdel
redisTemplate.opsForHash().delete("num", "k1");