前言
- 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");