使用redis的5种常用场景
文章目录
- 1. 缓存热点数据
- 2. 分布式锁
- 3. 计数器和限流器
- 4. 消息队列
- 5. 会话管理
- 总结
在日常开发工作中,Redis作为一款高性能的内存数据库,凭借其强大的功能特性和卓越的性能表现,已经成为了许多项目中不可或缺的组件。本文将详细介绍Redis在实际工作中最常见的5种应用场景,并附上具体的代码实现。
1. 缓存热点数据
在高并发系统中,大量的数据库查询会对系统性能造成严重影响。通过Redis缓存热点数据,可以显著减少数据库的访问压力,提升系统响应速度。
实现示例:
public class ProductService {@Autowiredprivate RedisTemplate<String, Product> redisTemplate;@Autowiredprivate ProductMapper productMapper;private static final String PRODUCT_KEY_PREFIX = "product:";private static final long CACHE_TIMEOUT = 3600; // 缓存过期时间:1小时public Product getProduct(Long productId) {// 构建Redis键String redisKey = PRODUCT_KEY_PREFIX + productId;// 首先从Redis中查询Product product = redisTemplate.opsForValue().get(redisKey);if (product != null) {// 缓存命中,直接返回return product;}// 缓存未命中,查询数据库product = productMapper.selectById(productId);if (product != null) {// 将查询结果存入RedisredisTemplate.opsForValue().set(redisKey, product, CACHE_TIMEOUT, TimeUnit.SECONDS);}return product;}
}
2. 分布式锁
在分布式系统中,常常需要控制对共享资源的访问。Redis的SETNX命令提供了一种实现分布式锁的简单方法。
实现示例:
public class RedisLock {@Autowiredprivate StringRedisTemplate redisTemplate;private static final long LOCK_TIMEOUT = 10000; // 锁超时时间:10秒public boolean acquireLock(String lockKey, String requestId) {// 使用SETNX命令尝试获取锁Boolean isLocked = redisTemplate.opsForValue().setIfAbsent(lockKey, requestId,LOCK_TIMEOUT,TimeUnit.MILLISECONDS);return Boolean.TRUE.equals(isLocked);}public boolean releaseLock(String lockKey, String requestId) {// 使用Lua脚本确保原子性操作String script = "if redis.call('get', KEYS[1]) == ARGV[1] then "+ "return redis.call('del', KEYS[1]) "+ "else "+ "return 0 "+ "end";Long result = redisTemplate.execute(new DefaultRedisScript<>(script, Long.class),Collections.singletonList(lockKey),requestId);return Long.valueOf(1).equals(result);}
}
3. 计数器和限流器
Redis的INCR命令可以原子性地实现计数器功能,非常适合用于实现访问统计和接口限流。
实现示例:
public class RateLimiter {@Autowiredprivate StringRedisTemplate redisTemplate;private static final String RATE_LIMIT_PREFIX = "rate:limit:";private static final int MAX_REQUESTS = 100; // 每分钟最大请求次数public boolean isAllowed(String userId) {String key = RATE_LIMIT_PREFIX + userId;// 获取当前时间的分钟数作为窗口long currentMinute = System.currentTimeMillis() / (60 * 1000);String windowKey = key + ":" + currentMinute;// 原子性增加计数Long count = redisTemplate.opsForValue().increment(windowKey);if (count == 1) {// 设置过期时间为1分钟redisTemplate.expire(windowKey, 60, TimeUnit.SECONDS);}// 判断是否超过限制return count <= MAX_REQUESTS;}
}
4. 消息队列
虽然Redis不是专门的消息队列系统,但它的List数据结构配合LPUSH和BRPOP命令可以实现简单的消息队列功能。
实现示例:
public class RedisMessageQueue {@Autowiredprivate StringRedisTemplate redisTemplate;private static final String QUEUE_KEY = "message:queue";// 生产者public void sendMessage(String message) {redisTemplate.opsForList().leftPush(QUEUE_KEY, message);}// 消费者@Asyncpublic void consumeMessage() {while (true) {try {// 阻塞式获取消息List<String> message = redisTemplate.opsForList().rightPop(QUEUE_KEY,30,TimeUnit.SECONDS);if (message != null) {// 处理消息processMessage(message);}} catch (Exception e) {log.error("处理消息出错", e);}}}private void processMessage(List<String> message) {// 具体的消息处理逻辑}
}
5. 会话管理
Redis的Hash数据结构非常适合存储用户会话信息,支持部分字段的更新,且可以设置过期时间。
实现示例:
public class SessionManager {@Autowiredprivate StringRedisTemplate redisTemplate;private static final String SESSION_KEY_PREFIX = "session:";private static final long SESSION_TIMEOUT = 1800; // 会话超时时间:30分钟public void saveSession(String sessionId, Map<String, String> sessionData) {String key = SESSION_KEY_PREFIX + sessionId;// 使用Hash结构存储会话数据redisTemplate.opsForHash().putAll(key, sessionData);// 设置过期时间redisTemplate.expire(key, SESSION_TIMEOUT, TimeUnit.SECONDS);}public void updateSessionField(String sessionId, String field, String value) {String key = SESSION_KEY_PREFIX + sessionId;// 更新单个字段redisTemplate.opsForHash().put(key, field, value);// 刷新过期时间redisTemplate.expire(key, SESSION_TIMEOUT, TimeUnit.SECONDS);}public Map<Object, Object> getSession(String sessionId) {String key = SESSION_KEY_PREFIX + sessionId;return redisTemplate.opsForHash().entries(key);}public void deleteSession(String sessionId) {String key = SESSION_KEY_PREFIX + sessionId;redisTemplate.delete(key);}
}
总结
Redis凭借其出色的性能和丰富的数据结构,在实际工作中可以解决很多具体问题。上述5种场景只是Redis应用的冰山一角,在实际开发中,我们还可以根据具体需求,结合Redis的特性来设计更多的解决方案。
在使用Redis时,需要注意以下几点:
- 合理设置过期时间,避免内存占用过大
- 注意缓存与数据库的一致性问题
- 在分布式环境下要考虑并发问题
- 根据实际需求选择合适的数据结构
- 定期监控Redis的内存使用情况和性能指标
相关文章:
使用redis的5种常用场景
文章目录 1. 缓存热点数据2. 分布式锁3. 计数器和限流器4. 消息队列5. 会话管理总结 在日常开发工作中,Redis作为一款高性能的内存数据库,凭借其强大的功能特性和卓越的性能表现,已经成为了许多项目中不可或缺的组件。本文将详细介绍Redis在实…...
微信小程序防止重复点击事件
直接写在app.wpy里面,全局可以调用 // 防止重复点击事件preventActive(fn) {const self this;if (this.globalData.PageActive) {this.globalData.PageActive false;if (fn) fn();setTimeout(() > {self.globalData.PageActive true;}, 3000); //设置该时间内…...
PySpark用sort-merge join解决数据倾斜的完整案例
假设有两个大表 table1 和 table2 ,并通过 sort-merge join 来解决可能的数据倾斜问题。 from pyspark.sql import SparkSession from pyspark.sql.functions import col# 初始化SparkSession spark SparkSession.builder.appName("SortMergeJoinExample&quo…...
sklearn-逻辑回归-制作评分卡
目录 数据集处理 分箱 分多少个箱子合适 分箱要达成什么样的效果 对一个特征进行分箱的步骤 分箱的实现 封装计算 WOE 值和 IV值函数 画IV曲线,判断最佳分箱数量 结论 pd.qcut 执行报错 功能函数封装 判断分箱个数 在银行借贷场景中,评分卡是…...
scrapy爬取图片
scrapy 爬取图片 环境准备 python3.10scrapy pillowpycharm 简要介绍scrapy Scrapy 是一个开源的 Python 爬虫框架,专为爬取网页数据和进行 Web 抓取而设计。它的主要特点包括: 高效的抓取性能:Scrapy 采用了异步机制,能够高效…...
在 Vue 项目中使用地区级联选
在 Vue 项目中使用地区级联选择的完整流程: 1.安装依赖包,这个包提供了中国省市区的完整数据。 npm install element-china-area-data --save 2.导入数据 import { regionData } from element-china-area-data 这个包提供了几种不同的数据格式&#…...
【简博士统计学习方法】第1章:1. 统计学习的定义与分类
自用笔记 1. 统计学习的定义与分类 1.1 统计学习的概念 统计学习(Statistical Machine Learning)是关于计算机基于数据构建概率统计模型并运用模型对数据进行预测与分析的一门学科。 以计算机和网络为平台;以数据为研究对象;以…...
利用 Python 脚本批量创建空白 Markdown 笔记
文章目录 利用 Python 脚本批量创建空白 Markdown 笔记1 背景介绍2 需求描述3 明确思路4 具体实现4.1. 遍历 toc.md 文件,收集文件名和对应的文件内容4.2. 实现文件批量生成逻辑4.3. 补全缺失的工具函数4.4. 进一步补全工具函数中的工具函数 5 脚本运行6 注意事项 利…...
【Qt】C++11 Lambda表达式
1. 举例 connect(ui->pushButton, &QPushButton::clicked, [](bool checked){//具体代码qDebug() << "Hello" << checked;}); 2. 详情 //完整形式 [ capture ] ( params ) opt -> ret { body; }; capture 是捕获列表params 是参数表opt 是函数…...
怎样提高服务器中的数据传输速度?
服务器中的数据传输速度会影响着用户的体验感,当企业中的数据传输速度出现卡顿或者是过慢时,用户不能及时浏览到所需的内容,给用户造成不好的体验感,那么企业该怎样才能提高服务器中的数据传输速度呢? 服务器之间如何传…...
Vue 封装公告滚动
文章目录 需求分析1. 创建公告组件Notice.vue2. 注册全局组件3. 使用 需求 系统中需要有一个公告展示,且这个公告位于页面上方,每个页面都要看到 分析 1. 创建公告组件Notice.vue 第一种 在你的项目的合适组件目录下(比如components目录&a…...
JVM实战—12.OOM的定位和解决
大纲 1.如何对系统的OOM异常进行监控和报警 2.如何在JVM内存溢出时自动dump内存快照 3.Metaspace区域内存溢出时应如何解决(OutOfMemoryError: Metaspace) 4.JVM栈内存溢出时应如何解决(StackOverflowError) 5.JVM堆内存溢出时应该如何解决(OutOfMemoryError: Java heap s…...
【python翻译软件V1.0】
如果不想使用密钥的形式,且需要一个直接可用的中英文翻译功能,可以使用一些免费的公共 API,如 opencc 或其他无需密钥的库,或直接用 requests 获取翻译结果。 其中,我可以给你一个简单的代码示例,使用 tra…...
Spring Boot中的依赖注入是如何工作
Spring Boot 中的依赖注入(Dependency Injection,简称 DI)是通过 Spring 框架的核心机制——控制反转(Inversion of Control,IOC)容器来实现的。Spring Boot 基于 Spring Framework,在应用中自动…...
ubuntu22.04 编译安装libvirt 10.x
环境安装 sudo apt-get update -y sudo apt-get install qemu-system-x86 bridge-utils libyajl-dev -y sudo apt-get install build-essential autoconf automake libtool -y sudo apt-get install libxml2-dev libxslt1-dev libgnutls28-dev libpciaccess-dev libnl-3-de…...
[fastadmin] 第三十四篇 FastAdmin 商城模块标签使用详解
FastAdmin 商城模块标签使用详解 一、标签基本语法 1.1 基础语法格式 {shop:goodslist flag"参数值" id"变量名" row"数量"}<!-- 循环内容 --> {/shop:goodslist}1.2 常用参数说明 flag: 商品标记筛选id: 循环变量名row: 显示数量 1.…...
(2024,LLaVA-Bench (Wilder),LLaVA-NeXT,LLaMA3,Qwen-1.5,语言模型扩展)
LLaVA-NeXT: Stronger LLMs Supercharge Multimodal Capabilities in the Wild 目录 1. 简介 2. 探索大规模语言模型的能力极限 3. LLaVA-Bench (Wilder):日常生活视觉聊天基准 4. Benchmark 结果 1. 简介 我们通过引入近期更强大的开源大语言模型(…...
IPEX-LLM开发项目过程中的技术总结和心得
IPEX-LLM开发项目过程中的技术总结和心得 在人工智能快速发展的时代,高效地开发和部署大语言模型(LLM)已成为技术人员的必备技能。在我们的项目中,我们采用了 Intel Extension for PyTorch(简称 IPEX)和 L…...
HTTP/HTTPS ②-Cookie || Session || HTTP报头
这里是Themberfue 上篇文章介绍了HTTP报头的首行信息 本篇我们将更进一步讲解HTTP报头键值对的含义~~~ ❤️❤️❤️❤️ 报头Header ✨再上一篇的学习中,我们了解了HTTP的报头主要是通过键值对的结构存储和表达信息的;我们已经了解了首行的HTTP方法和UR…...
【软考】软件设计师
「学习路线」(推荐该顺序学习,按照先易后难排序) 1、上午题—计算机系统(5~6分)[1.8; ] 2、上午题—程序设计语言(固定6分)[1.9; ] 3、下午题—试题一(15分) 4、上午题—…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...
.Net Framework 4/C# 关键字(非常用,持续更新...)
一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...
智能AI电话机器人系统的识别能力现状与发展水平
一、引言 随着人工智能技术的飞速发展,AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术,在客户服务、营销推广、信息查询等领域发挥着越来越重要…...
【SpringBoot自动化部署】
SpringBoot自动化部署方法 使用Jenkins进行持续集成与部署 Jenkins是最常用的自动化部署工具之一,能够实现代码拉取、构建、测试和部署的全流程自动化。 配置Jenkins任务时,需要添加Git仓库地址和凭证,设置构建触发器(如GitHub…...
用鸿蒙HarmonyOS5实现国际象棋小游戏的过程
下面是一个基于鸿蒙OS (HarmonyOS) 的国际象棋小游戏的完整实现代码,使用Java语言和鸿蒙的Ability框架。 1. 项目结构 /src/main/java/com/example/chess/├── MainAbilitySlice.java // 主界面逻辑├── ChessView.java // 游戏视图和逻辑├── …...
k8s从入门到放弃之Pod的容器探针检测
k8s从入门到放弃之Pod的容器探针检测 在Kubernetes(简称K8s)中,容器探测是指kubelet对容器执行定期诊断的过程,以确保容器中的应用程序处于预期的状态。这些探测是保障应用健康和高可用性的重要机制。Kubernetes提供了两种种类型…...
Java中HashMap底层原理深度解析:从数据结构到红黑树优化
一、HashMap概述与核心特性 HashMap作为Java集合框架中最常用的数据结构之一,是基于哈希表的Map接口非同步实现。它允许使用null键和null值(但只能有一个null键),并且不保证映射顺序的恒久不变。与Hashtable相比,Hash…...
【SSM】SpringMVC学习笔记7:前后端数据传输协议和异常处理
这篇学习笔记是Spring系列笔记的第7篇,该笔记是笔者在学习黑马程序员SSM框架教程课程期间的笔记,供自己和他人参考。 Spring学习笔记目录 笔记1:【SSM】Spring基础: IoC配置学习笔记-CSDN博客 对应黑马课程P1~P20的内容。 笔记2…...
Git 切换到旧提交,同时保证当前修改不丢失
在 Git 中,可以通过以下几种方式切换到之前的提交,同时保留当前的修改 1. 使用 git checkout 创建临时分离头指针(推荐用于查看代码) git checkout <commit-hash>这会让你进入"分离头指针"状态,你可…...
