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

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

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

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

因为他的命令都会进行排序让我很懊恼,所以采用lua+limit+randomseed去解决

上代码

lua 复制代码
-- 获取 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个成员

sh 复制代码
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"

根据最高分数随机取值

sh 复制代码
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分的成员,并且不是按照成员大小排序获取

相关推荐
程序员小羊!11 分钟前
Java教程:JavaWeb ---MySQL高级
java·开发语言·mysql
m0_7231402318 分钟前
Python训练营-Day49
开发语言·python
一洽客服系统1 小时前
网页嵌入与接入功能说明
开发语言·前端·javascript
zhangfeng11331 小时前
python 数据分析 单细胞测序数据分析 相关的图表,常见于肿瘤免疫微环境、细胞亚群功能研究 ,各图表类型及逻辑关系如下
开发语言·python·数据分析·医学
Sylvia-girl1 小时前
Java---IDEA
java·开发语言·intellij-idea
Z_W_H_1 小时前
【Springboot】Bean解释
java·开发语言
好奇的菜鸟2 小时前
在 Postman 中高效生成随机环境变量的完整指南
测试工具·lua·postman
L_autinue_Star3 小时前
手写vector容器:C++模板实战指南(从0到1掌握泛型编程)
java·c语言·开发语言·c++·学习·stl
晨岳3 小时前
CentOS 安装 JDK+ NGINX+ Tomcat + Redis + MySQL搭建项目环境
java·redis·mysql·nginx·centos·tomcat
执笔诉情殇〆3 小时前
前后端分离(java) 和 Nginx在服务器上的完整部署方案(redis、minio)
java·服务器·redis·nginx·minio