Redis 之 ZSET 实战应用场景,持续更新!

news2024/11/17 3:34:22

前言

大白话介绍 Redis 五大基本数据类型之一的 ZSET 开发中常见的应用场景

ZSET 介绍

  • ZSET 与 SET 相同点:都是是 String类型元素的集合,且不允许重复的成员
  • ZSET 与 SET 不同点:ZSET 每个元素都会关联一个 Double 类型的分数,Redis
    通过分数来为集合中的成员进行从小到大的排序。ZSET 的成员是唯一的,但分数 score 却可以重复

ZSET 应用场景

  1. 基于 ZSET 实现的滑动窗口限流
  2. 直播间送礼物排名榜
  3. 网易新闻、百度热搜,实时新闻、文章类的需求

ZSET 常用 Redis 指令介绍

直接对着控制台简单实操一下,方便大家理解。熟悉指令的读者可自行跳过本章节
在这里插入图片描述

zremrangeByScore

移除 key 为 ranking 且 source 值在 (0,1) 区间的所有数据,返回结果是 3,代表成功移除 3 条数据

zremrangeByScore ranking 0 1

zremrangeByScore ranking 0 1

zcard

统计 key 为 ranking 中剩余元素的个数,移除 3 条数据还剩一条,因此返回结果是 1

zcard ranking

在这里插入图片描述

zrevrangeByScore

ZSET 分页查询,LIMIT 对满足条件的成员列表进行分页。一般会配合 “+inf” 或者 “-inf” 来表示最大值和最小值。这个最大最小值针对于 score 而言。

zrevrangeByScore ranking +inf -inf LIMIT 0 2

在这里插入图片描述

zincrby

没有当前成员则新增、有则修改分数

zincrby ranking 666 "无名黑马"

在这里插入图片描述

zadd

往 ZSET 中添加元素

zadd ranking 5 "王老五"

在这里插入图片描述

基于 ZSET 实现的滑动窗口 Lua 脚本

实现步骤:

  1. 删除固定时间窗口之前的所有的数据
  2. 统计剩余元素数量
  3. 剩余元素数量超过设定阈值,返回 0,没超过返回 1
-- 1. 依赖 redis 中的 zset 类型,zremrangeByScore命令含义:移除0ARGV[1]的所有数据
redis.call('zremrangeByScore', KEYS[1], 0, ARGV[1])
-- 2. 统计剩余元素数量
local res = redis.call('zcard', KEYS[1])
-- 3. 剩余元素是否超过阈值
if (res == nil) or (res < tonumber(ARGV[3])) then
    -- 4.没超过阈值 zadd
    redis.call('zadd', KEYS[1], ARGV[2], ARGV[4])
    return 1
else
    return 0
end

redis.call()表示执行当前的 redis 指令,比方说 redis.call(‘zremrangeByScore’, ‘ranking’, 0, 1) 等价于执行 zremrangeByScore ranking 0 1 这么一条命令。 Java 代码调用代码如下。

 /**
     * unit秒内只能通过qps个请求
     */
    public Object acquire(String key, Integer unit, String qps) {
        long now = System.currentTimeMillis();
        Assert.notNull(unit, "unit不能为 null");
        /**
         * --KEYS[1]: 限流 key
         * --ARGV[1]: 限流窗口(String.valueOf(now - 1000 * unit))
         * --ARGV[2]: 当前时间戳(String.valueOf(now))
         * --ARGV[3]: 阈值 qps
         * --ARGV[4]: score 对应的唯一value(String.valueOf(now))
         */
        return redisTemplate.execute(redisScript,
                Arrays.asList(defaultKeyPrefix + key),
                String.valueOf(now - 1000 * unit),
                String.valueOf(now),
                qps == null ? defaultQps : qps,
                String.valueOf(now));
    }

基于 ZSET实现的热搜文章

也是利用ZSET范围有序查询的特性实现,现在初始化一波数据如下图,先用 Redis 命令演示一波。后续用 Java 代码实现。

在这里插入图片描述
现在需要查最新的 2 条热点数据,执行如下指令。由于 ZSET是有序集合且查询的结果默认是倒序输出,因此最新的俩条数据就被查到了。结果如下

zrevrangeByScore article +inf -inf LIMIT 0 2

在这里插入图片描述
查第二页的数据怎么查?记录每一次查询的最大值,当做下一次查询的游标即可查到第二页数据。

zrevrangeByScore article 20231207 -inf LIMIT 0 2

在这里插入图片描述

对应配套 java 代码

因为 Jedis 的 Api,和原生 Redis 命令命名上很接近,为了方便理解这里用 Jedis 实现。

   @Autowired
    private Jedis jedis;
    private String RANKING_NAME = "ranking";
    private String LIVE_ROME = "liveRoom";
    private String ROOM_NAME = "李佳琦的直播间";

    @ApiOperation("热搜文章分页查询:zrevrangeWithScores 分页查询 0,-1 查全部")
    @PostMapping("rankingList")
    public Result rankingList() {
        return Result.success(jedis.zrevrangeWithScores(RANKING_NAME, 0, -1));
    }

    @ApiOperation("成员当前排名")
    @PostMapping("pos/{member}")
    public Result pos(@PathVariable("member") String member) {
        return Result.success((jedis.zrevrank(RANKING_NAME, member) + 1));
    }

    @ApiOperation("刷礼物(没有当前成员则新增、有则修改分数)")
    @PostMapping("weighting/{member}/{source}")
    public Result pos(@PathVariable("member") String member,
                      @PathVariable("source") String source) {
        jedis.zincrby(RANKING_NAME, Double.parseDouble(source), member);
        return Result.success("ok");
    }

小结 ZSET

由于大家做的业务都不一样,本文只提供实现热点文章排行榜的基本思路。 举2个常见的排行榜开发业务如下

一种是纯 Redis 实现的在线排行榜: 同学 A 做的是直播聊天室业务,里面需要彰显榜一大哥实力,因此需要搞个在线的排行榜,并且还要实现刷礼物、在线人数新增记录、在线人数统计、排名这些需求,为了提升性能,完全就可以用Redis 做数据库。所有操作基于 Redis 完成,至于结果数据的持久化的话,只需在直播间关闭的时候,将数据落库到 Mysql 或者 Oracle 即可。之前写过一个聊天系统,在线人数统计就是每新开一个 Scoket 的时候,人数加 1,我就是这么干的。具体业务不多 bb。

还有一种是通过定时刷新实现的非实时排行榜 同学 b 的公司,不是查实时排行榜,而是通过定时刷数据库同步数据到 redis 中实现的。

小咸鱼的技术窝

关注不迷路,分享更多技术干货B站、CSDN、微信公众号同名(小咸鱼的技术窝),更多详情在主页
在这里插入图片描述

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

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

相关文章

用python删除指定目录下带某个字符串的图片

前言&#xff1a; 在文件处理中&#xff0c;有时我们需要批量删除指定文件夹中的特定类型文件。如果文件数量非常庞大&#xff0c;手动删除会非常麻烦&#xff0c;所有可以用 Python 编写一个简单而高效的脚本&#xff0c;自动执行重复性的任务&#xff0c;从而节省时间和精力&…

@Scheduled,Quartz,XXL-JOB三种定时任务总结

Scheduled&#xff0c;Quartz&#xff0c;XXL-JOB三种定时任务总结 一、Scheduled 简介 Scheduled 是 Spring 框架中用于声明定时任务的注解。通过使用 Scheduled 注解&#xff0c;你可以指定一个方法应该在何时执行&#xff0c;无需依赖外部的调度器。 这个注解通常与Enab…

避免20种常见Selenium自动化测试异常,让你的测试更加稳定和可靠!

常见的Selenium异常 以下是所有Selenium WebDriver代码中可能发生的一些常见Selenium异常。 1、ElementClickInterceptedException 由于以某种方式隐藏了接收到click命令的元素&#xff0c;因此无法正确执行Element Click命令。 2、ElementNotInteractableException 即使目…

分清社保、医保、新农合

社保中的大头是养老保险&#xff0c;从上图可知成都每个月最低849.2元&#xff0c;对于底层人民来说价格不菲&#xff0c;但对应的医保才107元&#xff0c;那么能不能只交医保呢&#xff1f; 分三种情况&#xff1a; 1、如果我们购买的是城镇职工医疗保险&#xff0c;公司买的也…

vivado实现分析与收敛技巧9-分析使用率统计数据

实现问题的常见原因之一是未考量显式和隐式物理约束。例如 &#xff0c; 管脚分配 (pinout) 在逻辑布局上变为显式物理约束。 slice&#xff08; 分片 &#xff09; 逻辑在大部分器件中都是一致的。但如下专用资源表示的是隐式物理约束 &#xff0c; 因为这些资源仅在某些位置…

GCN,GraphSAGE 到底在训练什么呢?

根据DGL 来做的&#xff0c;按照DGL 实现来讲述 1. GCN Cora 训练代码&#xff1a; import osos.environ["DGLBACKEND"] "pytorch" import dgl import dgl.data import torch import torch.nn as nn import torch.nn.functional as F from dgl.nn.pytorc…

UVM验证环境 加入env

&#xff08;1&#xff09; 如何在UVM验证环境中例化reference model、scoreboard 如何在在验证平台中加入reference model、scoreboard&#xff0c;这个问题的解决方案是引入一个容器类&#xff0c;在这个容器类中实例化driver、monitor、reference model和scoreboard等。在…

Python 自动化办公:文件快速整理分类

平时桌面或文件夹内鱼龙混杂&#xff0c;各种类型的文件都有怎么办&#xff1f; 本篇文章中&#xff0c;我们将学习如何使用 Python 编写一个文件整理分类的脚本。 该脚本能够自动获取文件类型&#xff0c;并将文件按照类型整理到不同的子文件夹中。 先看下效果&#xff0c;…

新的 BLUFFS 攻击导致蓝牙连接不再私密

蓝牙是一种连接我们设备的低功耗无线技术&#xff0c;有一个新的漏洞需要解决。 中间的攻击者可以使用新的 BLUFFS 攻击轻松窥探您的通信。 法国研究中心 EURECOM 的研究员 Daniele Antonioli 演示了六种新颖的攻击&#xff0c;这些攻击被定义为 BLUFFS&#xff08;蓝牙转发和…

渗透测试学习day4

文章目录 靶机&#xff1a;SequelTask1Task2Task3Task4Task5Task6Task7Task8 靶机&#xff1a;CrocodileTask1Task2Task3Task4Task5Task6Task7Task8Task9Task10 靶机&#xff1a;ResponderTask1Task2Task3Task4Task5Task6Task7Task8Task9Task10Task11 靶机&#xff1a;ThreeTas…

使用百度开发者平台处理语音朗读

--TIME --百度开发者中心-汇聚、开放、助力、共赢 --注册账号 -- 准备工作 准备工作 更新时间&#xff1a;2023-01-13 成为开发者 三步完成账号的基本注册与认证&#xff1a; STEP1&#xff1a;点击进入控制台&#xff0c;选择需要使用的AI服务项。若为未登录状态&#xf…

CleanMyMac X2024破解注册激活码

CleanMyMac X for Mac中文2024版只需两个简单步骤就可以把系统里那些乱七八糟的无用文件统统清理掉&#xff0c;节省宝贵的磁盘空间。 cleanmymac x个人认为X代表界面上的最大升级&#xff0c;功能方面有更多增加&#xff0c;与最新macOS系统更加兼容&#xff0c;流畅地与系统性…

MacBook Pro 安装Redis【超详细图解】

目录 一、使用brew安装Redis 二、查看安装及配置文件位置 三、启动Redis 3.1 查看redis服务进程 3.2 redis-cli连接redis服务 四、关闭Redis 因项目需要&#xff0c;顺便记录安装过程 一、使用brew安装Redis brew install redis 如图所示即为安装成功&#xff01; 二…

csdn语法说明/csdn新手指导/csdn入门指导/csdn博文助手

文章目录 1、文章目录2、标题3、文本样式3.1、强调、加粗、黄色标记、删除、引用、乘方&#xff0c;化学表达式3.2、标红、按钮效果 4、功能快捷键5、注脚、注释6、链接7、图片8、列表9、表格 本篇博文主要写一下csdn博文中的语法说明。 1、文章目录 [TOC](这里写自定义目录标…

谈谈压测方案的那点事

&#x1f4e2;专注于分享软件测试干货内容&#xff0c;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;交流讨论&#xff1a;欢迎加入我们一起学习&#xff01;&#x1f4e2;资源分享&#xff1a;耗时200小时精选的「软件测试」资…

论文解读:EfficientViT-提高吞吐量

摘要 要解决的问题 Vision transformers have shown great success due to their high model capabilities. However, their remarkable performance is accompanied by heavy computation costs, which makes them unsuitable for real-time applications. vit计算开销大&a…

人工智能学习7(决策树算法)

编译工具&#xff1a;PyCharm 文章目录 编译工具&#xff1a;PyCharm 决策树算法信息熵信息熵例题计算&#xff1a; 信息增益&#xff08;决策树划分依据之一ID3&#xff09;信息增益例题计算&#xff1a; 信息增益率(决策树划分依据之一C4.5)基尼值和基尼指数(决策树划分依据之…

蓝桥杯物联网竞赛_STM32L071KBU6_全部工程及源码

包含stm32L071kbu6全部实验工程、源码、原理图、官方提供参考代码及原理图 链接&#xff1a;https://pan.baidu.com/s/1xm8mLotLBvOULQlg76ca7g?pwdp0mx 提取码&#xff1a;p0mx

边缘计算网关构建智慧楼宇新生态,打造未来建筑管理

边缘计算网关在无人值守环境中的应用十分广泛&#xff0c;尤其在智慧楼宇管理方面发挥着重要作用。它能够实现多个地点多楼宇之间的数据实时互通&#xff0c;通过边缘计算网关物联网应用构建智慧楼宇生态系统&#xff0c;解决传统楼宇管理网络布线、人员巡检以及后期运维等问题…

SQL Server 数据库,创建数据表(使用T-SQL语句)

2.3表的基本概念 表是包含数据库中所有数据的数据库对象。数据在表中的组织方式与在电子表格中相似&#xff0c;都是 按行和列的格式组织的&#xff0c;每行代表一条唯一的记录&#xff0c;每列代表记录中的一个字段.例如&#xff0c;在包含公 司员工信息的表中&#xff0c;每行…