分布式中间件:Redis 数据结构
引言
在当今的分布式系统开发中,中间件起着至关重要的作用。Redis 作为一款高性能的分布式内存数据库,凭借其丰富的数据结构和高效的读写性能,被广泛应用于缓存、消息队列、分布式锁等场景。本文将结合实际代码,详细介绍 Redis 中几种常见的数据结构在 Spring Boot 项目中的使用。
环境准备
我们的示例代码基于 Spring Boot 框架,使用了 Spring Data Redis
来操作 Redis 数据库。以下是关键的依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
同时,需要在 application.properties
或 application.yml
中配置 Redis 的连接信息。
代码示例
以下是一个完整的测试类,展示了如何使用 Redis 的不同数据结构:
package com.dm.redis;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import java.util.List;
import java.util.Set;
/**
* @Author 21326
* @Date 2025 2025/3/3 22:22
*/
@SpringBootTest
public class Test2 {
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private ObjectMapper objectMapper;
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Test
public void test1() {
// 字符串操作
System.out.println("字符串==》");
User user = new User("张三", 18, "男");
String userKey = "user";
System.out.println("user==》" + user.toString());
try {
String info = objectMapper.writeValueAsString(user);
System.out.println("info==》" + info);
redisTemplate.opsForValue().set(userKey, info);
System.out.println("redisTemplate==》" + redisTemplate.opsForValue().get(userKey));
User u = objectMapper.readValue(redisTemplate.opsForValue().get(userKey).toString(), User.class);
System.out.println("u==》" + u.toString());
} catch (Exception e) {
e.printStackTrace();
}
// 列表操作
System.out.println("列表==》");
List<User> list = List.of(new User("张三", 18, "男"),
new User("李四", 18, "男"),
new User("王五", 18, "男"));
String listKey = "list";
System.out.println("list==》" + list.toString());
list.forEach(item -> {
System.out.println("列表添加数据==》队尾添加");
redisTemplate.opsForList().leftPush(listKey, item.toString());
});
for (int i = 0; i < list.size(); i++) {
System.out.println("列表取出数据==》队首取出");
System.out.println(redisTemplate.opsForList().leftPop(listKey));
}
// 集合操作
System.out.println("集合==》");
Set<String> set = Set.of("张三", "李四", "王五");
System.out.println("set==》" + set.toString());
String setKey = "set";
set.forEach(item -> {
System.out.println("集合添加数据==》");
redisTemplate.opsForSet().add(setKey, item.toString());
});
for (int i = 0; i < set.size(); i++) {
System.out.println("集合取出数据==》");
System.out.println(redisTemplate.opsForSet().pop(setKey));
}
// 有序集合操作
System.out.println("有序集合==》");
Set<User> zSet = Set.of(new User("张三", 18, "男"),
new User("李四", 20, "男"),
new User("王五", 19, "男"));
System.out.println("zSet==》" + zSet.toString());
String zSetKey = "zSet";
zSet.forEach(item -> {
System.out.println("有序集合添加数据==》");
redisTemplate.opsForZSet().add(zSetKey, item.toString(), item.getAge());
});
Long size = redisTemplate.opsForZSet().size(zSetKey);
Set<User> zSetMinToMax = redisTemplate.opsForZSet().range(zSetKey, 0, size);
Set<User> zSetMaxToMin = redisTemplate.opsForZSet().reverseRange(zSetKey, 0, size);
System.out.println("zSetMinToMax==》" + zSetMinToMax.toString());
System.out.println("zSetMaxToMin==》" + zSetMaxToMin.toString());
// 哈希操作
System.out.println("哈希==》");
String hashKey = "hash";
for (User item : zSet) {
System.out.println("哈希添加数据==》");
redisTemplate.opsForHash().put(hashKey, item.getName(), item.toString());
}
for (User item : zSet) {
System.out.println("哈希取出数据==》");
System.out.println(redisTemplate.opsForHash().get(hashKey, item.getName()));
}
System.out.println("哈希查找单个数据");
System.out.println(redisTemplate.opsForHash().get(hashKey, "张三"));
}
}
详细解释
1. 字符串(String)
字符串是 Redis 中最基本的数据结构。在示例中,我们将一个 User
对象转换为 JSON 字符串后存储到 Redis 中,然后再从 Redis 中读取并反序列化为 User
对象。
User user = new User("张三", 18, "男");
String userKey = "user";
String info = objectMapper.writeValueAsString(user);
redisTemplate.opsForValue().set(userKey, info);
User u = objectMapper.readValue(redisTemplate.opsForValue().get(userKey).toString(), User.class);
2. 列表(List)
列表是一个有序的字符串列表。我们可以使用 leftPush
方法从列表的左侧插入元素,使用 leftPop
方法从列表的左侧弹出元素,实现队列的功能。
List<User> list = List.of(new User("张三", 18, "男"), new User("李四", 18, "男"), new User("王五", 18, "男"));
String listKey = "list";
list.forEach(item -> redisTemplate.opsForList().leftPush(listKey, item.toString()));
for (int i = 0; i < list.size(); i++) {
System.out.println(redisTemplate.opsForList().leftPop(listKey));
}
3. 集合(Set)
集合是一个无序且唯一的字符串集合。我们可以使用 add
方法向集合中添加元素,使用 pop
方法随机弹出一个元素。
Set<String> set = Set.of("张三", "李四", "王五");
String setKey = "set";
set.forEach(item -> redisTemplate.opsForSet().add(setKey, item.toString()));
for (int i = 0; i < set.size(); i++) {
System.out.println(redisTemplate.opsForSet().pop(setKey));
}
4. 有序集合(Sorted Set)
有序集合是一个有序的字符串集合,每个元素都有一个分数(score),用于排序。我们可以使用 add
方法向有序集合中添加元素,使用 range
和 reverseRange
方法按分数从小到大和从大到小的顺序获取元素。
Set<User> zSet = Set.of(new User("张三", 18, "男"), new User("李四", 20, "男"), new User("王五", 19, "男"));
String zSetKey = "zSet";
zSet.forEach(item -> redisTemplate.opsForZSet().add(zSetKey, item.toString(), item.getAge()));
Long size = redisTemplate.opsForZSet().size(zSetKey);
Set<User> zSetMinToMax = redisTemplate.opsForZSet().range(zSetKey, 0, size);
Set<User> zSetMaxToMin = redisTemplate.opsForZSet().reverseRange(zSetKey, 0, size);
5. 哈希(Hash)
哈希是一个键值对的集合。我们可以使用 put
方法向哈希中添加键值对,使用 get
方法根据键获取值。
String hashKey = "hash";
for (User item : zSet) {
redisTemplate.opsForHash().put(hashKey, item.getName(), item.toString());
}
for (User item : zSet) {
System.out.println(redisTemplate.opsForHash().get(hashKey, item.getName()));
}
System.out.println(redisTemplate.opsForHash().get(hashKey, "张三"));
结果如下:
字符串==》
user==》User(name=张三, age=18, sex=男)
info==》{"name":"张三","age":18,"sex":"男"}
redisTemplate==》{"name":"张三","age":18,"sex":"男"}
u==》User(name=张三, age=18, sex=男)
列表==》
list==》[User(name=张三, age=18, sex=男), User(name=李四, age=18, sex=男), User(name=王五, age=18, sex=男)]
列表添加数据==》队尾添加
列表添加数据==》队尾添加
列表添加数据==》队尾添加
列表取出数据==》队首取出
User(name=王五, age=18, sex=男)
列表取出数据==》队首取出
User(name=李四, age=18, sex=男)
列表取出数据==》队首取出
User(name=张三, age=18, sex=男)
集合==》
set==》[张三, 李四, 王五]
集合添加数据==》
集合添加数据==》
集合添加数据==》
集合取出数据==》
李四
集合取出数据==》
张三
集合取出数据==》
王五
有序集合==》
zSet==》[User(name=王五, age=19, sex=男), User(name=张三, age=18, sex=男), User(name=李四, age=20, sex=男)]
有序集合添加数据==》
有序集合添加数据==》
有序集合添加数据==》
zSetMinToMax==》[User(name=张三, age=18, sex=男), User(name=王五, age=19, sex=男), User(name=李四, age=20, sex=男)]
zSetMaxToMin==》[User(name=李四, age=20, sex=男), User(name=王五, age=19, sex=男), User(name=张三, age=18, sex=男)]
哈希==》
哈希添加数据==》
哈希添加数据==》
哈希添加数据==》
哈希取出数据==》
User(name=王五, age=19, sex=男)
哈希取出数据==》
User(name=张三, age=18, sex=男)
哈希取出数据==》
User(name=李四, age=20, sex=男)
哈希查找单个数据
User(name=张三, age=18, sex=男)
总结
通过以上示例,我们可以看到 Redis 的不同数据结构在实际应用中的使用方法。每种数据结构都有其独特的特点和适用场景,合理选择数据结构可以提高系统的性能和效率。在分布式系统开发中,Redis 作为一款强大的分布式中间件,能够帮助我们解决很多复杂的问题。
希望本文对你理解 Redis 的数据结构和在 Spring Boot 项目中的使用有所帮助。如果你有任何问题或建议,欢迎留言讨论。