Java操作Redis
Java操作Redis
分类
-
Jedis (官方推荐)
-
特点:轻量级、同步阻塞、直接操作 Redis 命令
-
导入依赖
-
<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>4.4.3</version> </dependency>
-
-
Lettuce (Spring 官方推荐)
-
特点:基于 Netty 实现异步非阻塞、支持 Reactive 编程
-
依赖
-
<dependency> <groupId>io.lettuce</groupId> <artifactId>lettuce-core</artifactId> <version>6.2.6.RELEASE</version> </dependency>
-
-
Spring Data Redis (整合框架)
-
特点:封装了 Jedis/Lettuce,提供模板化操作
-
依赖
-
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
-
Jedis
-
导入依赖
-
启动Redis服务器
-
连接到 Redis
-
import redis.clients.jedis.Jedis; public class JedisExample { public static void main(String[] args) { // 1. 创建 Jedis 实例(默认连接本地 6379 端口) try (Jedis jedis = new Jedis("localhost", 6379)) { // 2. 认证(如果 Redis 设置了密码) jedis.auth("your_password"); // 3. 测试连接 System.out.println("连接成功: " + jedis.ping()); } } }
-
-
基本操作
-
字符串(String)
-
jedis.set("key", "value"); String value = jedis.get("key"); System.out.println(value); // 输出 "value" // 设置过期时间(单位:秒) jedis.setex("temp_key", 60, "temp_value"); // 设置键值对,并指定过期时间(60秒),仅在键不存在时设置 SetParams params = SetParams.setParams().nx().ex(60); String result = jedis.set("temp_key", "temp_value", params);
-
-
哈希(Hash)
-
jedis.hset("user:1", "name", "Alice"); jedis.hset("user:1", "age", "30"); Map<String, String> user = jedis.hgetAll("user:1"); System.out.println(user); // {name=Alice, age=30}
-
-
列表(List)
-
jedis.lpush("mylist", "item1", "item2"); List<String> list = jedis.lrange("mylist", 0, -1); // 获取所有元素 System.out.println(list); // [item2, item1]
-
-
集合(Set)
-
jedis.sadd("myset", "a", "b", "c"); Set<String> set = jedis.smembers("myset"); System.out.println(set); // [a, b, c]
-
-
有序集合(Sorted Set)
-
jedis.zadd("ranking", 100, "player1"); jedis.zadd("ranking", 90, "player2"); List<String> topPlayers = jedis.zrevrange("ranking", 0, 1); // 获取前两名 System.out.println(topPlayers); // [player1, player2]
-
-
-
事务(Transaction)
-
try (Jedis jedis = new Jedis("localhost")) { Transaction tx = jedis.multi(); // 开启事务 tx.set("a", "1"); tx.incr("a"); tx.get("a"); List<Object> results = tx.exec(); // 执行事务 // 输出结果:[OK, 2, 2] System.out.println(results); }
-
-
连接池(JedisPool)
-
推荐使用连接池管理资源,避免频繁创建和销毁连接:
-
import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; public class JedisPoolDemo { public static void main(String[] args) { JedisPoolConfig config = new JedisPoolConfig(); config.setMaxTotal(100); // 最大连接数 config.setMaxIdle(20); // 最大空闲连接数 try (JedisPool jedisPool = new JedisPool(config, "localhost", 6379)) { try (Jedis jedis = jedisPool.getResource()) { jedis.set("pool_key", "pool_value"); System.out.println(jedis.get("pool_key")); } } } } -
JedisPool的构造函数支持以下参数:config:连接池配置(JedisPoolConfig)。host:Redis 服务器地址(如localhost)。port:Redis 服务器端口(默认6379)。timeout:连接超时时间(单位:毫秒)。password:Redis 服务器密码。
-
-
注意事项
- 异常处理:所有操作都可能抛出
JedisConnectionException,需捕获处理。 - 资源释放:使用
try-with-resources或手动关闭Jedis实例。 - 线程安全:Jedis 实例非线程安全,每个线程应使用独立实例或连接池。
- 性能优化:合理配置连接池参数,避免资源耗尽。
- 异常处理:所有操作都可能抛出
Spring Data Redis
-
启动Redis服务
-
添加依赖
-
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
-
-
配置 Redis 连接:
-
spring: redis: host: localhost port: 6379 password: your_password timeout: 2000ms
-
-
Spring Data Redis 的核心组件包括:
RedisTemplate:用于操作 Redis 的模板类,支持多种数据类型的操作。StringRedisTemplate:专门用于操作字符串类型的模板类。RedisRepository:用于实现 Redis 数据访问的仓库接口。
-
配置 RedisTemplate
-
在 Spring Boot 中,默认会自动配置
RedisTemplate和StringRedisTemplate。如果需要自定义配置,可以手动定义 Bean -
@Configuration public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(connectionFactory); // 设置键和值的序列化器 template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(new StringRedisSerializer()); return template; } }
-
-
Lettuce 是一个基于 Netty 的高性能 Redis 客户端,它本身是线程安全的,默认情况下不需要连接池,因为它的连接是异步的且可以共享。
-
Spring Boot:自动配置连接池(如果需要),具体行为取决于使用的客户端(Lettuce 或 Jedis)。
-
如果没有特殊需求,直接使用 Spring Boot 的默认配置即可,它会处理好连接池的问题。如果需要优化性能或调整连接池参数,可以通过配置文件或代码进行自定义配置。
RedisTemplate
-
RedisTemplate是 Spring Data Redis 提供的一个核心工具类,用于与 Redis 进行交互。它封装了 Redis 的常用操作,并提供了丰富的 API 来操作各种数据类型(如字符串、哈希、列表、集合、有序集合等)。 -
RedisTemplate 的基本配置
-
在使用
RedisTemplate之前,通常需要对其进行配置,包括设置连接工厂和序列化器。 -
RedisTemplate默认使用 JdkSerializationRedisSerializer,这会将对象序列化为字节数组。这种序列化方式可能会导致存储的数据不易读,并且在跨语言环境中不兼容。 -
序列化后的数据体积较大,可能会影响性能。
-
@Configuration public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(connectionFactory); /* 设置键和值的序列化器 template.setKeySerializer(new StringRedisSerializer()); 设置的是 Redis 中所有普通键(key)的序列化器。这里的“普通键”指的是 Redis 中最常见的键类型,比如字符串、列表、集合、有序集合等数据结构的键。*/ template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); // 设置哈希键和值的序列化器 /* 哈希类型(hash)在 Redis 中是一种特殊的数据结构,它包含键值对。因此,RedisTemplate 提供了 setHashKeySerializer 和 setHashValueSerializer 来分别处理哈希键和哈希值的序列化。 */ template.setHashKeySerializer(new StringRedisSerializer()); template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); return template; } } -
StringRedisSerializer:用于序列化键和哈希键,确保键以字符串形式存储。 -
GenericJackson2JsonRedisSerializer:用于序列化值和哈希值,支持将对象序列化为 JSON 格式。
-
-
RedisTemplate 的常用操作
-
操作键(Key)
-
RedisTemplate提供了直接操作键的方法。 -
public void keyOperations() { // 设置键值对 redisTemplate.opsForValue().set("key1", "value1"); // 检查键是否存在 boolean exists = redisTemplate.hasKey("key1"); System.out.println("Key exists: " + exists); // 设置键的过期时间 redisTemplate.expire("key1", 60, TimeUnit.SECONDS); // 获取键的剩余过期时间 Long ttl = redisTemplate.getExpire("key1"); System.out.println("TTL: " + ttl); // 删除键 redisTemplate.delete("key1"); }
-
-
操作字符串(String)
-
字符串是 Redis 中最基本的数据类型,
RedisTemplate提供了opsForValue()方法来操作字符串。 -
@Autowired private RedisTemplate<String, Object> redisTemplate; public void stringOperations() { // 设置值 redisTemplate.opsForValue().set("name", "Alice"); // 获取值 String name = (String) redisTemplate.opsForValue().get("name"); System.out.println("Name: " + name); // 删除键 redisTemplate.delete("name"); // 检查键是否存在 boolean exists = redisTemplate.hasKey("name"); System.out.println("Key exists: " + exists); }
-
-
操作哈希(Hash)
-
哈希用于存储字段和值的映射,
RedisTemplate提供了opsForHash()方法来操作哈希。 -
public void hashOperations() { String key = "user:1"; // 设置哈希字段 redisTemplate.opsForHash().put(key, "name", "Bob"); redisTemplate.opsForHash().put(key, "age", 25); // 获取哈希字段 String name = (String) redisTemplate.opsForHash().get(key, "name"); int age = (int) redisTemplate.opsForHash().get(key, "age"); System.out.println("Name: " + name + ", Age: " + age); // 获取所有字段和值 Map<Object, Object> user = redisTemplate.opsForHash().entries(key); System.out.println("User: " + user); // 删除哈希字段 redisTemplate.opsForHash().delete(key, "age"); }
-
-
操作列表(List)
-
列表是一个有序的字符串集合,
RedisTemplate提供了opsForList()方法来操作列表。 -
public void listOperations() { String key = "tasks"; // 从左侧插入元素 redisTemplate.opsForList().leftPush(key, "Task 1"); redisTemplate.opsForList().leftPush(key, "Task 2"); // 从右侧插入元素 redisTemplate.opsForList().rightPush(key, "Task 3"); // 获取列表范围 List<Object> tasks = redisTemplate.opsForList().range(key, 0, -1); System.out.println("Tasks: " + tasks); // 从左侧弹出元素 String task = (String) redisTemplate.opsForList().leftPop(key); System.out.println("Popped task: " + task); }
-
-
操作集合(Set)
-
集合是一个无序的字符串集合,且元素唯一,
RedisTemplate提供了opsForSet()方法来操作集合。 -
public void setOperations() { String key = "tags"; // 添加元素 redisTemplate.opsForSet().add(key, "Java", "Redis", "Spring"); // 获取所有元素 Set<Object> tags = redisTemplate.opsForSet().members(key); System.out.println("Tags: " + tags); // 检查元素是否存在 boolean exists = redisTemplate.opsForSet().isMember(key, "Java"); System.out.println("Java exists: " + exists); // 删除元素 redisTemplate.opsForSet().remove(key, "Spring"); }
-
-
操作有序集合(ZSet)
-
有序集合是一个有序的字符串集合,每个元素关联一个分数,
RedisTemplate提供了opsForZSet()方法来操作有序集合。 -
public void zSetOperations() { String key = "rank"; // 添加元素 redisTemplate.opsForZSet().add(key, "Alice", 100); redisTemplate.opsForZSet().add(key, "Bob", 90); redisTemplate.opsForZSet().add(key, "Charlie", 80); // 获取元素排名(按分数从低到高) Long rank = redisTemplate.opsForZSet().rank(key, "Bob"); System.out.println("Bob's rank: " + rank); // 获取元素分数 Double score = redisTemplate.opsForZSet().score(key, "Alice"); System.out.println("Alice's score: " + score); // 获取范围内的元素(按分数从低到高) Set<Object> topUsers = redisTemplate.opsForZSet().range(key, 0, 1); System.out.println("Top users: " + topUsers); }
-
-
-
事务支持
-
RedisTemplate支持事务操作,可以通过multi()和exec()方法实现。 -
public void transactionOperations() { redisTemplate.execute(new SessionCallback<Object>() { @Override public Object execute(RedisOperations operations) throws DataAccessException { operations.multi(); // 开启事务 operations.opsForValue().set("key1", "value1"); operations.opsForValue().set("key2", "value2"); return operations.exec(); // 提交事务 } }); }
-
StringRedisTemplate
-
StringRedisTemplate是 Spring Data Redis 提供的一个专门用于处理字符串数据的RedisTemplate实现。它是RedisTemplate的一个子类,专门针对键和值都是字符串的场景进行了优化和简化。 -
特点
- 键和值都是字符串:
StringRedisTemplate默认将键(key)和值(value)都序列化为字符串。它使用StringRedisSerializer作为默认的序列化器。 - 简化配置:相比于通用的
RedisTemplate,StringRedisTemplate不需要手动配置序列化器,开箱即用。默认全部都为字符串序列化器- 当直接尝试使用
StringRedisTemplate将一个对象作为值存入 Redis 时,由于StringRedisTemplate期望的是字符串类型的值,而传入的是对象,会导致ClassCastException或SerializationException。
- 当直接尝试使用
- 适用于字符串操作:适合处理 Redis 中的字符串数据,比如简单的键值对、计数器等。
StringRedisTemplate虽然主要处理字符串类型的数据,但它能够进行递增操作,这是因为 Redis 本身支持对存储为字符串形式的数字进行原子性的递增和递减操作。- 要确保存储在 Redis 中的值是可以被解析为数字的字符串,否则会抛出异常。例如,如果键
"counter"存储的是"abc",执行递增操作时 Redis 会报错,因为"abc"无法被解析为数字。
- 键和值都是字符串:
-
初始化方式
-
// 通过 Spring Boot 自动配置 @Autowired private StringRedisTemplate stringRedisTemplate; // 手动创建 StringRedisTemplate template = new StringRedisTemplate(redisConnectionFactory);
-
-
主要操作方法
-
值操作 (ValueOperations)
-
// 设置值 stringRedisTemplate.opsForValue().set("key", "value"); // 获取值 String value = stringRedisTemplate.opsForValue().get("key"); // 设置带过期时间 stringRedisTemplate.opsForValue().set("key", "value", 10, TimeUnit.SECONDS); // 递增 Long newValue = stringRedisTemplate.opsForValue().increment("counter");
-
-
列表操作 (ListOperations)
-
// 左推 stringRedisTemplate.opsForList().leftPush("listKey", "value1"); // 右推 stringRedisTemplate.opsForList().rightPush("listKey", "value2"); // 获取范围 List<String> range = stringRedisTemplate.opsForList().range("listKey", 0, -1);
-
-
集合操作 (SetOperations)
-
// 添加元素 stringRedisTemplate.opsForSet().add("setKey", "value1", "value2"); // 获取所有成员 Set<String> members = stringRedisTemplate.opsForSet().members("setKey");
-
-
哈希操作 (HashOperations)
-
// 设置哈希字段 stringRedisTemplate.opsForHash().put("hashKey", "field", "value"); // 获取哈希字段 String hashValue = (String) stringRedisTemplate.opsForHash().get("hashKey", "field");
-
-
有序集合操作 (ZSetOperations)
-
// 添加元素 stringRedisTemplate.opsForZSet().add("zsetKey", "member", 10.0); // 获取范围 Set<String> range = stringRedisTemplate.opsForZSet().range("zsetKey", 0, -1);
-
-
-
事务支持
-
stringRedisTemplate.execute(new SessionCallback<List<Object>>() { @Override public List<Object> execute(RedisOperations operations) throws DataAccessException { operations.multi(); operations.opsForValue().set("key1", "value1"); operations.opsForValue().set("key2", "value2"); return operations.exec(); } });
-

浙公网安备 33010602011771号