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

相关推荐
为何创造硅基生物5 小时前
C语言 结构体内存对齐规则(通俗易懂版)
c语言·开发语言
吃好睡好便好5 小时前
在Matlab中绘制横直方图
开发语言·学习·算法·matlab
栗子~~5 小时前
JAVA - 二层缓存设计(本地缓冲+redis缓冲+广播所有本地缓冲失效) demo
java·redis·缓存
星寂樱易李5 小时前
iperf3 + Python-- 网络带宽、网速、网络稳定性
开发语言·网络·python
仰泳之鹅5 小时前
【C语言】自定义数据类型2——联合体与枚举
c语言·开发语言·算法
之歆6 小时前
DAY_12JavaScript DOM 完全指南(二):实战与性能篇
开发语言·前端·javascript·ecmascript
cen__y7 小时前
Linux12(Git01)
linux·运维·服务器·c语言·开发语言·git
AI人工智能+电脑小能手7 小时前
【大白话说Java面试题 第65题】【JVM篇】第25题:谈谈对 OOM 的认识
java·开发语言·jvm
社交怪人7 小时前
【算平均分】信息学奥赛一本通C语言解法(题号2071)
c语言·开发语言
郭涤生8 小时前
不同主机之间网络通信-以太网连接复习
开发语言·rk3588