【Spring Boot】操作Redis数据结构

2023-09-18 16:08:32

在这里插入图片描述

🌿欢迎来到@衍生星球的CSDN博文🌿
🍁本文主要学习【Spring Boot】操作Redis数据结构 🍁
🌱我是衍生星球,一个从事集成开发的打工人🌱
⭐️喜欢的朋友可以关注一下🫰🫰🫰,下次更新不迷路⭐️
💠作为一名热衷于分享知识的程序员,我乐于在CSDN上与广大开发者交流学习。
💠我希望通过每一次学习,让更多读者了解我,也希望能结识更多志同道合的朋友。
💠在今后的日子里,我将继续努力,不断提升自己的专业技能,创造更多价值。

在这里插入图片描述

学习目标:

  • 如何使用Redis的5个常用数据结构
  • 学习使用Redis的基础

1.String

String(字符串)是常用的数据格式,一般在缓存数据时基本是使用String格式来进行存储的。

    @Test
    public void testString() {
        ValueOperations<Serializable,Object> operations =redisTemplate.opsForValue();
        // 调用set()方法创建缓存
        operations.set("string","you");
        //获取缓存数据
        String value=(String) operations.get("string");
        System.out.println("string value :"+value);
    }

在这里插入图片描述

通过上面的示例可以看到,我们调用了set()和get()方法来创建与获取缓存数据,使用起来特别简单方便。

Redis除了提供set()、get()方法之外,还提供了decr()和incr()方法。当String类型的值为整数时,Redis可以把它当作整数一样执行自增(incr)和自减(decr)操作。由于Redis所有的操作都是原子性的,因此不必担心在多客户端连接时可能出现的事务处理问题。具体示例代码如下:

    @Test
    public void testStringIncr() {
        // 设置当前在线用户数
        redisTemplate.opsForValue().set("user:online", "100");
        //当前在线用户数+1
        redisTemplate.opsForValue().increment("user:online");
        // 获取缓存数据
        Integer value = (Integer) redisTemplate.opsForValue().get("user:online");
        System.out.println("string value :" + value);
    }

通过上面的示例可以看到,RedisTemplate提供了increment()和decrement()方法实现String数据类型的自增(incr)、自减(decr)操作。

2.Hash

我们使用缓存时基本都是使用String进行存储的,但是有些场景String类型存储可能不太适用。因为Redis每存储一个key都会占用一个内存空间,key太多会消耗不必要的内存,也不方便数据的管理,因此合理地使用Hash(哈希)可以减少key的数量,也能节省内存。

Hash是一个String类型的field和value的映射表。如果key不存在,就会创建新的哈希表并进行HSET操作;如果字段(field)已经存在于哈希表中,则旧值将被覆盖。Hash适用于存储对象。

    @Test
    public void testHash() {
        HashOperations<String, Object, Object> hash = redisTemplate.opsForHash();
        //调用put()方法创建Hash数据缓存
        hash.put("hash","test","hello");
        hash.put("hash","test","spring");
        hash.put("hash","test","boot");
        //获取Hash数据
        String value=(String)hash.get("hash","you");
        System.out.println("hash value :"+value);
    }

在这里插入图片描述

通过上面的示例可以看到,使用Hash存储数据时需要传入3个参数:第一个参数为key,第二个参数为字段(field),第三个参数为要存储的值(value)。

Hash删除时特别方便,比如将同类的数据聚集在一个Hash中,删除key就可以实现全部删除,清理数据比较方便。除此之外,另一种是删除Hash中的部分key。

//删除Hash 中的部分key
redisTemplate.opsForHash().delete("hash","test");

如上面的示例所示,如果需要删除Hash集合中的某个数据,传入对应的key和field参数即可。

3.List

List(列表)的应用场景非常广泛,是Redis重要的数据结构之一。使用List可以轻松地实现数据队列,List典型的应用场景就是消息队列,通过List的Push操作将消息数据存储到List中,然后在“消费”线程中再用POP操作将消息取出并进行相应的处理。

List的实现为一个双向链表,可以按照插入顺序排序。另外,也可以把一个元素到添加列链表的头部(左边)或者链表的尾部(右边),操作起来更加方便。

    @Test
    public void testList() {
        ListOperations<String, String > list = redisTemplate.opsForList();
        // 把数据插入到List的左边
        list.leftPush("list", "hello");
        list.leftPush("list", "spring");
        list.leftPush("list", "boot");
        // 从左边取出List中的数据
        String value = (String)list.leftPop("list");
        System.out.println("list value :" + value.toString());
    }

在这里插入图片描述

上面的例子表示把值从左侧插入(leftPush)一个key为“list”的队列中,然后从该队列的最左侧取出(leftPop)一个数据。

List还有很多其他API操作函数,比如从右侧插入(rightPush)队列,从右侧读取(rightPop)数据,或者调用range()方法读取队列的一部分。接着上面的例子,我们调用range()方法进行读取。

    @Test
    public void testListRange() {
        ListOperations<String, String> list = redisTemplate.opsForList();
        // 从List的左边插入数据
        list.leftPush("list", "ysxq");
        list.leftPush("list", "spring");
        list.leftPush("list", "boot");
        // 调用range()方法获取部分List
        List<String> values = list.range("list", 0, 2);
        for (String v : values) {
            System.out.println("list range :" + v);
        }
    }

在这里插入图片描述

Range()方法包含3个参数:第一个参数是key,第二个参数是读取的起始位置,第三个参数是读取的结束位置。输入不同的参数就可以从队列中读取对应的数据。

4.Set

Set(集合)是String类型的无序集合。集合成员是唯一的,所以集合中不能出现重复的数据。Set的功能与List类似,不同之处在于Set可以自动去除重复的数据。因此,当我们需要存储一个列表数据又不希望其中出现重复的数据时,Set类型就是一个很好的选择。示例代码如下:

    @Test
    public void testSet() {
        String key = "set";
        SetOperations<String, String> set = redisTemplate.opsForSet();
        // 在Set 中插入数据
        set.add(key, "hello");
        set.add(key, "spring");
        set.add(key, "boot");
        set.add(key, "hello");
        // 调用members()方法判断某个数据
        Set<String> values = set.members(key);
        for (String v : values) {
            System.out.println("set value :" + v);
        }
    }

在这里插入图片描述

通过上面的例子可以发现,Set提供了members()方法获取集合中全部的数据。而且,当存入两个相同的数据“hello”时,全部读取Set时只剩下一个数据,说明Set对队列进行了自动去重操作。

Set还为集合提供了求交集、并集、差集等操作函数,使用起来非常方便,适用于各种业务需求。示例代码如下:

    @Test
    public void testSetUnion() {
        SetOperations<String,String> set = redisTemplate.opsForSet();
        //在seta 中插入数据
        set.add("set:a","spring");
        set.add("set:a","ysxq");
        set.add("set:a", "test");
        //在setb 中插入数据
        set.add("set:b","spring");
        set.add("set:b","ysxq");
        set.add("set:b","test");
        // 返回多个集合的并集
        redisTemplate.opsForSet().union("set:a","set:b");
        // 返回多个集合的交集
        redisTemplate.opsForSet().intersect("set:a","set:b");
        //返回集合key1中存在但是key2中不存在的数据集合,即差集
        redisTemplate.opsForSet().difference("set:a","set:b");
    }

5.ZSet

ZSet的使用场景与Set类似,区别在于Set是无序的,而ZSet可以通过一个优先级(Score)参数来为成员排序。示例代码如下:

    @Test
    public void testZset() {
        String key = "zset";
        redisTemplate.delete(key);
        ZSetOperations<String, String> zset = redisTemplate.opsForZSet();
        zset.add(key, "hello", 1);
        zset.add(key, "ysxq", 6);
        zset.add(key, "boot", 4);
        zset.add(key, "spring", 3);
        // 调用range()方法获取数据
        Set<String> zsets = zset.range(key, 0, 3);
        for (String v : zsets) {
            System.out.println("zset value :" + v);
        }
    }

在这里插入图片描述

通过上面的例子可以发现,保存ZSet类型的缓存时会传入key、value、Score三个参数,然后通过range获取数据。

ZSet还可以根据Score的值对集合进行排序。我们可以利用这个特性来实现具有权重的队列,比如普通消息的Score为1,重要消息的Score为2,然后消费线程可以选择按Score的倒序来获取相关数据。

    @Test
    public void testZset1() {
        String key = "zset";
        redisTemplate.delete(key);
        ZSetOperations<String, String> zset = redisTemplate.opsForZSet();
        zset.add(key, "it", 1);
        zset.add(key, "you", 6);
        zset.add(key, "know", 4);
        zset.add(key, "neo", 3);
        // 调用range()方法获取数据并排序
        Set<String> zsetB = zset.rangeByScore(key, 0, 3);
        for (String v : zsetB) {
            System.out.println("zsetB value :" + v);
        }
    }

在这里插入图片描述

通过上面的示例可以发现,插入ZSet的数据会自动根据Score进行排序,还可以调用rangeByScore()方法获取Score范围内排序后的数据。根据这个特性可以实现优先队列的功能。

更多推荐

力扣669 补9.16

最近大三上四天有早八,真的是受不了了啊,欧嗨呦,早上困如狗,然后,下午困如狗,然后晚上困如狗,尤其我最近在晚上7点到10点这个时间段看力扣,看得我昏昏欲睡,不自觉就睡了1个小时,可能在犯困的时间段不适合做高难度的题目。还有英语也要抓紧搞,好久没搞英语了,力扣每天一题就搞得我没时间搞别的了,基本就是下午在看力扣,然后睡了

基于Spring Boot的房屋租赁系统

目录前言一、技术栈二、系统功能介绍租客功能模块的实现​编辑管理员功能模块的实现三、核心代码1、登录模块2、文件上传模块3、代码封装前言房屋是人类生活栖息的重要场所,随着城市中的流动人口的增多,人们对房屋租赁需求越来越高,为满足用户查询房屋、预约看房、房屋租赁的需求,特开发了本基于SpringBoot的房屋租赁系统。本文

Android Studio导入aosp源码

1、在Ubuntu系统下,进入源码根目录,运行如下命令:sourcebuild/envsetup.sh#初始化环境变量。lunchsdk_phone_x86_64makeidegen-j6#六核编译idegen模块忽略此命令:mmmdevelopment/tools/idegen/#此命令可以不执行(同makeideg

【leetcode】数组排序

【leetcode】数组排序task03主要了解了数组中常见的排序方法:1.常见数组排序方法冒泡排序(BubbleSort):冒泡排序是一种简单的排序算法,它多次遍历数组,比较相邻的元素并交换它们,直到整个数组按升序排列。时间复杂度为O(n^2)。选择排序(SelectionSort):选择排序是一种简单的排序算法,它

基于Spring Boot的网上购物商城系统

目录前言一、技术栈二、系统功能介绍用户功能模块的实现管理员功能模块的实现商家功能模块的实现三、核心代码1、登录模块2、文件上传模块3、代码封装前言本课题是根据用户的需要以及网络的优势建立的一个基于SpringBoot的网上购物商城系统,来满足用户网络购物的需求。本网上购物商城系统应用Java技术,MYSQL数据库存储数

汉威科技亮相上海传感器展并发表主题演讲,智能传感器大有可为

9月15日,第8届中国(上海)国际传感器技术与应用展览会圆满落幕,该展会吸引了逾400家传感领域国内外的企业、100余家专业传感应用单位、500余位传感大咖共同参与,展会观众达30000人。作为全球三大传感器展之一的盛会,该展会也被称为全球传感器行业发展的风向标,而智能化则成为本次传感器的主题。展会同期举办的第八届智能

C++---链表

1、链表1.1、链表的结构每个链表开头都有一个头指针Head尾节点的指针域为NULL,用于判断此列表是否结束如果一个链表开始就为NULL,那么该链表为空链表链表中的先后不代表在真实内存中的位置,只是单纯的逻辑上关系1.2、创建链表我们首先利用结构体创建一个Student的结构体//利用链表创建3个学生的信息,学生信息包

【unity小技巧】Unity 存储存档保存——PlayerPrefs、JsonUtility和MySQL数据库的使用

文章目录前言PlayerPrefs一、基本介绍二、Demo三、优缺点JsonUtility一、基本使用二、Demo三、优缺点Mysql(扩展)完结前言游戏存档不言而喻,是游戏设计中的重要元素,可以提高游戏的可玩性,为玩家提供更多的自由和控制权。看完这篇文章就可以构建属于自己的存储系统了。PlayerPrefs它是一个仅

【Spring】数据导出为Excel的接口报java.io.IOException: UT010029: Stream is closed错误

数据导出为Excel的接口报java.io.IOException:UT010029:Streamisclosed错误实习时导师让写一个平台信息导出为Excel的功能,写完之后发现文件正常导出,但控制台一直报Streamisclosed错误。在网上找了大半天,都说是使用OutputStream时关闭了流导致的,这也确实

使用git-repo管理多个git仓库

step1:下载repogit-repo下载可在服务器端通过以下任一方式下载。gitclonehttps://gerrit.googlesource.com/git-repo(谷歌官方源)gitclonehttps://mirrors.tuna.tsinghua.edu.cn/git/git-repo(国内清华源)gi

JS模块化

JS模块化什么是模块化?将一个复杂的程序依据一定的规则(规范)封装成几个块(文件),并进行组合在一起。块的内部数据/实现是私有的,只是向外部暴露一些接口(方法)与外部其它模板通信。把所有的js代码写在一起,功能点不明确,耦合度不够,很难维护。模块化的优点避免命名冲突,减少命名空间污染更好的分离,按需加载更高复用性高可维

热文推荐