使用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、上午题—…...
Linux应用开发之网络套接字编程(实例篇)
服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...
内存分配函数malloc kmalloc vmalloc
内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...
UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...
UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...
均衡后的SNRSINR
本文主要摘自参考文献中的前两篇,相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程,其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt 根发送天线, n r n_r nr 根接收天线的 MIMO 系…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...
视觉slam十四讲实践部分记录——ch2、ch3
ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...
CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)
漏洞概览 漏洞名称:Apache Flink REST API 任意文件读取漏洞CVE编号:CVE-2020-17519CVSS评分:7.5影响版本:Apache Flink 1.11.0、1.11.1、1.11.2修复版本:≥ 1.11.3 或 ≥ 1.12.0漏洞类型:路径遍历&#x…...
