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

相关推荐
喜欢喝果茶.几秒前
QOverload<参数列表>::of(&函数名)信号槽
开发语言·qt
亓才孓1 分钟前
[Class类的应用]反射的理解
开发语言·python
努力学编程呀(๑•ี_เ•ี๑)1 分钟前
【在 IntelliJ IDEA 中切换项目 JDK 版本】
java·开发语言·intellij-idea
佛祖让我来巡山14 分钟前
Redis 为什么这么快?——「极速快递站」的故事
redis·redis为什么快?
island131423 分钟前
CANN GE(图引擎)深度解析:计算图优化管线、内存静态规划与异构任务的 Stream 调度机制
开发语言·人工智能·深度学习·神经网络
坚持就完事了27 分钟前
Java中的集合
java·开发语言
魔芋红茶31 分钟前
Python 项目版本控制
开发语言·python
云小逸1 小时前
【nmap源码解析】Nmap OS识别核心模块深度解析:osscan2.cc源码剖析(1)
开发语言·网络·学习·nmap
冰暮流星1 小时前
javascript之二重循环练习
开发语言·javascript·数据库
风指引着方向1 小时前
自定义算子开发入门:基于 CANN op-plugin 的扩展实践
开发语言