当前位置: 首页 > news >正文

zset使用lua实现取最高分数中的随机成员

zset使用lua实现取最高分数中的随机成员

  1. 这种场景适用队列中不想要先入先出、先入后出
  2. 因为zset的命令都是带有排序功能的,所以取值时要不从大到小要不从小到大
  3. 所以我使用lua实现随机取成员
  4. 使用lua是因为可以保持原子性
  5. 在执行过程中Lua脚本是不会被其他命令或请求打断,因此可以保证每个任务的执行都是原子性的
  6. 当然还有一个方法你是可以通过一些随机算法做ID做成员,这样你就不需要使用lua脚本了
  7. 我这是为了旧数据兼容

zset的命令可以去看菜鸟文章

在这里插入图片描述
因为他的命令都会进行排序让我很懊恼,所以采用lua+limit+randomseed去解决

上代码

-- 获取 zsetKey 中分数最高的成员
local zsetKey = KEYS[1]
local maxScoreData = redis.call('ZRANGE', zsetKey, -1, -1, 'WITHSCORES')
if #maxScoreData == 0 then-- return 'Max score not found'return nil
end
local maxScore = maxScoreData[2]-- 获取最高分数的成员数量
local memberCount = redis.call('ZCOUNT', zsetKey, maxScore, maxScore)
if memberCount == 0 then-- return 'No members with maxScore'return nil
end-- 生成一个随机索引
local time = redis.call('time')[1]
math.randomseed(time)
local randomIndex = math.random(0, memberCount - 1)-- 使用 ZRANGEBYSCORE 获取随机成员
local member = redis.call('ZRANGEBYSCORE', zsetKey, maxScore, maxScore, 'LIMIT', randomIndex, 1)[1]-- 删除选中的成员
redis.call('ZREM', zsetKey, member)-- 返回选中的成员
return member

准备测试数据命令

添加15个成员

ZADD tttt 1 "member1" 1 "member2" 1 "member3" 1 "member4" 1 "member5" 2 "member6" 2 "member7" 2 "member8" 2 "member9" 2 "member10" 3 "member11" 3 "member12" 3 "member13" 3 "member14" 3 "member15"

根据最高分数随机取值

EVAL "local zsetKey = KEYS[1]; local maxScoreData = redis.call('ZRANGE', zsetKey, -1, -1, 'WITHSCORES'); if #maxScoreData == 0 then return 'Max score not found' end; local maxScore = maxScoreData[2]; local memberCount = redis.call('ZCOUNT', zsetKey, maxScore, maxScore); if memberCount == 0 then return 'No members with maxScore' end; math.randomseed(redis.call('time')[1]); local randomIndex = math.random(0, memberCount - 1); local member = redis.call('ZRANGEBYSCORE', zsetKey, maxScore, maxScore, 'LIMIT', randomIndex, 1)[1]; redis.call('ZREM', zsetKey, member); return member" 1 tttt

在这里插入图片描述
在这里插入图片描述
通过命令你可以观察到每次都是取的3分的成员,并且不是按照成员大小排序获取

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 干货含源码!如何用Java后端操作Docker(命令行篇)
  • Redis在服务器启动的日志问题
  • 选择排序的动画展示与实现
  • Ubuntu20上的Qt程序连接Windows上的mssql服务器
  • Oracle(ORA-00214)-undo表空间文件损坏
  • 【Python机器学习】卷积神经网络(CNN)——语义理解
  • 深入解析C#中的锁机制:`lock(this)`、`lock(privateObj)`与`lock(staticObj)`的区别
  • 【C++】汇编分析,函数是如何调用,传参,返回
  • 四种NAT类型
  • OpenCVSharp中的图像数据结构与类型
  • 【PyQt6 应用程序】视频百叶窗效果一键生成模块
  • Android Studio gradle下载太慢了!怎么办?(已解决)
  • RO通讯数据包
  • Linux实现异步IO的方法:epoll,posix aio,libaio,io_uring
  • Datawhale x李宏毅苹果书AI夏令营深度学习详解进阶Task03
  • [nginx文档翻译系列] 控制nginx
  • 0x05 Python数据分析,Anaconda八斩刀
  • Apache Spark Streaming 使用实例
  • Effective Java 笔记(一)
  • Flex布局到底解决了什么问题
  • js ES6 求数组的交集,并集,还有差集
  • Linux各目录及每个目录的详细介绍
  • MobX
  • Unix命令
  • 编写高质量JavaScript代码之并发
  • 和 || 运算
  • 前端设计模式
  • 入口文件开始,分析Vue源码实现
  • 时间复杂度与空间复杂度分析
  • 通过几道题目学习二叉搜索树
  • 新手搭建网站的主要流程
  • 一些基于React、Vue、Node.js、MongoDB技术栈的实践项目
  • 由插件封装引出的一丢丢思考
  • 正则与JS中的正则
  • !! 2.对十份论文和报告中的关于OpenCV和Android NDK开发的总结
  • !!【OpenCV学习】计算两幅图像的重叠区域
  • #define
  • (4)事件处理——(7)简单事件(Simple events)
  • (C语言)求出1,2,5三个数不同个数组合为100的组合个数
  • (八)光盘的挂载与解挂、挂载CentOS镜像、rpm安装软件详细学习笔记
  • (附程序)AD采集中的10种经典软件滤波程序优缺点分析
  • (离散数学)逻辑连接词
  • (十六)一篇文章学会Java的常用API
  • (转)详解PHP处理密码的几种方式
  • .net core开源商城系统源码,支持可视化布局小程序
  • .NET MAUI Sqlite程序应用-数据库配置(一)
  • .NET 读取 JSON格式的数据
  • .NET 中 GetHashCode 的哈希值有多大概率会相同(哈希碰撞)
  • .NET/C# 使窗口永不激活(No Activate 永不获得焦点)
  • .netcore 如何获取系统中所有session_ASP.NET Core如何解决分布式Session一致性问题
  • .NetCore实践篇:分布式监控Zipkin持久化之殇
  • /etc/shadow字段详解
  • @ModelAttribute 注解
  • [000-01-011].第2节:持久层方案的对比
  • [8-27]正则表达式、扩展表达式以及相关实战