Redis适用场景

Redis适用场景

  • 一、加速缓存
  • 二、会话管理
  • 三、排行榜和计数器
  • 四、消息队列
  • 五、实时分析
  • 六、分布式锁
  • 七、地理位置数据
  • 八、限流
  • 九、数据共享
  • 十、签到

一、加速缓存

Redis最常见的应用之一是作为缓存层,用于存储频繁访问的数据,从而减轻数据库的负载。
通过将数据存储在内存中,Redis可以实现高速的读取和写入操作,极大地提升应用程序的性能。例如,在一个电子商务网站中,可以将热门商品的信息存储在Redis中,当用户访问这些商品时,首先从Redis中读取,如果Redis中没有,再从数据库中读取并更新到Redis中。
示例
假设我们有一个在线书店应用,用户经常查看书籍的详细信息。
我们可以使用Redis来缓存这些热门书籍的信息:

// 尝试从Redis缓存中获取书籍信息
Book cachedBook = redisTemplate.opsForValue().get(id);
if (cachedBook != null) {return cachedBook;
}// 如果缓存中没有,从数据库查询
Bookbook book = bookRepository.findById(id).orElse(null);
if (book != null) {// 将查询结果放入缓存,并设置过期时间redisTemplate.opsForValue().set(id, book, 10, TimeUnit.MINUTES);
}
return book;

二、会话管理

在Web应用中,Redis常用于存储用户会话信息,如登录状态、购物车内容等。
由于其快速的读写速度,Redis非常适合这种需要频繁访问和更新的数据。
示例
假设我们有一个需要用户登录的Web应用,可以使用Redis来存储用户的登录状态:

// 用户登录时,将会话信息存储到Redis中
redisTemplate.opsForValue().set(sessionId, user, 1, TimeUnit.HOURS);// 用户访问时,从Redis中获取会话信息
User user = redisTemplate.opsForValue().get(sessionId);
if (user != null) {// 用户已登录,继续处理请求
} else {// 用户未登录,重定向到登录页面
}

三、排行榜和计数器

Redis的原子增减操作非常适合用于计数器和排行榜应用,如社交媒体的点赞数、阅读数、排名等。
Redis的Sorted Set数据类型可以方便地实现排行榜功能。
示例
假设我们要实现一个文章阅读量排行榜:

// 增加文章的阅读量
redisTemplate.opsForValue().increment("article:" + articleId + ":views");// 获取排行榜
Set<ZSetOperations.TypedTuple<String>> range = redisTemplate.opsForZSet().reverseRangeWithScores("article:views", 0, 9);
for (ZSetOperations.TypedTuple<String> tuple : range) {System.out.println("文章ID: " + tuple.getValue() + ", 阅读量: " + tuple.getScore());
}

四、消息队列

Redis支持发布/订阅模式,可以用作轻量级的消息队列系统,用于异步任务处理、事件处理等。
示例
假设我们要实现一个异步任务处理系统:

// 生产者发送消息
redisTemplate.convertAndSend("taskQueue", new TaskMessage("processData"));// 消费者接收消息并处理
@RedisMessageListener(topics = "taskQueue")
public void receiveMessage(Message message, String channel) {TaskMessage taskMessage = (TaskMessage) message.getBody();processData(taskMessage.getData());
}

五、实时分析

Redis的有序集合和位图数据结构使其成为实时分析和计数的理想工具,可以用于记录用户活动、页面访问量等。
示例
假设我们要统计网站的访问量:

// 增加页面访问量
redisTemplate.opsForValue().increment("page:" + pageId + ":views");// 获取页面访问量
Long views = redisTemplate.opsForValue().get("page:" + pageId + ":views");
System.out.println("页面访问量: " + views);

六、分布式锁

在分布式系统中,Redis可以用于实现分布式锁,可以在分布式系统中协调多节点对共享资源的访问,确保操作的原子性。
示例:

// 实现一个分布式锁来防止并发写入数据库
// 尝试获取锁
Boolean lockAcquired = redisTemplate.opsForValue().setIfAbsent("lock:data", "locked", 10, TimeUnit.SECONDS);
if (lockAcquired) {try {// 持有锁,执行数据库写操作} finally {// 释放锁redisTemplate.delete("lock:data");}
} else {// 获取锁失败,等待或重试
}
public void redisLock() throws InterruptedException {//获取锁(重入锁),执行锁的名称RLock lock = redissonclient.getlock("my:book:lock:id");//尝试获取锁,参数分别是:获取锁的最大等待时间(期间会重试),锁自动释放时间,时间单位//boolean isLock=lock.tryLock(10,30,TimeUnit.SECONDS);boolean isLock =lock.tryLock( time:10,TimeUnit.SECONDS);//判断是否获取成功if (isLock) {try {System.out.println("执行业务");} finally {//释放锁lock.unlock();}}
}
public <T> T executeWithLock(String lockKey, long timeout, Callable<T> action) {RLock lock = redissonClient.getLock(lockKey);boolean isLock = false;try {// 尝试获取锁,最大等待时间1秒,锁自动释放时间为timeout秒isLock = lock.tryLock(1, timeout, TimeUnit.SECONDS);if (isLock) {try {// 执行传入的操作并返回结果return action.call();} finally {// 检查是否持有锁再释放if (lock.isHeldByCurrentThread()) {lock.unlock();}}} else {System.out.println("未能获取锁,稍后重试");return null; // 或者抛出异常}} catch (InterruptedException e) {// 处理异常,恢复线程中断状态Thread.currentThread().interrupt();System.out.println("获取锁时被中断");return null; // 或者抛出异常} catch (Exception e) {// 处理其他异常System.out.println("执行操作时发生异常: " + e.getMessage());return null; // 或者抛出异常}
}

redis实现的分布式锁是不可重入的。同一个线程再次获取锁会失败。
redisson实现的分布式锁是可重入的。同一个线程可以再次获取锁,判断依据是线程id。可重入能避免多个锁之间产生死锁的问题。它在存储锁数据的时候利用的是hash结构记录线程id和重入次数,key是自定义的锁名称。

七、地理位置数据

Redis支持地理空间数据,可以用于构建地理位置应用,如附近的人、地点推荐等功能。
示例
假设我们要实现一个附近的人功能:

// 添加地理位置坐标
redisTemplate.opsForGeo().add("users", "user1", 116.397428, 39.90923);// 查询附近的人
GeoResults<RedisGeoCommands.GeoLocation<String>> nearbyUsers = redisTemplate.opsForGeo().radius("users", 116.397428, 39.90923, 1, RedisGeoCommands.GeoUnit.KILOMETERS);
for (GeoResult<RedisGeoCommands.GeoLocation<String>> result : nearbyUsers) {System.out.println("用户ID: " + result.getContent().getName() + ", 距离: " + result.getDistance().getValue() + "km");
}
# 添加餐厅地理位置
GEOADD restaurants 13.361389 38.115556 "餐厅A"
GEOADD restaurants 15.087269 37.502669 "餐厅B"
GEOADD restaurants 9.191383 45.464211 "餐厅C"# 用户当前位置:经纬度 (14, 37)
# 查找附近 100 公里内的餐厅
GEORADIUS restaurants 14 37 100 km
# 返回:餐厅A 餐厅B

八、限流

Redis 适合用于限流(Rate Limiting)场景。限流的目的是控制某个操作在特定时间内的访问频率,比如 API 请求、短信发送、登录尝试等。Redis 的原子操作和高效性能使其成为实现限流的理想工具。
示例
假设我们要限制API的调用频率

// 尝试获取令牌
Long tokens = redisTemplate.opsForValue().increment("api:" + apiId + ":tokens");
if (tokens <= 10) {// 令牌充足,处理请求
} else {// 令牌不足,拒绝请求
}

使用 Redis 实现滑动窗口计数器

  • 使用 Redis 的 List 存储每次请求的时间。
  • 每次请求时,移除时间窗口外的旧记录,并添加新记录。
  • 统计当前时间窗口内的记录数,如果超过阈值则拒绝请求。

限制每个用户每分钟只能访问10次,假设用户在第一分钟的最后一秒访问了9次,又在下一分钟的第一秒访间了10次,这样的访问是可以通过现在的访问频率限制的,但实际上该用户在2秒内访问了19次,这与每个用户每分钟只能访问10次的限制差距较大。尽管这种情况比较极端,但是在一些场合中还是需要粒度更小的控制方案。如果要精确地保证每分钟最多访问10次需要记下用户每次访问的时间。
因此对每个用户,我们使用一个列表类型的键来记录他最近10次访间客的时间。一旦键中的元素超过10个,就判断时间最早的元素距现在的时间是否小于1分钟。如果是则表示用户最近1分钟的访问次数超过了10次;如果不是就将现在的时间加入到列表中,同时把最早的元素删除。
如果要限制“A时间最多访问B次”时,如果“B”的数值较大,此方法会占用较多的存储空间,实际使用时还需要开发者自己去权衡。

// 伪代码如下
// 获取列表长度
$listLength = LLEN rate:limiting:$IP
if $listLength<10// 将当前时间新增到列表左侧LPUSH rate:limiting:$IP now()
else // 获取列表最后一位元素,也就是最早的那个时间$time = LINDEX rate:limiting:$IP - 1if now() - $time < 60return "访问超过了限制"else// 将当前时间新增到列表左侧,并删除最右侧的元素LPUSH rate:limiting:$IP now()RPOP rate:limiting:$IP

九、数据共享

在微服务架构中,Redis可以作为服务间共享数据的媒介。
示例
假设我们有两个服务需要共享用户信息:

// 服务A设置用户信息
redisTemplate.opsForValue().set("user:" + userId, user);// 服务B获取用户信息
User user = redisTemplate.opsForValue().get("user:" + userId);

十、签到

Redis的Bitmap是一种非常适合用于签到系统的数据结构。它通过位图(bit array)存储和操作数据,可以高效地处理大量的签到操作,特别适合于需要频繁更新并查询某个用户是否已签到的场景。
假设每个用户的签到状态通过 位图(Bitmap) 记录,每个用户对应一个唯一的 ID,通过设置和查询位来确定该用户是否签到。

设置用户 101 已签到
SETBIT sign_in_bitmap 101 1比如查询用户 ID 为 101 的签到状态
GETBIT sign_in_bitmap 101统计总共有多少用户已签到
BITCOUNT sign_in_bitmap

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

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

相关文章

【LangChain4j快速入门】5分钟用Java接入AI大模型,Spring Boot整合实战!| 附源码

【LangChain4j快速入门】5分钟用Java接入AI大模型&#xff0c;Spring Boot整合实战&#xff01; 前言&#xff1a;当Java遇上大模型 在AI浪潮席卷全球的今天&#xff0c;Java开发者如何快速拥抱大语言模型&#xff1f;LangChain4j作为专为Java打造的AI开发框架&#xff0c;以…

2025第十七届“华中杯”大学生数学建模挑战赛题目B 题 校园共享单车的调度与维护问题完整成品正文33页(不含附录)文章思路 模型 代码 结果分享

校园共享单车运营优化与调度模型研究 摘 要 本研究聚焦校园共享单车点位布局、供需平衡、运营效率及故障车辆回收四大核心问题&#xff0c;通过构建一系列数学模型&#xff0c;系统分析与优化共享单车的运维体系。 针对问题一&#xff0c;我们建立了基于多时段观测的库存估算…

Unity游戏多语言工具包

由于一开始的代码没有考虑多语言场景&#xff0c;导致代码中提示框和UI显示直接用了中文&#xff0c;最近开始提取代码的中文&#xff0c;提取起来太麻烦&#xff0c;所以拓展了之前的多语言包&#xff0c;降低了操作复杂度。最后把工具代码提取出来到单独项目里面&#xff0c;…

.NET MCP 文档

MCP 概述 MCP&#xff08;Model Context Protocol&#xff09;是由 Anthropic 推出的一种开放协议&#xff0c;类似 AI 的 USB-C 扩展坞&#xff0c;用于在大模型和数据源之间建立安全的通信&#xff08;授权&#xff09;&#xff0c;让 AI 应用能够安全地访问和操作本地或远程…

【Linux】vim配置----超详细

目录 一、插件管理器准备 二、目录准备 三、安装插件 一、插件管理器准备 Vim-plug 是一个Vim插件管理器&#xff0c;利用异步并行可以快速地安装、更新和卸载插件。它的安装和配置都非常简单&#xff0c;而且在操作过程中会给出很多易读的反馈信息&#xff0c;是一个自由、…

PHP实现图片自动添加水印效果

<?php // 设置原始图片路径和水印图片路径 $original_image original.jpg; $watermark_image watermark.png;// 创建图片资源 $original imagecreatefromjpeg($original_image); $watermark imagecreatefrompng($watermark_image);// 获取图片尺寸 $original_width im…

检查新接手LINUX服务器应用的部署情况和正在运行的服务

当接手一台新的 Linux 服务器时&#xff0c;第一要务就是摸清系统上已经安装部署了哪些应用和服务。 本文将以 CentOS7为例&#xff0c;详细介绍如何系统地排查已安装的应用和服务&#xff0c;包括它们的安装方式和安装位置。 1.查看系统基本信息 首先获取系统整体信息&…

使用注解方式整合ssm时,启动tomcat扫描不到resource下面的xxxmapper.xml问题,解决方法

解决org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.xxx.mapper.方法 在Spring与Mybatis整合时&#xff0c;可能会遇到这样的报错 原因&#xff1a; 其原因为mapper路径的映射错误&#xff0c;表示在尝试执行某个 Mapper 接口的方法时…

C++11特性补充

目录 lambda表达式 定义 捕捉的方式 可变模板参数 递归函数方式展开参数包 数组展开参数包 移动构造和移动赋值 包装器 绑定bind 智能指针 RAII auto_ptr unique_ptr shared_ptr 循环引用 weak_ptr 补充 总结 特殊类的设计 不能被拷贝的类 只能在堆上创建…

My SQL 索引

核心目标&#xff1a; 理解 mysql 索引的工作原理、类型、优缺点&#xff0c;并掌握创建、管理和优化索引的方法&#xff0c;以显著提升数据库查询性能。 什么是索引&#xff1f; 索引是一种特殊的数据库结构&#xff0c;它包含表中一列或多列的值以及指向这些值所在物理行的指…

极狐GitLab 注册限制如何设置?

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;关于中文参考文档和资料有&#xff1a; 极狐GitLab 中文文档极狐GitLab 中文论坛极狐GitLab 官网 注册限制 (BASIC SELF) 您可以对注册实施以下限制&#xff1a; 禁用新注册。新注册需要管理员批准。需要用户电子邮件确认。…

10.(vue3.x+vite)div实现tooltip功能(css实现)

1:效果截图 2:代码实现 <template><div><div class="tooltip" style="margin-top: 20%; margin-left: 20%; background-color: blueviolet; color: white;

Linux下 文件的查找、复制、移动和解压缩

1、在/var/log目录下创建一个hehe.log的文件&#xff0c;其文件内容是&#xff1a; myhostname ghl mydomain localdomain relayhost [smtp.qq.com]:587 smtp_use_tls yes smtp_sasl_auth_enable yes smtp_sasl_security_options noanonymous smtp_sasl_tls_security_opt…

Ubuntu 安装 Docker 教程(官方推荐方式)

✅ 步骤 1&#xff1a;卸载旧版本&#xff08;如果有&#xff09; for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done---### ✅ 步骤 2&#xff1a;更新 APT 索引并安装依赖项bash sudo a…

计算机视觉与深度学习 | Transformer原理,公式,代码,应用

Transformer 详解 Transformer 是 Google 在 2017 年提出的基于自注意力机制的深度学习模型,彻底改变了序列建模的范式,解决了 RNN 和 LSTM 在长距离依赖和并行计算上的局限性。以下是其原理、公式、代码和应用的详细解析。 一、原理 核心架构 Transformer 由 编码器(Encod…

计算机基础 | 常见进制与单位简介 / 表示 / 描述

注&#xff1a;本文为 “进制与常见单位应用” 相关文章合辑。 原文为繁体&#xff0c;注意术语描述差异。 略作重排。 进制简介&#xff08;二进制、八进制、十进制、十六进制&#xff09; 发表于 2017-01-20 郑中胜 数字系统&#xff08;Numeral system&#xff09;&#…

门面模式与适配器模式

一、门面模式 门面模式&#xff1a;提供统一接口访问子系统接口 1、包含角色 外观系统对外的统一接口子系统类的集合&#xff1b;并不知道外观角色的存在&#xff0c;需要为了配合外观角色而做特殊处理或修改 2、举例 原本开关灯要分别操作各个房间的灯&#xff0c;现在设置总…

SpringBoot Actuator指标收集:Micrometer与Prometheus集成

文章目录 引言一、Spring Boot Actuator基础二、Micrometer简介与集成三、基本指标收集与配置四、自定义业务指标实现五、与Prometheus集成六、实战案例&#xff1a;API性能监控总结 引言 在现代微服务架构中&#xff0c;监控应用程序的健康状况和性能指标变得至关重要。Sprin…

【Android面试八股文】Android应用进程的启动流程【二】

应用进程 1.1 Android系统进程的启动过程&#xff1a; 1、init进程fork出Zygote进程后&#xff0c;Zygote进程会创建一个服务端socket&#xff0c;等待AMS发起socket请求。 同时&#xff0c;由Zygote进程fork出的SystemServer进程会启动各项系统服务&#xff0c;其中就包含了A…

基于Django的AI客服租车分析系统

基于Django的AI客服租车分析系统 【包含内容】 【一】项目提供完整源代码及详细注释 【二】系统设计思路与实现说明 【三】AI智能客服与用户交互指导手册 【技术栈】 ①&#xff1a;系统环境&#xff1a;Python 3.8&#xff0c;Django 4.2框架 ②&#xff1a;开发环境&a…