分布式中间件:Redis 数据结构

分布式中间件: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.propertiesapplication.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 方法向有序集合中添加元素,使用 rangereverseRange 方法按分数从小到大和从大到小的顺序获取元素。

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 项目中的使用有所帮助。如果你有任何问题或建议,欢迎留言讨论。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

顾北辰20

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值