0

0

java使用教程怎样使用Redis缓存数据 java使用教程的Redis操作基础方法​

絕刀狂花

絕刀狂花

发布时间:2025-08-11 18:42:03

|

429人浏览过

|

来源于php中文网

原创

redis作为缓存的优势在于其内存存储带来的高速读写、支持丰富的数据结构(如字符串、哈希、有序集合等)、具备持久化能力(rdb/aof),适用于热点数据缓存、查询结果缓存、会话管理、计数器与排行榜、消息队列等场景;2. java中选择redis客户端时,jedis简单直观适合小型项目,lettuce基于netty支持异步和高并发,适合高性能场景,spring data redis则提供与spring生态集成的高级抽象,推荐用于spring项目;3. 常见缓存问题包括缓存穿透(可采用缓存空值或布隆过滤器)、缓存击穿(可用互斥锁或永不过期策略)、缓存雪崩(可通过错开过期时间、多级缓存、熔断降级和redis高可用解决)、数据一致性(推荐cache-aside模式、延时双删或结合消息队列)以及内存管理(需合理设置淘汰策略、优化key设计、监控内存并考虑集群分片)。

java使用教程怎样使用Redis缓存数据 java使用教程的Redis操作基础方法​

用Java操作Redis来做缓存,说白了,就是引入一个合适的Redis客户端库(比如Jedis或Lettuce),然后通过这个库提供的API,将那些需要快速访问的数据存入Redis,在需要时从Redis中读取,以此来减轻后端数据库的压力,提升系统响应速度。它本质上就是一种内存中的键值存储,特别适合做数据高速存取层。

解决方案

在Java应用中使用Redis缓存数据,核心步骤通常包括引入依赖、配置连接、以及执行数据操作。这里我们以Jedis为例,因为它上手快,概念直观。

首先,你需要在项目的

pom.xml
(如果是Maven项目)或
build.gradle
(如果是Gradle项目)中添加Jedis的依赖:

立即学习Java免费学习笔记(深入)”;



    redis.clients
    jedis
    3.7.0 

接着,在Java代码中,你需要建立与Redis服务器的连接。这通常涉及指定Redis服务器的IP地址和端口。

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class RedisCacheExample {

    // 实际项目中,这些配置应该放在配置文件里,比如application.properties或yml
    private static final String REDIS_HOST = "localhost";
    private static final int REDIS_PORT = 6379;
    private static JedisPool jedisPool; // 连接池,推荐在生产环境使用

    static {
        // 配置连接池
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxTotal(100); // 最大连接数
        poolConfig.setMaxIdle(20);   // 最大空闲连接数
        poolConfig.setMinIdle(5);    // 最小空闲连接数
        poolConfig.setTestOnBorrow(true); // 每次从池中获取连接时,检查连接是否有效
        poolConfig.setTestOnReturn(true); // 每次将连接归还到池中时,检查连接是否有效
        poolConfig.setTestWhileIdle(true); // 空闲时是否进行连接验证

        // 初始化连接池
        jedisPool = new JedisPool(poolConfig, REDIS_HOST, REDIS_PORT);
        System.out.println("JedisPool initialized for Redis at " + REDIS_HOST + ":" + REDIS_PORT);
    }

    /**
     * 从Redis连接池获取Jedis实例
     * 实际使用时,通常通过try-with-resources确保连接关闭
     */
    public static Jedis getJedis() {
        return jedisPool.getResource();
    }

    /**
     * 将数据存入Redis缓存,并设置过期时间
     * @param key 键
     * @param value 值
     * @param expireSeconds 过期时间(秒)
     */
    public static void cacheData(String key, String value, int expireSeconds) {
        try (Jedis jedis = getJedis()) {
            jedis.setex(key, expireSeconds, value); // setex = set + expire
            System.out.println("Cached: " + key + " -> " + value + " (Expires in " + expireSeconds + "s)");
        } catch (Exception e) {
            System.err.println("Error caching data: " + e.getMessage());
            // 生产环境应该记录日志,考虑熔断或降级策略
        }
    }

    /**
     * 从Redis缓存中获取数据
     * @param key 键
     * @return 对应的值,如果不存在则返回null
     */
    public static String getCachedData(String key) {
        try (Jedis jedis = getJedis()) {
            String value = jedis.get(key);
            System.out.println("Retrieved: " + key + " -> " + (value != null ? value : "null"));
            return value;
        } catch (Exception e) {
            System.err.println("Error getting cached data: " + e.getMessage());
            return null;
        }
    }

    /**
     * 从Redis缓存中删除数据
     * @param key 键
     * @return 删除的键的数量
     */
    public static Long deleteCachedData(String key) {
        try (Jedis jedis = getJedis()) {
            Long deletedCount = jedis.del(key);
            System.out.println("Deleted: " + key + " (Count: " + deletedCount + ")");
            return deletedCount;
        } catch (Exception e) {
            System.err.println("Error deleting cached data: " + e.getMessage());
            return 0L;
        }
    }

    public static void main(String[] args) throws InterruptedException {
        // 示例使用
        String userId = "user:1001";
        String userData = "{\"name\":\"张三\", \"age\":30}";
        int expireTime = 60; // 缓存60秒

        // 模拟第一次查询,数据从数据库来,存入缓存
        System.out.println("--- 首次查询,数据从数据库获取并缓存 ---");
        cacheData(userId, userData, expireTime);

        // 模拟后续查询,数据从缓存获取
        System.out.println("\n--- 后续查询,数据从缓存获取 ---");
        String cachedValue = getCachedData(userId);
        if (cachedValue != null) {
            System.out.println("成功从缓存获取数据: " + cachedValue);
        } else {
            System.out.println("缓存中没有数据,需要从数据库加载。");
        }

        // 等待缓存过期
        System.out.println("\n--- 等待缓存过期... (2秒后) ---");
        Thread.sleep(2000); // 实际中不会这么短,这里只是为了演示过期

        System.out.println("\n--- 再次查询,缓存可能已过期 ---");
        String expiredValue = getCachedData(userId);
        if (expiredValue != null) {
            System.out.println("缓存仍有效: " + expiredValue);
        } else {
            System.out.println("缓存已过期或不存在,需要重新从数据库加载。");
        }

        // 清理缓存
        System.out.println("\n--- 清理缓存 ---");
        deleteCachedData(userId);
        getCachedData(userId); // 验证是否已删除

        // 关闭连接池
        if (jedisPool != null) {
            jedisPool.close();
            System.out.println("JedisPool closed.");
        }
    }
}

这段代码展示了如何通过Jedis连接池来管理Redis连接,以及最常用的

setex
(设置带过期时间的键值对)、
get
(获取键值)和
del
(删除键)操作。实际项目里,你通常会把这些Redis操作封装到一个服务层或者DAO层里,比如
UserService
里有个
getUserById
方法,它会先尝试从缓存里取,取不到再去数据库。

Redis缓存的优势与适用场景是什么?

Redis作为缓存层,它的优势简直不要太多,尤其是在高性能和灵活度上。首先,它速度快得惊人,因为数据全部在内存里,而且它的底层数据结构设计得非常精妙,读写操作的复杂度大多是O(1)或O(logN)。这跟传统关系型数据库动辄磁盘I/O比起来,简直是云泥之别。其次,它支持丰富的数据结构,不光是简单的字符串,还有哈希、列表、集合、有序集合,这些能让你在处理复杂业务逻辑时,不用再把所有东西都序列化成字符串,直接利用Redis的特性就能高效存储和操作,比如用有序集合做排行榜,用哈希存对象。再有,它支持持久化,虽然是内存数据库,但RDB和AOF两种持久化方式能保证数据在服务器重启后也能恢复,这给生产环境使用带来了极大的信心。

至于适用场景,那可就太多了:

  • 热点数据缓存: 这是最常见的,比如电商网站的商品详情、新闻网站的热点文章、用户个人资料等。这些数据访问频率高,但更新频率相对较低,非常适合放在Redis里,能大幅降低数据库压力,提升用户体验。
  • 查询结果缓存: 那些执行时间长、涉及多表连接的复杂查询结果,可以直接缓存起来。下次相同的查询请求过来,直接从Redis返回,避免了重复的昂贵计算。
  • 会话管理: 分布式系统里,用户的Session信息可以统一存放在Redis中,这样无论用户请求被转发到哪台服务器,都能找到对应的会话信息,实现无状态的服务。
  • 计数器与排行榜: Redis的原子性操作和有序集合,天生就是做各种计数器(如点赞数、浏览量)和排行榜(如热门商品、积分榜)的利器,效率极高。
  • 消息队列: 简单场景下,Redis的列表(List)结构可以充当一个轻量级的消息队列,实现生产者-消费者模式。

在我看来,只要你的应用存在“读多写少”或者“需要极速响应”的场景,Redis就几乎是首选的缓存方案。

如何选择合适的Java Redis客户端库?

Java生态里操作Redis的客户端库,最常用的无非就是Jedis和Lettuce,当然还有Spring Data Redis这个更高层面的抽象。选择哪个,真的要看你的项目需求和技术栈偏好。

Jedis:

SUN2008 企业网站管理系统2.0 beta
SUN2008 企业网站管理系统2.0 beta

1、数据调用该功能使界面与程序分离实施变得更加容易,美工无需任何编程基础即可完成数据调用操作。2、交互设计该功能可以方便的为栏目提供个性化性息功能及交互功能,为产品栏目添加产品颜色尺寸等属性或简单的留言和订单功能无需另外开发模块。3、静态生成触发式静态生成。4、友好URL设置网页路径变得更加友好5、多语言设计1)UTF8国际编码; 2)理论上可以承担一个任意多语言的网站版本。6、缓存机制减轻服务器

下载
  • 特点: 它是Redis官方推荐的第一个Java客户端,历史悠久,社区活跃。它的API设计非常直观,跟Redis命令几乎一一对应,学习曲线很平缓。Jedis是阻塞式的,这意味着当你执行一个Redis命令时,当前线程会等待直到Redis返回结果。
  • 优点: 上手快,代码简洁,对于简单的应用或者快速验证原型非常友好。
  • 缺点: 阻塞特性在高并发场景下可能会成为瓶颈,因为它会占用大量线程。如果连接池配置不当,或者Redis响应慢,很容易导致线程池耗尽。
  • 适用场景: 对并发要求不那么极致的小型应用、教学示例、或者你就是喜欢它简单粗暴的风格。

Lettuce:

  • 特点: 这是一个比较新的、非阻塞的、基于Netty的Redis客户端。它支持异步和响应式编程模型(Reactive Streams),这意味着你发送一个Redis命令后,线程可以立即去做其他事情,等Redis结果返回时再通过回调或Future来处理。
  • 优点: 高性能、高并发,能够充分利用CPU资源,非常适合现代的微服务架构和异步编程模型。支持Redis 6的客户端缓存(Client-side Caching)等高级特性。
  • 缺点: 学习曲线相对Jedis要陡峭一些,异步编程模型对开发者要求更高。
  • 适用场景: 高并发、高性能要求的系统,响应式编程风格的项目,或者你已经在使用Spring WebFlux等异步框架。

Spring Data Redis:

  • 特点: 它不是一个独立的Redis客户端,而是Spring框架提供的一个抽象层,它封装了Jedis和Lettuce,提供了更高级别的API和模板方法,让你不用直接接触Jedis或Lettuce的底层API。它还提供了缓存注解(
    @Cacheable
    等),能让你以声明式的方式使用缓存。
  • 优点: 与Spring生态无缝集成,简化了Redis的配置和使用,提供了统一的API。支持事务、消息发布/订阅等。
  • 缺点: 增加了抽象层,有时调试起来可能不如直接使用Jedis/Lettuce那么直观。
  • 适用场景: 任何使用Spring框架的项目,特别是Spring Boot项目,它能大大提高开发效率。

我个人觉得,如果你只是想快速跑个Demo或者项目并发量不高,Jedis足矣。但如果你的项目是面向高并发、需要异步处理或者已经深度拥抱Spring生态,那么Lettuce或者Spring Data Redis(底层用Lettuce)会是更明智的选择。特别是Spring Data Redis,它能让你更专注于业务逻辑,而不是Redis的底层操作。

Redis缓存的常见问题与优化策略有哪些?

用Redis做缓存,虽然好处多多,但也不是一劳永逸。总会遇到一些挑战,这些挑战处理不好,反而会拖累系统。

  • 缓存穿透 (Cache Penetration)

    • 问题: 用户请求的数据既不在缓存中,也不在数据库中。比如恶意攻击者频繁查询一个不存在的商品ID。每次请求都会穿透缓存,直接打到数据库上,可能导致数据库崩溃。
    • 策略:
      1. 缓存空值: 如果从数据库查询的结果为空,也把这个空值缓存起来,并设置一个较短的过期时间。这样下次同样的请求过来,就直接从缓存返回空,避免了对数据库的无效查询。
      2. 布隆过滤器 (Bloom Filter): 在缓存层和数据库层之间加一个布隆过滤器。查询前,先通过布隆过滤器判断数据是否存在。如果布隆过滤器说不存在,那就一定不存在,直接返回;如果说可能存在,再去查缓存和数据库。布隆过滤器有误判率,但能大幅减少无效请求。
  • 缓存击穿 (Cache Breakdown)

    • 问题: 某个热点数据(比如爆款商品的库存)突然过期了,同时有大量请求涌入。这些请求都会因为缓存失效而直接打到数据库上,瞬间的巨大压力可能导致数据库宕机。
    • 策略:
      1. 互斥锁 (Mutex Lock): 当缓存失效时,只有一个线程允许去数据库加载数据并回写缓存,其他线程则等待或者从队列中获取结果。这可以用Redis的分布式锁来实现。
      2. 永不过期: 对于特别热点的数据,可以设置其永不过期,或者过期时间非常长。但需要配合后台线程定时刷新缓存,或者在数据更新时主动删除/更新缓存。
      3. 异步刷新: 当缓存即将过期时,启动一个后台线程去异步刷新数据,而不是等到请求过来时才刷新。
  • 缓存雪崩 (Cache Avalanche)

    • 问题: 大量缓存数据在同一时间集中失效,或者Redis服务宕机。这会导致所有请求都直接打到数据库上,数据库瞬间压力剧增,可能导致服务雪崩。
    • 策略:
      1. 错开过期时间: 给不同的key设置不同的过期时间,可以在基础过期时间上加上一个随机值。比如,一个商品缓存30分钟,可以设置为
        30 + random(0, 10)
        分钟。
      2. 多级缓存: 引入多级缓存,比如本地缓存+Redis缓存。当Redis失效时,请求可以先走本地缓存。
      3. 熔断与降级: 当数据库压力过大时,可以对部分非核心业务进行降级处理,比如返回默认值、友好提示,或者直接拒绝服务,保护核心服务。
      4. Redis高可用: 部署Redis集群(如Sentinel或Cluster),确保Redis服务本身的稳定性和可用性。
  • 数据一致性

    • 问题: 缓存中的数据与数据库中的数据不一致。这是缓存系统最头疼的问题之一。
    • 策略:
      1. Cache-Aside (旁路缓存) 模式: 这是最常用的模式。
        • 读: 先读缓存,缓存没有再读数据库,然后把数据写入缓存。
        • 写: 先更新数据库,再删除(或更新)缓存。这里删除缓存比更新缓存更安全,因为更新缓存可能遇到并发问题导致脏数据。
      2. 延时双删: 在更新数据库后,先删除缓存。然后等待一小段时间(比如几秒),再次删除缓存。这是为了应对数据库更新成功,但删除缓存失败,或者在删除缓存期间,另一个读请求读取了旧数据并写入缓存的情况。
      3. 消息队列: 通过MQ来异步通知缓存更新或删除,确保最终一致性。当数据库数据更新后,发送一条消息到MQ,缓存服务订阅此消息,收到后更新或删除对应的缓存。
  • 内存管理

    • 问题: Redis是内存数据库,如果缓存的数据量过大,可能会导致内存溢出,或者频繁触发Redis的内存淘汰策略,影响性能。
    • 策略:
      1. 设置合理的淘汰策略: Redis支持多种内存淘汰策略(如LRU、LFU、随机等),根据业务场景选择最合适的。
      2. 合理设计key: 避免存储过大的value,将大对象拆分成多个小对象存储。
      3. 监控: 实时监控Redis的内存使用情况,及时发现并解决问题。
      4. 数据分片/集群: 当单机Redis内存不足时,考虑使用Redis集群进行数据分片,将数据分散到多台机器上。

这些问题和策略,其实都是在实践中踩坑、总结出来的经验。没有哪个方案是完美的,关键在于理解业务,然后选择最适合的组合拳来应对。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
spring框架介绍
spring框架介绍

本专题整合了spring框架相关内容,想了解更多详细内容,请阅读专题下面的文章。

112

2025.08.06

Java Spring Security 与认证授权
Java Spring Security 与认证授权

本专题系统讲解 Java Spring Security 框架在认证与授权中的应用,涵盖用户身份验证、权限控制、JWT与OAuth2实现、跨站请求伪造(CSRF)防护、会话管理与安全漏洞防范。通过实际项目案例,帮助学习者掌握如何 使用 Spring Security 实现高安全性认证与授权机制,提升 Web 应用的安全性与用户数据保护。

26

2026.01.26

spring boot框架优点
spring boot框架优点

spring boot框架的优点有简化配置、快速开发、内嵌服务器、微服务支持、自动化测试和生态系统支持。本专题为大家提供spring boot相关的文章、下载、课程内容,供大家免费下载体验。

135

2023.09.05

spring框架有哪些
spring框架有哪些

spring框架有Spring Core、Spring MVC、Spring Data、Spring Security、Spring AOP和Spring Boot。详细介绍:1、Spring Core,通过将对象的创建和依赖关系的管理交给容器来实现,从而降低了组件之间的耦合度;2、Spring MVC,提供基于模型-视图-控制器的架构,用于开发灵活和可扩展的Web应用程序等。

390

2023.10.12

Java Spring Boot开发
Java Spring Boot开发

本专题围绕 Java 主流开发框架 Spring Boot 展开,系统讲解依赖注入、配置管理、数据访问、RESTful API、微服务架构与安全认证等核心知识,并通过电商平台、博客系统与企业管理系统等项目实战,帮助学员掌握使用 Spring Boot 快速开发高效、稳定的企业级应用。

70

2025.08.19

Java Spring Boot 4更新教程_Java Spring Boot 4有哪些新特性
Java Spring Boot 4更新教程_Java Spring Boot 4有哪些新特性

Spring Boot 是一个基于 Spring 框架的 Java 开发框架,它通过 约定优于配置的原则,大幅简化了 Spring 应用的初始搭建、配置和开发过程,让开发者可以快速构建独立的、生产级别的 Spring 应用,无需繁琐的样板配置,通常集成嵌入式服务器(如 Tomcat),提供“开箱即用”的体验,是构建微服务和 Web 应用的流行工具。

34

2025.12.22

Java Spring Boot 微服务实战
Java Spring Boot 微服务实战

本专题深入讲解 Java Spring Boot 在微服务架构中的应用,内容涵盖服务注册与发现、REST API开发、配置中心、负载均衡、熔断与限流、日志与监控。通过实际项目案例(如电商订单系统),帮助开发者掌握 从单体应用迁移到高可用微服务系统的完整流程与实战能力。

135

2025.12.24

什么是分布式
什么是分布式

分布式是一种计算和数据处理的方式,将计算任务或数据分散到多个计算机或节点中进行处理。本专题为大家提供分布式相关的文章、下载、课程内容,供大家免费下载体验。

327

2023.08.11

Python 自然语言处理(NLP)基础与实战
Python 自然语言处理(NLP)基础与实战

本专题系统讲解 Python 在自然语言处理(NLP)领域的基础方法与实战应用,涵盖文本预处理(分词、去停用词)、词性标注、命名实体识别、关键词提取、情感分析,以及常用 NLP 库(NLTK、spaCy)的核心用法。通过真实文本案例,帮助学习者掌握 使用 Python 进行文本分析与语言数据处理的完整流程,适用于内容分析、舆情监测与智能文本应用场景。

10

2026.01.27

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Django 教程
Django 教程

共28课时 | 3.6万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.3万人学习

Kotlin 教程
Kotlin 教程

共23课时 | 2.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号