Redis项目中应用

1. Redis简介

Redis是一个基于内存的key-value结构数据库。Redis 是互联网技术领域使用最为广泛的存储中间件

官网:https://redis.io

中文网:Redis中文网

2. Redis下载与安装

2.1 Redis下载

Redis安装包分为windows版和Linux版:

  • Windows版下载地址:https://github.com/microsoftarchive/redis/releases

  • Linux版下载地址: https://download.redis.io/releases/

2.2 Redis安装

2.2.1 Windows中

Redis的Windows版属于绿色软件,直接解压即可使用,解压后目录结构如下:

2.2.2 Linux中

  1. 将Redis安装包上传到Linux

  2. 解压安装包,命令:tar -zxvf redis-4.0.0.tar.gz -C /usr/local

  3. 安装Redis的依赖环境gcc,命令:yum install gcc-c++

  4. 进入/usr/local/redis-4.0.0,进行编译,命令:make

  5. 进入redis的src目录进行安装,命令:make install

安装后重点文件说明:

  • /usr/local/redis-4.0.0/src/redis-server:Redis服务启动脚本

  • /usr/local/redis-4.0.0/src/redis-cli:Redis客户端脚本

  • /usr/local/redis-4.0.0/redis.conf:Redis配置文件

3. Spring Data Redis使用

3.1 介绍

在java程序中应该如何操作Redis呢?这就需要使用Redis的Java客户端,就如同我们使用JDBC操作MySQL数据库一样。

Spring 对 Redis 客户端进行了整合,提供了 Spring Data Redis,在Spring Boot项目中还提供了对应的Starter,即 spring-boot-starter-data-redis。

Spring Data Redis 是 Spring 的一部分,提供了在 Spring 应用中通过简单的配置就可以访问 Redis 服务,对 Redis 底层开发包进行了高度封装。在 Spring 项目中,可以使用Spring Data Redis来简化 Redis 操作。

网址:https://spring.io/projects/spring-data-redis

Spring Data Redis中提供了一个高度封装的类:RedisTemplate,对相关api进行了归类封装,将同一类型操作封装为operation接口,具体分类如下:

  • ValueOperations:string数据操作

  • SetOperations:set类型数据操作

  • ZSetOperations:zset类型数据操作

  • HashOperations:hash类型的数据操作

  • ListOperations:list类型的数据操作

3.2 环境搭建

3.2.1 导入maven坐标

<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

3.2.2 配置Redis数据源

在application.yml中添加:

spring:
  redis:
    host: 地址
    port: 6379
    password: 123456
    database: 8

解释说明:

database:指定使用Redis的哪个数据库,Redis服务启动后默认有16个数据库,编号分别是从0到15。可以通过修改Redis配置文件来指定数据库的数量。

3.2.3 编写配置类,创建RedisTemplate对象

@Configuration
@Slf4j
public class RedisConfiguration {

    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory){
        log.info("开始创建redis模板对象...");
        RedisTemplate redisTemplate = new RedisTemplate();
        //设置redis的连接工厂对象
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        //设置redis key的序列化器
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        return redisTemplate;
    }
}

解释说明:

当前配置类不是必须的,因为 Spring Boot 框架会自动装配 RedisTemplate 对象,但是默认的key序列化器为JdkSerializationRedisSerializer,导致我们存到Redis中后的数据和原始数据有差别,故设置为StringRedisSerializer序列化器。

3.2.4 通过RedisTemplate对象操作Redis

下面测试类中进行了简单的测试:

@SpringBootTest
public class SpringDataRedisTest {
    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    public void testRedisTemplate(){
        System.out.println(redisTemplate);
        //string数据操作
        ValueOperations valueOperations = redisTemplate.opsForValue();
        //hash类型的数据操作
        HashOperations hashOperations = redisTemplate.opsForHash();
        //list类型的数据操作
        ListOperations listOperations = redisTemplate.opsForList();
        //set类型数据操作
        SetOperations setOperations = redisTemplate.opsForSet();
        //zset类型数据操作
        ZSetOperations zSetOperations = redisTemplate.opsForZSet();
    }
}

测试通过,说明RedisTemplate对象注入成功,并且通过该RedisTemplate对象获取操作5种数据类型相关对象。

3.3 使用示例

3.3.1 操作字符串类型数据

/**
 * 操作字符串类型的数据
 */
@Test
public void testString(){
    // 使用 redisTemplate 的 opsForValue() 操作字符串类型的数据
    
    // 1. 使用 set() 方法设置键为 "name",值为 "小明"
    redisTemplate.opsForValue().set("name", "小明");
    
    // 2. 使用 get() 方法获取键为 "name" 的值,类型为 String
    // 由于 redisTemplate 返回的值是 Object 类型,因此这里需要强制转换为 String 类型
    String city = (String) redisTemplate.opsForValue().get("name");
    
    // 3. 输出获取到的值 "name" 对应的内容,即 "小明"
    System.out.println(city);

    // 4. 使用 set() 方法设置键为 "code",值为 "1234",并且设置该键 3 分钟后过期
    // 参数说明:
    // 第一个参数是键(key),这里为 "code"
    // 第二个参数是值(value),这里为 "1234"
    // 第三个参数是过期时间,这里为 3
    // 第四个参数是时间单位,这里为分钟(TimeUnit.MINUTES)
    redisTemplate.opsForValue().set("code", "1234", 3, TimeUnit.MINUTES);

    // 5. 使用 setIfAbsent() 方法尝试设置键为 "lock" 的值为 "1",如果键不存在则设置成功
    // setIfAbsent() 方法等同于 Redis 的 SETNX(Set if Not eXists)操作
    // 如果 "lock" 不存在,设置值为 "1" 并返回 true;如果 "lock" 已经存在,返回 false
    redisTemplate.opsForValue().setIfAbsent("lock", "1");

    // 6. 再次尝试使用 setIfAbsent() 设置键为 "lock" 的值为 "2",但因为上一步已经设置了 "lock" 键的值,所以这次不会成功
    // 由于 "lock" 键已经存在,setIfAbsent() 不会修改它的值,返回 false
    redisTemplate.opsForValue().setIfAbsent("lock", "2");
}

3.3.2 操作哈希类型数据

/**
 * 操作哈希类型的数据
 */
@Test
public void testHash(){
    // 使用 redisTemplate 的 opsForHash() 来操作哈希类型数据
    HashOperations hashOperations = redisTemplate.opsForHash();

    // 1. 使用 put() 方法向哈希表 "100" 中添加键值对 "name"-"tom"
    // 这里 "100" 是哈希表的 key,"name" 是哈希表中字段的 key,"tom" 是对应的 value
    hashOperations.put("100", "name", "tom");

    // 2. 使用 put() 方法向哈希表 "100" 中添加键值对 "age"-"20"
    // "100" 是哈希表的 key,"age" 是字段的 key,"20" 是字段的值
    hashOperations.put("100", "age", "20");

    // 3. 使用 get() 方法从哈希表 "100" 中获取字段 "name" 对应的值
    // 这里获取的是哈希表 "100" 中字段 "name" 的值,返回的是 Object 类型
    String name = (String) hashOperations.get("100", "name");

    // 4. 输出获取到的字段 "name" 的值,即 "tom"
    System.out.println(name);

    // 5. 使用 keys() 方法获取哈希表 "100" 中的所有字段名称
    // 该方法返回哈希表中所有字段的 key 值,类型为 Set
    Set keys = hashOperations.keys("100");

    // 6. 输出哈希表 "100" 中的所有字段名称
    System.out.println(keys);

    // 7. 使用 values() 方法获取哈希表 "100" 中所有字段的值
    // 该方法返回哈希表中所有字段的值,类型为 List
    List values = hashOperations.values("100");

    // 8. 输出哈希表 "100" 中的所有字段值
    System.out.println(values);

    // 9. 使用 delete() 方法删除哈希表 "100" 中的字段 "age"
    // 这里 "100" 是哈希表的 key,"age" 是要删除的字段的 key
    hashOperations.delete("100", "age");
}

3.3.3 操作列表类型数据

/**
 * 操作列表类型的数据
 */
@Test
public void testList(){
    // 使用 redisTemplate 的 opsForList() 方法获取操作列表类型数据的工具
    ListOperations listOperations = redisTemplate.opsForList();

    // 1. 使用 leftPushAll() 方法,将多个元素 "a", "b", "c" 依次从左边推入列表 "mylist"
    // "mylist" 是 Redis 中的 key,元素 "a", "b", "c" 将按顺序推入列表左端
    listOperations.leftPushAll("mylist", "a", "b", "c");

    // 2. 使用 leftPush() 方法,将元素 "d" 从左边推入列表 "mylist"
    // 这个操作会使得 "d" 位于列表最左端,顺序为 ["d", "a", "b", "c"]
    listOperations.leftPush("mylist", "d");

    // 3. 使用 range() 方法获取列表 "mylist" 中指定范围的元素
    // 参数 0 表示起始索引,-1 表示结束索引(-1 代表列表的最后一个元素)
    // 该操作会返回整个列表中的所有元素
    List mylist = listOperations.range("mylist", 0, -1);

    // 4. 输出列表 "mylist" 的所有元素
    System.out.println(mylist); // 输出结果为 ["d", "a", "b", "c"]

    // 5. 使用 rightPop() 方法从右边移除列表 "mylist" 的最后一个元素
    // 此操作会移除元素 "c",使得列表变为 ["d", "a", "b"]
    listOperations.rightPop("mylist");

    // 6. 使用 size() 方法获取列表 "mylist" 的长度(元素个数)
    // 此时列表的长度应为 3,因为移除了一个元素
    Long size = listOperations.size("mylist");

    // 7. 输出列表 "mylist" 的长度
    System.out.println(size); // 输出结果为 3
}

3.3.4 操作集合类型数据

/**
 * 操作集合(Set)类型的数据
 */
@Test
public void testSet(){
    // 使用 redisTemplate 的 opsForSet() 方法获取操作集合类型数据的工具
    SetOperations setOperations = redisTemplate.opsForSet();

    // 1. 使用 add() 方法向集合 "set1" 中添加元素 "a", "b", "c", "d"
    // Redis 中的集合类型不允许重复元素,这里 "set1" 是 Redis 中的一个集合 key
    setOperations.add("set1", "a", "b", "c", "d");

    // 2. 向另一个集合 "set2" 中添加元素 "a", "b", "x", "y"
    // "set2" 是 Redis 中的另一个集合 key,元素 "a" 和 "b" 在两个集合中都有,形成交集
    setOperations.add("set2", "a", "b", "x", "y");

    // 3. 使用 members() 方法获取集合 "set1" 中的所有元素
    // 此操作返回集合中的所有成员,集合的顺序是无序的
    Set members = setOperations.members("set1");

    // 4. 输出集合 "set1" 中的所有元素
    System.out.println(members); // 可能输出为 [a, b, c, d]

    // 5. 使用 size() 方法获取集合 "set1" 的元素个数
    Long size = setOperations.size("set1");

    // 6. 输出集合 "set1" 的大小
    System.out.println(size); // 输出结果应为 4

    // 7. 使用 intersect() 方法获取集合 "set1" 和集合 "set2" 的交集
    // 交集是两个集合中共同存在的元素,此操作返回交集中的元素
    Set intersect = setOperations.intersect("set1", "set2");

    // 8. 输出两个集合的交集
    System.out.println(intersect); // 可能输出为 [a, b]

    // 9. 使用 union() 方法获取集合 "set1" 和集合 "set2" 的并集
    // 并集是两个集合中的所有元素,此操作返回并集中所有不重复的元素
    Set union = setOperations.union("set1", "set2");

    // 10. 输出两个集合的并集
    System.out.println(union); // 可能输出为 [a, b, c, d, x, y]

    // 11. 使用 remove() 方法从集合 "set1" 中移除指定的元素 "a" 和 "b"
    // 此操作会将 "a" 和 "b" 从 "set1" 中删除
    setOperations.remove("set1", "a", "b");
}

3.3.5 操作有序集合类型数据

/**
 * 操作有序集合(ZSet)类型的数据
 */
@Test
public void testZset(){
    // 使用 redisTemplate 的 opsForZSet() 方法获取操作有序集合类型数据的工具
    ZSetOperations zSetOperations = redisTemplate.opsForZSet();

    // 1. 使用 add() 方法向有序集合 "zset1" 中添加元素 "a" 并设置其分数为 10
    // Redis 中的 ZSet 是有序集合,它的每个元素都有一个分数,元素按分数从小到大排序
    zSetOperations.add("zset1", "a", 10);

    // 2. 向有序集合 "zset1" 中添加元素 "b",分数为 12
    zSetOperations.add("zset1", "b", 12);

    // 3. 向有序集合 "zset1" 中添加元素 "c",分数为 9
    zSetOperations.add("zset1", "c", 9);

    // 4. 使用 range() 方法获取有序集合 "zset1" 中所有元素
    // 参数 (0, -1) 表示获取从第 0 位到最后一位的所有元素,集合按分数从小到大排序
    Set zset1 = zSetOperations.range("zset1", 0, -1);

    // 5. 输出集合 "zset1" 中的所有元素,按分数升序排列
    System.out.println(zset1); // 可能输出为 [c, a, b],根据分数排序

    // 6. 使用 incrementScore() 方法为有序集合 "zset1" 中的元素 "c" 的分数增加 10
    // 元素 "c" 的原分数为 9,增加后变为 19
    zSetOperations.incrementScore("zset1", "c", 10);

    // 7. 使用 remove() 方法从有序集合 "zset1" 中删除指定的元素 "a" 和 "b"
    // 此操作会将元素 "a" 和 "b" 从集合中移除
    zSetOperations.remove("zset1", "a", "b");
}

3.3.6 通用命令操作

/**
 * 通用命令操作
 */
@Test
public void testCommon(){
    // 使用 redisTemplate 的 keys() 方法获取所有键(key),支持通配符 "*"
    // 例如, "*" 获取所有键,"user*" 可以获取所有以 "user" 开头的键
    Set keys = redisTemplate.keys("*");
    
    // 输出当前 Redis 数据库中所有的键
    System.out.println(keys);

    // 使用 hasKey() 方法检查 Redis 中是否存在键 "name"
    Boolean name = redisTemplate.hasKey("name");

    // 检查键 "set1" 是否存在
    Boolean set1 = redisTemplate.hasKey("set1");

    // 遍历所有获取到的键
    for (Object key : keys) {
        // 使用 type() 方法获取每个键对应的值类型,如 String、Hash、List、Set、ZSet 等
        DataType type = redisTemplate.type(key);
        
        // 输出键的类型名称
        System.out.println(type.name());
    }

    // 使用 delete() 方法删除键 "mylist" 及其对应的值
    redisTemplate.delete("mylist");
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/904399.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

cursor连接远程jupyter

cursor的步骤跟vscode应该是基本一样的&#xff0c;主要需要两个插件&#xff0c;一个是remote-ssh&#xff0c;另一个是jupyter 第一步 首先连接远程的ssh&#xff0c;因为我已经新建好了&#xff0c;所以直接选207&#xff0c;没有连接过的就选Add New SSH Host&#xff…

9款热门CRM客户关系管理系统大盘点

在当今竞争激烈的商业环境中&#xff0c;客户关系管理&#xff08;CRM&#xff09;系统已成为企业不可或缺的工具。CRM系统不仅帮助企业管理客户信息&#xff0c;还能提高销售效率、改善客户服务、增强客户满意度。本文将为您盘点9款热门的CRM客户关系管理系统&#xff0c;并重…

IMX6ULL裸机-汇编_反汇编_机器码

程序处理的4个步骤 我们编写的C程序是不能直接在ARM等平台上运行的&#xff0c;必须经过一系列的程序处理才可以&#xff0c;我们的第一个LED程序涉及两个文件&#xff1a;start.S、main.c&#xff0c;它们的处理过程如下&#xff1a; 对于汇编程序&#xff0c;经过汇编之后&a…

【Unity】游戏UI中添加粒子特效导致穿层问题的解决

这里介绍一下简易的ui系统中&#xff0c;添加粒子特效导致的穿层问题 首先是在ui界面中添加粒子特效预制体&#xff0c;这个时候&#xff0c;控制这个粒子显示层级的有两个方面 上图中&#xff0c;如果你的Sorting Layer ID的值&#xff08;Layer排序&#xff09;是大于当前C…

SAP 根据不同生产版本创建销售预测简介

SAP 根据不同生产版本创建销售预测简介 业务场景前台操作1、创建BOM2、创建工艺路线3、创建生产版本4、创建销售预测5、调整销售预测6、查看物料需求业务场景 很多工厂一个物料可能会存在多个BOM,当有多个BOM存在的情况下就会存在多个生产版本,当创建计划独立需求的时候,系…

STM32 RTC 驱动代码(解决了使用HAL库函数导致的复位或者掉电后导致RTC年月日日期清零的问题)

问题背景&#xff1a;在RTC中断里面使用HAL库HAL_RTC_GetDate()和HAL_RTC_GetTime()来获取RTC时间日期。 源码如下图&#xff1a; 问题描述&#xff1a;单片机断电或者复位后的时分秒的时间可以接上&#xff0c;但年月日的日期就会被清零。如图&#xff1a; 导致问题的根本原因…

SpringBoot3+SpringSecurity6基于若依系统整合自定义登录流程

SpringBoot3SpringSecurity6基于若依系统整合自定义登录流程 问题背景 在做项目时遇到了要对接统一认证的需求&#xff0c;但是由于框架的不兼容性&#xff08;我们项目是springboot3&#xff0c;jdk17&#xff0c;springsecurity6.1.5&#xff09;等因素&#xff0c;不得不使…

Mount Image Pro,在取证安全的环境中挂载和访问镜像文件内容

天津鸿萌科贸发展有限公司从事数据安全服务二十余年&#xff0c;致力于为各领域客户提供专业的数据恢复、数据备份解决方案与服务&#xff0c;并针对企业面临的数据安全风险&#xff0c;提供专业的相关数据安全培训。 天津鸿萌科贸发展有限公司是 GetData 公司数据恢复与取证工…

PHP合成图片,生成海报图,poster-editor使用说明

之前写过一篇使用Grafika插件生成海报图的文章&#xff0c;但是当我再次使用时&#xff0c;却发生了错误&#xff0c;回看Grafika文档&#xff0c;发现很久没更新了&#xff0c;不兼容新版的GD&#xff0c;所以改用了intervention/image插件来生成海报图。 但是后来需要对海报…

React 前端框架全面教程:从入门到进阶

React 前端框架全面教程&#xff1a;从入门到进阶 引言 在现代前端开发中&#xff0c;React 作为一款流行的 JavaScript 库&#xff0c;以其组件化、声明式的特性和强大的生态系统&#xff0c;成为了开发者的首选。无论是构建单页应用&#xff08;SPA&#xff09;还是复杂的用…

基于Python的自然语言处理系列(42):Token Classification(标注分类)

在本篇文章中&#xff0c;我们将探讨如何进行 Token Classification&#xff08;标注分类&#xff09;&#xff0c;这是一类为句子中的每个 token&#xff08;词或子词&#xff09;分配标签的任务。该任务可以解决很多问题&#xff0c;例如命名实体识别&#xff08;NER&#xf…

用Pyhon写一款简单的益智类小游戏——2048

文字版——代码及讲解 代码—— import random# 初始化游戏棋盘 def init_board():return [[0] * 4 for _ in range(4)]# 在棋盘上随机生成一个2或4 def add_new_tile(board):empty_cells [(i, j) for i in range(4) for j in range(4) if board[i][j] 0]if empty_cells:i,…

『Linux学习笔记』如何在 Ubuntu 22.04 上安装和配置 VNC

『Linux学习笔记』如何在 Ubuntu 22.04 上安装和配置 VNC 文章目录 一. 『Linux学习笔记』如何在 Ubuntu 22.04 上安装和配置 VNC1. 介绍 二. 参考文献 一. 『Linux学习笔记』如何在 Ubuntu 22.04 上安装和配置 VNC 如何在 Ubuntu 22.04 上安装和配置 VNC 1. 介绍 虚拟网络计算…

【Java】方法的使用 —— 语法要求、方法的重载和签名、方法递归

目录 1. 方法基础知识 1.1 方法的概念 1.2 语法格式 * 注意事项【与C不同】 1.3 return —— 返回值的严格检查【比C语言严格】 2. 形参与实参的关系 3. 方法重载 3.1 什么是方法重载&#xff1f;为什么要方法重载&#xff1f; 3.2 方法重载的规则 4. 方法签名 5. 递…

HT7178 带输出关断的20V,14A全集成同步升压转换器

1、特点 输入电压范围VpIN:2.7V-20V 输出电压范围VouT:4.5V-20V 可编程峰值电流:14A 高转换效率: 95%(VPIN7.2V, VoUT 16V, IouT3A) 94%(VPIN12V,VoUT18V,IoUT4A) 90%(VPIN3.3, VoUT-9V,IOUT3A) 轻载条件下两种调制方式:脉频调制(PFM)和 强制脉宽调试(PWM) 集成输出关断的栅极…

【史上最全SD教程】Stable Diffusion系统教学!Ai绘画零基础入门到精通商业实战 人工智能绘图画图商业变现

一、为什么要学Stable Diffusion&#xff0c;它究竟有多强大&#xff1f; 1.Stable Diffusion能干嘛 Stable Diffusion&#xff08;SD&#xff09;作为一种先进的AI图像生成技术&#xff0c;其功能和应用场景非常广泛。以下是SD的一些主要功能和应用领域&#xff1a; \1. 图…

《链表篇》---两数相加(中等)

题目传送门 方法一&#xff1a;迭代 文字描述看代母注释 class Solution {public ListNode addTwoNumbers(ListNode l1, ListNode l2) {//定义头结点和当前节点ListNode head null,cur null;//carry记录进位情况。int carry 0; while(l1 ! null || l2 ! null){//判断节点是…

QT找不到ffmpeg链接库解决方法

error: undefined reference to avformat_network_init() 一个神奇的报错&#xff0c;查了很久&#xff0c;检查步骤&#xff1a; 1、检查了 pro工程文件 2、链接库的真实性和正确性 在main.cpp中调用没有报错&#xff0c;在其它cpp文件中调用就报错。 破案了&#xff0c;…

详细了解C++11(1)

大家好呀&#xff0c;我是残念&#xff0c;希望在你看完之后&#xff0c;能对你有所帮助&#xff0c;有什么不足请指正&#xff01;共同学习交流哦 本文由&#xff1a;残念ing原创CSDN首发&#xff0c;如需要转载请通知 个人主页&#xff1a;残念ing-CSDN博客&#xff0c;欢迎各…

04.DDD与CQRS

学习视频来源&#xff1a;DDD独家秘籍视频合集 https://space.bilibili.com/24690212/channel/collectiondetail?sid1940048&ctype0 文章目录 定义职责分离DDD与CQRS的关系领域模型和查询模型特点命令场景的领域模型查询场景的查询模型 架构方案领域事件方案1&#xff1a…