SpringBoot整合Redis

news2024/10/2 10:43:15

SpringBoot整合Redis

文章目录

    • SpringBoot整合Redis
      • 一 .简介
        • 1. redie是什么?
        • 2. redie的使用场景?
      • 二 . 使用
        • 1. 引入依赖
        • 2. 配置文件
        • 3. 启动redis
        • 4. 创建Redis工具类
        • 5. 创建测试类
        • 6. 查看效果


一 .简介

1. redie是什么?

Redis是现在最受欢迎的NoSQL数据库之一,Redis是一个使用ANSI C编写的开源、包含多种数据结构、支持网络、基于内存、可选持久性的键值对存储数据库。它具备如下的特点:

  • redis 是采用C语言编写的,好处就是底层代码执行效率高,依赖性低,没有太多运行时的依赖,而且系统的兼容性好,稳定性高。
  • redis是基于内存的数据里,可避免磁盘IO,因此也被称作缓存工具。
  • redis采用key-value的方式进行存储,也就是使用hash结构进行操作,数据的操作时间复杂度是O(1)
  • redis采用的是单进程单线程的模型,可以避免上下文切换和线程之间引起的资源竞争。而且Redis还采用了IO多路复用技术,这里的多路复用是指多个socket网络连接,复用是指一个线程中处理多个IO请求,这样可以减少网络IO的消耗,大幅度提升效率

2. redie的使用场景?

  1. 缓存:

毫无疑问这是Redis当今最为人熟知的使用场景。再提升服务器性能方面非常有效;
一些频繁被访问的数据,经常被访问的数据如果放在关系型数据库,每次查询的开销都会很大,而放在redis中, 因为redis是放在内存中的可以很高效的访问。

  1. 排行榜:

在使用传统的关系型数据库(mysql oracle 等)来做这个事儿,非常的麻烦,而利用Redis的SortSet(有序集合)数据结构能够简单的搞定;

  1. 计算器/限速器:

Redis中原子性的自增操作,我们可以统计类似用户点赞数、用户访问数等,这类操作如果用MySQL,频繁的读 写会带来相当大的压力;限速器比较典型的使用场景是限制某个用户访问某个API的频率,常用的有抢购时,防 止用户疯狂点击带来不必要的压力;

  1. 好友关系:

利用集合的一些命令,比如求交集、并集、差集等。可以方便搞定一些共同好友、共同爱好之类的功能。

  1. 简单消息队列:

除了Redis自身的发布/订阅模式,我们也可以利用List来实现一个队列机制,比如:到货通知、邮件发送之类的
需求,不需要高可靠,但是会带来非常大的DB压力,完全可以用List来完成异步解耦;

  1. Session共享

以PHP为例,默认Session是保存在服务器的文件中,如果是集群服务,同一个用户过来可能落在不同机器上,这就会导致用户频繁登陆,采用Redis保存Session后,无论用户落在那台机器上都能够获取到对应的Session信息。

  1. 分布式锁:

分布式场景下,无法使用单机环境下的锁来对多个节点上的进程进行同步。可以使用 Redis 自带的 SETNX 命令实现分布式锁,除此之外,还可以使用官方提供的 RedLock 分布式锁实现。

二 . 使用

虽然redis的功能很多,但大多数下情况下我们只使用它来做缓存。

1. 引入依赖

        <!--redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <version>2.2.1.RELEASE</version>
        </dependency>

2. 配置文件

这里只进行了基础配置,更详细的配置请查看其他相关文档

  redis:
    host: 127.0.0.1
    port: 6379
    timeout: 3000
    database: 1

3. 启动redis

网上下载redis,安装后点击redis-cli.exe进行启动

在这里插入图片描述
在这里插入图片描述
为了方便查看下效果,我们可以本地安装一个redis图形化工具,推荐使用Another Redis Desktop Manager 下载地址:Another Redis Desktop Manager
在这里插入图片描述

4. 创建Redis工具类

package com.student.studentserver.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author gf
 * @date 2022/11/15
 */
@Slf4j
@Component
public class RedisUtil {

    @Autowired
    private StringRedisTemplate redisTemplate;

    private final String DEFAULT_KEY_PREFIX = "";
    private final int EXPIRE_TIME = 1;
    private final TimeUnit EXPIRE_TIME_TYPE = TimeUnit.DAYS;


    /**
     * 数据缓存至redis
     *
     * @param key
     * @param value
     * @return
     */
    public <K, V> void add(K key, V value) {
        try {
            if (value != null) {
                redisTemplate
                        .opsForValue()
                        .set(DEFAULT_KEY_PREFIX + key, JSON.toJSONString(value));
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new RuntimeException("数据缓存至redis失败");
        }
    }

    /**
     * 数据缓存至redis并设置过期时间
     *
     * @param key
     * @param value
     * @return
     */
    public <K, V> void add(K key, V value, long timeout, TimeUnit unit) {
        try {
            if (value != null) {
                redisTemplate
                        .opsForValue()
                        .set(DEFAULT_KEY_PREFIX + key, JSON.toJSONString(value), timeout, unit);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new RuntimeException("数据缓存至redis失败");
        }
    }

    /**
     * 写入 hash-set,已经是key-value的键值,不能再写入为hash-set
     *
     * @param key    must not be {@literal null}.
     * @param subKey must not be {@literal null}.
     * @param value  写入的值
     */
    public <K, SK, V> void addHashCache(K key, SK subKey, V value) {
        redisTemplate.opsForHash().put(DEFAULT_KEY_PREFIX + key, subKey, value);
    }

    /**
     * 写入 hash-set,并设置过期时间
     *
     * @param key    must not be {@literal null}.
     * @param subKey must not be {@literal null}.
     * @param value  写入的值
     */
    public <K, SK, V> void addHashCache(K key, SK subKey, V value, long timeout, TimeUnit unit) {
        redisTemplate.opsForHash().put(DEFAULT_KEY_PREFIX + key, subKey, value);
        redisTemplate.expire(DEFAULT_KEY_PREFIX + key, timeout, unit);
    }

    /**
     * 获取 hash-setvalue
     *
     * @param key    must not be {@literal null}.
     * @param subKey must not be {@literal null}.
     */
    public <K, SK> Object getHashCache(K key, SK subKey) {
        return  redisTemplate.opsForHash().get(DEFAULT_KEY_PREFIX + key, subKey);
    }


    /**
     * 从redis中获取缓存数据,转成对象
     *
     * @param key   must not be {@literal null}.
     * @param clazz 对象类型
     * @return
     */
    public <K, V> V getObject(K key, Class<V> clazz) {
        String value = this.get(key);
        V result = null;
        if (!StringUtils.isEmpty(value)) {
            result = JSONObject.parseObject(value, clazz);
        }
        return result;
    }

    /**
     * 从redis中获取缓存数据,转成list
     *
     * @param key   must not be {@literal null}.
     * @param clazz 对象类型
     * @return
     */
    public <K, V> List<V> getList(K key, Class<V> clazz) {
        String value = this.get(key);
        List<V> result = Collections.emptyList();
        if (!StringUtils.isEmpty(value)) {
            result = JSONArray.parseArray(value, clazz);
        }
        return result;
    }

    /**
     * 功能描述:Get the value of {@code key}.
     *
     * @param key must not be {@literal null}.
     * @return java.lang.String
     * @date 2021/9/19
     **/
    public <K> String get(K key) {
        String value;
        try {
            value = redisTemplate.opsForValue().get(DEFAULT_KEY_PREFIX + key);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new RuntimeException("从redis缓存中获取缓存数据失败");
        }
        return value;
    }

    /**
     * 删除key
     */
    public void delete(String key) {
        redisTemplate.delete(key);
    }

    /**
     * 批量删除key
     */
    public void delete(Collection<String> keys) {
        redisTemplate.delete(keys);
    }

    /**
     * 序列化key
     */
    public byte[] dump(String key) {
        return redisTemplate.dump(key);
    }

    /**
     * 是否存在key
     */
    public Boolean hasKey(String key) {
        return redisTemplate.hasKey(key);
    }

    /**
     * 设置过期时间
     */
    public Boolean expire(String key, long timeout, TimeUnit unit) {
        return redisTemplate.expire(key, timeout, unit);
    }

    /**
     * 设置过期时间
     */
    public Boolean expireAt(String key, Date date) {
        return redisTemplate.expireAt(key, date);
    }


    /**
     * 移除 key 的过期时间,key 将持久保持
     */
    public Boolean persist(String key) {
        return redisTemplate.persist(key);
    }

    /**
     * 返回 key 的剩余的过期时间
     */
    public Long getExpire(String key, TimeUnit unit) {
        return redisTemplate.getExpire(key, unit);
    }

    /**
     * 返回 key 的剩余的过期时间
     */
    public Long getExpire(String key) {
        return redisTemplate.getExpire(key);
    }

}

此工具类我们使用的是StringRedisTemplate

5. 创建测试类

创建测试类,我们向redis中添加一个字符串

@RestController
@RequestMapping(path = "/api/v1/student")
public class StudentController {
    @Autowired
    private RedisUtil redisUtil;

    @GetMapping("/redis")
    public String testRedis() {
        String notice="疫情又严重了,请大家自觉戴好口罩";
        redisUtil.add("notice",notice);
        return notice;
    }
}

6. 查看效果

在postman或浏览器中请求接口地址,查看redis中的结果
在这里插入图片描述
在这里插入图片描述

从缓存中获取值,redis根据key从缓存中获取值。

    public String testRedis() {
        String notice1 = redisUtil.get("notice");
        System.out.println("获取缓存的值:"+notice1);
        return notice1;
    }

这样我们就将数据存入到了Redis中,我们还可以设置redis的缓存时间,可以仔细看下RedisUtil中的其他方法,这里不做演示。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

图解计算机的存储器金字塔

本文已收录到 GitHub AndroidFamily&#xff0c;有 Android 进阶知识体系&#xff0c;欢迎 Star。技术和职场问题&#xff0c;请关注公众号 [彭旭锐] 进 Android 面试交流群。 前言 大家好&#xff0c;我是小彭。 在计算机组成原理中的众多概念中&#xff0c;开发者接触得最…

LeetCode-剑指43-1-n整数中出现1的次数

1、逐位统计 我们统计每一位k上面可能出现1的次数&#xff1a;1、对于每一位k上面的出现的1&#xff0c;我们首先统计其出现(n/10k)10k−1(n/10^k)\times10^{k-1}(n/10k)10k−1次的1&#xff1b;2、考虑到存在余数的情况&#xff0c;我们还需要比较剩余余数中出现1的次数&…

浅谈HTTP缓存与CDN缓存的那点事

HTTP缓存与CDN缓存一直是提升web性能的两大利器&#xff0c;合理的缓存配置可以降低带宽成本、减轻服务器压力、提升用户的体验。而不合理的缓存配置会导致资源界面无法及时更新&#xff0c;从而引发一系列的衍生问题。本文将分别将从HTTP缓存与cdn缓存的规则、流程、配置入手&…

XSS挑战之旅1-10关

文章目录前言第1关第2关第3关第4关第5关第6关第7关第8关第9关第10关前言 漏洞介绍&#xff1a;XSS漏洞 参考文章&#xff1a;XSS挑战之旅 游戏规则&#xff1a;触发alert()弹窗&#xff0c;进入下一关 第1关 进入第一关 随便输入一下&#xff0c;观测输出&#xff0c;看源代…

还在为数据库事务一致性检测而苦恼?让Elle帮帮你,以TDSQL为例我们测测 | DB·洞见#7

数据库用户通常依赖隔离级别来确保数据一致性&#xff0c;但很多数据库却并未达到其所表明的级别。主要原因是&#xff1a;一方面&#xff0c;数据库开发者对各个级别的理解有细微差异&#xff1b;另一方面&#xff0c;实现层面没有达到理论上的要求。 用户在使用或开发者在交…

147. SAP UI5 SmartTable 控件的使用介绍

本文来自笔者 SAP 开发技术交流知识星球内一位朋友的提问: smartfilter bar 有个输入框Cost Element绑定了cds实现value help 请问其对应的suggestion功能是通过cds的注解实现的嘛? 要回答这个问题,我们必须首先掌握 SAP UI5 SmartTable 控件的使用方式,然后才能深入探究 …

【Tensorflow】使用Tensorflow自定义模型和训练

Tensorflow的核心与NumPy非常相似&#xff0c;但具有GPU支持&#xff1b;Tensorflow支持分布式计算&#xff08;跨多个设备和服务器&#xff09;。 像NumPy一样使用TensorFlow 运算符是在Python 3.5 中添加的&#xff0c;用于矩阵乘法&#xff0c;等效于 tf.matmul() 函数。…

C++数据结构迷宫哈希表二叉树

C数据结构迷宫哈希表二叉树 《数据结构》应用系统设计——迷宫问题 问题描述:设计算法求出并显示从入口点到出口点可沿八个方向前进的一条通路&#xff0c;或显示没有通路 难度:易 基本要求: (1)键盘(或文件)输入迷宫行数m和列数n&#xff0c;计算机随机生成迷宫(或从文件读入…

robots (攻防世界)

前言: 这篇文章还是是为了帮助一些 像我这样的菜鸟 找到简单的题解 题目描述 进入网址 啥也没有 解题工具: 额...浏览器&#xff1f; (可能还需要百度) 问题解析: 科普时间到 robots协议也称爬虫协议、爬虫规则等, 是指网站建立一个robots.txt文件来告诉搜索引擎哪些…

安卓 手机硬改 工具下载 一键新机 改串 抹机 root隐藏 改串号MEID imei SN信息 工具教程分享

一键新机、模拟机型、一键备份、还原APP数据、ROOT隐藏、修改数据、保护隐私 一键新机 超过3000机型一键模拟、无束缚轻松做注册、激活、留存 安卓/IOS(进行中) 支持目前最流行的机型&#xff0c;安卓全机型兼容&#xff0c;我们坚持领先一步 操作简单 适合脚本作者 群控…

为了验证某些事,我实现了一个toy微前端框架【万字长文,请君一览】

众所周知微前端是企业中前端发展的必经之路。 我司搭建了自己的微前端脚手架工具&#xff0c;它将项目变成了“多页应用”&#xff0c;跳转方式由 location.href 这类api进行。所以笔者之前在想&#xff1a;这种方式跳转能不能有动画效果呢&#xff1f; 在“上层建筑”中进行“…

【文件同步和备份软件】上海道宁为您带来GoodSync软件,让您轻松备份和同步您的文件

GoodSync发布于2006年 是一种简单可靠的文件同步和 备份解决方案 使用GoodSync可以轻松备份和 同步您的文件 确保您的文件绝对不会丢失 GoodSync企业版是 为商用设计的 数据备份、同步和恢复软件 适用于所有平台、项目或业务环境 保护我们的商业数据 开发商介绍 Siber…

golang开发相关面试题

目录 go有哪些数据类型? 方法与函数有什么区别? 方法中值接收者与指针接收者的区别是什么? 函数返回局部变量的指针是否安全? 函数参数传递值是值传递还是引用传递? defer关键字的实现原理? 内置函数make和new的区别? slice底层实现原理? array与slice的区别是…

GICv3和GICv4虚拟化

本文档翻译自文档Arm Generic Interrupt Controller v3 and v4 - Virtualization 1 虚拟化 Armv8-A选择性的支持虚拟化。为了完成该功能&#xff0c;GICv3也支持虚拟化。GICv3中对虚拟化的支持包括如下功能&#xff1a; CPU Interface寄存器的硬件虚拟化产生和发送虚拟中断的…

pytorch深度学习实战lesson14

第十四课 丢弃法&#xff08;Dropout&#xff09; 目录 理论部分 实践部分 从零开始实现&#xff1a; 简洁实现&#xff1a; 理论部分 这节课很重要&#xff0c;因为沐神说这个丢弃法比上节课的权重衰退效果更好&#xff01; 为什么期望没变&#xff1f; 如上图所示&#…

java main方法控制日志级别

背景&#xff1a; 今天想用main方法去调用http请求&#xff0c;结果已经没什么问题了&#xff0c;但是打印了一大堆Http业务内部的日志信息&#xff0c;特别挡路&#xff0c;导致想看到的业务输出看不到&#xff0c;所以经过多方求证&#xff0c;进行了日志等级处理。 默认情…

【Pytorch with fastai】第 5 章 :图像分类

&#x1f50e;大家好&#xff0c;我是Sonhhxg_柒&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流&#x1f50e; &#x1f4dd;个人主页&#xff0d;Sonhhxg_柒的博客_CSDN博客 &#x1f4c3; &#x1f381;欢迎各位→点赞…

电商项目缓存问题的解决方案(初步)

内容分类 容量规化 架构设计 数据库设计 缓存设计 框架选型 数据迁移方案 性能压测 监控报警 领域模型 回滚方案 高并发 分库分表 优化策略 负载均衡 软件负载 nginx&#xff1a;它自身的高可用是用lvs去保证。 下单需要登录 > 需要Session > 分布式Ses…

好书赠送丨海伦·尼森鲍姆著:《场景中的隐私——技术、政治和社会生活中的和谐》,王苑等译

开放隐私计算 收录于合集#书籍分享1个 开放隐私计算 开放隐私计算OpenMPC是国内第一个且影响力最大的隐私计算开放社区。社区秉承开放共享的精神&#xff0c;专注于隐私计算行业的研究与布道。社区致力于隐私计算技术的传播&#xff0c;愿成为中国 “隐私计算最后一公里的服…

[附源码]java毕业设计基于javaweb电影购票系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…