Redis常用的八种场景

作为一名 Java后端人员,对 Redis肯定并不陌生,Redis作为一种内存数据库,以其速度之快在编程的舞台上纵横多年,那么,Redis到底适合哪些业务场景?今天就来聊一聊。

1. 缓存/数据库

缓存(Cache)是 Redis使用最广泛的场景之一,也是很多小伙伴结识 Redis的重要原因,在 8种10倍提升API性能的方式 文章中我们也强调了Redis可以作为缓存的来加速 API性能。如下图,在 WebServer和数据库之间会增加一层 Redis缓存,这样 WebServer可以直接从Redis中快速拿到数据返回,加快了 WebServer的响应速度。

举例:

  • 电商领域,可以缓存一些热门商品的静态信息或用户数据,这样,在大流量访问时,不用查询数据库,加速访问速度。
  • 配置中心,业务开发中,经常会使用一些全局配置,而且配置更改的频率很低,因此,可以把配置都加载到 Redis内存中,加快查询数据。

需要说明的是:很多时候,我们都会把 Redis的持久化功能打开,因此,在把 Redis当作缓存的同时,同样把 Redis当作数据库在使用。

2. 分布式锁

分布式锁(Distributed Lock)也是 Redis使用最广泛的场景之一,分布式系统中,当我们在处理有并发的业务场景时,为了保证线程安全,通常通常会使用分布式锁,单机下,Redis通常使用 SET NX(if Not Exist)和 PX(过期时间)来创建锁,指令如下:

# 如果key不存,set key=value,
# 失效时间是 expiration毫秒
SET key value NX PX expiration

在 Java中,Redission是一个基于 Redis的分布式Java对象映射(Java Redis Client),它提供了丰富的特性和工具,示例代码展示了如何在 Redission框架中使用 Redis分布式锁:

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;

public class RedissonExample {
    public static void main(String[] args) {
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379");
        RedissonClient redisson = Redisson.create(config);

        // 使用分布式锁
        String lockKey = "lockKey";
        boolean isLocked = redisson.getLock(lockKey).tryLock();
        if (isLocked) {
            // 获得锁,执行相关操作
            System.out.println("Lock acquired successfully");
            redisson.getLock(lockKey).unlock(); // 释放锁
        } else {
            System.out.println("Failed to acquire lock");
        }
        redisson.shutdown(); // 关闭连接
    }
}

需要说明的是:除了Redis,Zookeeper也是实现分布式锁比较常用的一种技术方案。

3. 限流

限流(Rate Limiter)也是 Redis使用比较多的一个场景,限流是保护系统免受过载的一种方法,它可以确保在指定时间内对系统的请求进行限制。在 Redis 中,可以使用 SET、EXPIRE 和 Lua 脚本来实现简单的限流功能。

示例代码展示了Java Jedis 库实现基于令牌桶算法的 Redis 限流:

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Response;
import redis.clients.jedis.Transaction;

public class RateLimiter {
    private final Jedis jedis;
    private final String key;
    private final int capacity;
    private final int tokensPerSecond;

    public RateLimiter(Jedis jedis, String key, int capacity, int tokensPerSecond) {
        this.jedis = jedis;
        this.key = key;
        this.capacity = capacity;
        this.tokensPerSecond = tokensPerSecond;
    }
   
    /**
    * 用于检查是否允许请求,根据当前令牌数量和容量进行判断
    */ 
    public boolean allowRequest() {
        long now = System.currentTimeMillis();
        Transaction transaction = jedis.multi();
        // Add current time with score
        transaction.zadd(key, now, String.valueOf(now)); 
        // Remove tokens that are older than 1 second
        transaction.zremrangeByScore(key, 0, now - 1000); 
        // Get current number of tokens
        Response<Long> sizeResponse = transaction.zcard(key); 

        transaction.exec();

        long size = sizeResponse.get();
        // Check if number of tokens is within capacity
        return size <= capacity; 
    }

    public static void main(String[] args) {
        Jedis jedis = new Jedis("localhost"); // Connect to Redis
        // Create rate limiter
        RateLimiter rateLimiter = new RateLimiter(jedis, "RateLimiterKey", 10, 5); 

        for (int i = 0; i < 15; i++) {
            boolean allowed = rateLimiter.allowRequest();
            if (allowed) {
                System.out.println("Request allowed");
            } else {
                System.out.println("Request denied");
            }
        }

        // Close Redis connection
        jedis.close(); 
    }
}
4. 会话存储

会话(Session)也是 Redis常见的一种功能,熟悉 Spring的小伙伴肯定知道它也有一个 Session功能,那么它和 Redis的 Session有什么区别呢?

Spring Session是一个抽象层,提供与存储后端衔接能力,至于后端采用内存、数据库还是Redis存储Spring Session不关注。而 Redis Session是 Spring Session的一种具体实现,将会话数据存储在Redis中。

举例:存储用户登录信息:

#将用户的登录信息存储在 Redis中,key:userId, value:user登录信息
SET user:userId {"username": "xxx", "password": "xxx",...}
5. 发布/订阅

发布/订阅(Sub/Pub)是 Redis中一个类似于消息中间件(MQ)的功能,当我们的业务中有需要通过事件触发的场景时可以使用该功能,不过 Redis的 Sub/Pub功能还是比较简陋,有复杂的业务场景时还是推荐MQ。

举例

群聊,在实时聊天应用中,利用 Redis的发布/订阅功能实现消息广播。

实现事件通知系统,如新订单通知、新邮件提醒等。

#订阅频道
SUBSCRIBE channel_xxx
# 向频道中发送消息
PUBLISH channel_xxx "Message content"
6. 排名/排行榜

排名/排行榜(Rank/LeaderBoard)是 Redis中一个比较实用的功能,在文章热榜、游戏竞技或社区平台中,排行榜(Leaderboard)和排名(Ranking)系统是常见的功能,用于展示用户在特定活动、比赛或指标上的排名情况,而 Redis的有序集合(Sorted Set)是实现排行榜功能的理想数据结构,因为它可以存储每个成员的分数,并根据分数进行排序。

举例:

(1) 记录网站访问次数或文章阅读次数

# 添加文章的点击量
#将 Article1 的值增加1。如果Article1 不存在于有序集合中,
# 该命令会将 Article1 添加到集合,并设置值为1
ZINCRBY leaderboard 1 "Article1"
ZINCRBY leaderboard 1 "Article2"
ZINCRBY leaderboard 1 "Article3"

# 获取 Article2的排名(从高到低排名)
ZREVRANK leaderboard "Article2" 

# 获点击量 Top10 的文章和点击量
ZREVRANGE leaderboard 0 9 WITHSCORES

(2) 实现用户积分排行榜

7. 计数

在 Redis中,可以使用 INCR、DECR 等命令来进行简单的计数操作。这些命令用于对键的值进行递增或递减操作,常用于实现计数器等功能。

常用计数命令:

# 对 key进行 +1 操作
INCR key
# 对key 进行 -1 操作
DECR key

# 对 key进行 +n 操作
INCRBY key n
# 对 key进行 -n 操作
DECRBY key n

另外,在排名/排行榜中,ZINCRBY 是对 Sort set的一种计数方式。

举例:

  • 网站访问量计数器,可以实时统计网站的访问次数;
  • 点赞/喜欢计数器,对文章或内容的点赞或喜欢次数进行计数;
  • 用户在线状态统计,统计在线用户数量;
8. 地理位置应用

Redis的地理位置应用功能使用的场景比较有针对性,如果你不是在特定的领域,可能并不会使用该功能,它是 通过 Geo数据类型支持地理位置存储和检索,可以用于构建位置服务和地理位置相关的应用。

举例:

(1) 点过外卖的小伙伴肯定不陌生,外卖平台上,附近商家搜索功能。

# 查找经度12.087269,纬度39.412669 附近5 km的距离范围
GEORADIUS locations 12.087269 39.412669 5 km

(2) 打车平台,比如一些网约车平台,就可以把司机,乘客的位置信息(经纬度)通过Redis的Geo来实现距离计算等功能。

# 添加经纬度信息,经纬度是编造的,不一定真实
GEOADD locations 12.322389 39.125356 "Driver"
GEOADD locations 12.087269 39.412669 "Passenger"
# 计算司机和乘客两地点间的距离
GEODIST locations Driver Passenger
总结

本文介绍了Redis常见的 8种实用场景:

  • 缓存/数据库
  • 分布式锁
  • 限流
  • 会话存储
  • 发布/订阅
  • 排名/排行榜
  • 计数
  • 地理位置应用

如果你在业务中不确定是否需要引入 Redis时,可以参考本文,如果场景刚好命中其中一种,那么可以选择使用 Redis。如果你的业务场景不在这 8种常见场景中,不代表不能使用 Redis,可能需要你更多的技术调研来确认合适的技术方案。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ESP32 http 请求

目录 参考教程1.使用的http连接2.使用Vscode-IDF创建http_request例程3.修改http_request_example_main.c函数4.已经获取到响应的数据 参考教程 ESP-IDF HTTP获取网络时间 1.使用的http连接 http://api.m.taobao.com/rest/api3.do?apimtop.common.getTimestamp请求可以得到…

校园报修抢修小程序系统开发 物业小区报修预约上门维修工单系统

开发的功能模块有&#xff1a; 1.报修工单提交&#xff1a;学生、教职员工等可以使用小程序提交报修请求。这通常包括选择报修的问题类型&#xff08;如水漏、电器故障、照明问题等&#xff09;&#xff0c;地点&#xff0c;报修联系人&#xff0c;联系电话等&#xff0c;并提供…

C语言——I /深入理解指针(一)

一、内存和地址 1byte&#xff08;字节&#xff09; 8bit&#xff08;比特位&#xff09; 1KB 1024byte 1MB 1024KB 1GB 1024MB 1TB 1024GB 1PB 1024TB一个比特位可以存放二进制的0/1的一位 ⽣活中我们把⻔牌号也叫地址&#xff0c;在计算机中我们把内存单元的编号也称为…

Java学习day14:权限修饰符,集合(知识点+例题详解)

声明&#xff1a;该专栏本人重新过一遍java知识点时候的笔记汇总&#xff0c;主要是每天的知识点题解&#xff0c;算是让自己巩固复习&#xff0c;也希望能给初学的朋友们一点帮助&#xff0c;大佬们不喜勿喷(抱拳了老铁&#xff01;) 往期回顾 Java学习day13&#xff1a;泛型&…

kettle创建数据库资源库kettle repository manager

数据库资源库是将作业和转换相关的信息存储在数据库中&#xff0c;执行的时候直接去数据库读取信息&#xff0c;很容易跨平台使用。 创建数据库资源库&#xff0c;如图 1.点击Connect 2.点击Repository Manager 3.点击Other Repository 4.点击Database Repository 在选择Ot…

Selenium IDE录制脚本

文章目录 1.环境搭建1.1 Chrome浏览器安装1.2 Chrome驱动安装1.3 Selenium IDE插件的安装 2.Selenium IDE插件介绍2.1 初始化界面2.2 菜单栏2.3 工具栏2.4 地址栏2.5 测试用例窗口2.6 测试脚本窗口2.7 日志和引用窗口 3.元素定位3.1 通过id进行元素定位3.2 通过name进行元素定位…

听GPT 讲Rust源代码--src/bootstrap

图片来自 使用rust的image库进行图片压缩[1] File: rust/src/bootstrap/build.rs 在Rust源代码中&#xff0c;rust/src/bootstrap/build.rs这个文件是一个构建脚本。构建脚本是一个在编译Rust编译器本身时运行的程序&#xff0c;它用于初始化和配置Rust编译器的构建过程。build…

数据结构【栈】

文章目录 数据结构 栈栈的概念与结构栈接口实现 数据结构 栈 栈的概念与结构 栈是是一种特殊的线性表&#xff0c;栈的规定是只在一端插入删除数据&#xff0c;插入删除的一端叫做栈顶&#xff0c;另一端叫栈底。根据上面的特性&#xff0c;栈的数据是后入先出 栈接口实现 栈接…

Java-方法的重写

【1】重写&#xff1a; 发生在子类和父类中&#xff0c;当子类对父类提供的方法不满意的时候&#xff0c;要对父类的方法进行重写。 【2】重写有严格的格式要求&#xff1a; 子类的方法名字和父类必须一致&#xff0c;参数列表&#xff08;个数&#xff0c;类型&#xff0c…

Java基础-----StringBuffer和StringBuilder

文章目录 1.StringBuffer1.1 构造方法1.2 常用方法 2.StringBuilder3.String、StringBuffer、StringBuilder的区别 1.StringBuffer 内容可变的字符串类&#xff0c;适应StringBuffer来对字符串的内容进行动态操作&#xff0c;不会产生额外的对象。StringBuffer在初始时&#x…

【Spring】SpringBoot的扩展点之ApplicationContextInitializer

简介 其实spring启动步骤中最早可以进行扩展的是实现ApplicationContextInitializer接口。来看看这个接口的注释。 package org.springframework.context;/*** Callback interface for initializing a Spring {link ConfigurableApplicationContext}* prior to being {linkpl…

【Linux】【开发】使用sed命令遇到的乱码问题

&#x1f41a;作者简介&#xff1a;花神庙码农&#xff08;专注于Linux、WLAN、TCP/IP、Python等技术方向&#xff09;&#x1f433;博客主页&#xff1a;花神庙码农 &#xff0c;地址&#xff1a;https://blog.csdn.net/qxhgd&#x1f310;系列专栏&#xff1a;Linux技术&…

蓝桥杯每日一题2023.11.20

题目描述 “蓝桥杯”练习系统 (lanqiao.cn) 题目分析 方法一&#xff1a;暴力枚举&#xff0c;如果说数字不在正确的位置上也就意味着这个数必须要改变&#xff0c;进行改变记录即可 #include<bits/stdc.h> using namespace std; const int N 2e5 10; int n, a[N], …

基于野狗算法优化概率神经网络PNN的分类预测 - 附代码

基于野狗算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于野狗算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于野狗优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神经网络的光滑…

【教3妹学编辑-mysql】详解数据库三大范式

什么是范式 简单地理解就是&#xff1a;数据库设计时遵循的规范 三大范式 数据库三大范式包含&#xff1a;1、第一范式(1NF)&#xff1b;2、第二范式(2NF)&#xff1b;3、第三范式(3NF)。其中&#xff0c;第一范式(1NF)的要求是属性不可分割&#xff0c;第二范式(2NF)的要求是…

Java基础-----正则表达式

文章目录 1.简介2.目的3.学习网站4.常用匹配字符5.String类中用到正则表达式的方法 1.简介 又叫做规则表达式。是一种文本模式&#xff0c;包括普通字符和特殊字符&#xff08;元字符&#xff09;。正则使用单个字符来描述、匹配一系列某个句法规则的字符串&#xff0c;通常用…

机器学习笔记 - Ocr识别中的CTC算法原理概述

一、文字识别 在文本检测步骤中,分割出了文本区域。现在需要识别这些片段中存在哪些文本。 机器学习笔记 - Ocr识别中的文本检测EAST网络概述-CSDN博客文章浏览阅读300次。在 EAST 网络的这个分支中,它合并了 VGG16 网络不同层的特征输出。现在,该层之后的特征大小将等于 p…

《崩坏:星穹铁道》1.5仙舟罗浮-绥园全宝箱攻略

大家好&#xff0c;我是闲游盒小盒子&#xff0c;本篇来说下崩铁1.5版本仙舟罗浮-绥园的全宝箱攻略&#xff0c;共有19个宝箱加1个扑满&#xff1b;做完间章可获取前14个普通宝箱加2个精英怪宝箱&#xff0c;以及1个扑满&#xff1b;完成《狐斋志异》全任务可获得另外3个宝箱。…

Wireshark抓包:理解TCP三次握手和四次挥手过程

TCP是一种面向连接、端到端可靠的协议&#xff0c;它被设计用于在互联网上传输数据和确保成功传递数据和消息。本节来介绍一下TCP中的三次握手和四次挥手。 文章目录 1 TCP头部格式2 wireshark抓包分析2.1 SEQ和ACK2.2 三次握手2.3 四次挥手 3 程序 1 TCP头部格式 TCP头部占据…

Unity--互动组件(Scrollbar)||Unity--互动组件(DropDown )

此组件中的&#xff0c;交互&#xff0c;过渡&#xff0c;导航与文章&#xff08;Unity--互动组件&#xff08;Button&#xff09;&#xff09;中的介绍如同&#xff1b; handle rect&#xff1a;&#xff08;父节点矩形&#xff09; 用于控件的滑动“句柄”部分的图形&#xf…
最新文章