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

相关推荐
索迪迈科技8 分钟前
STL库——map/set(类函数学习)
开发语言·c++·学习
奔跑吧邓邓子23 分钟前
【Java实战㊱】Spring Boot邂逅Redis:缓存加速的奇妙之旅
java·spring boot·redis·缓存·实战
ForteScarlet30 分钟前
Kotlin 2.2.20 现已发布!下个版本的特性抢先看!
android·开发语言·kotlin·jetbrains
失散1332 分钟前
分布式专题——4 大厂生产级Redis高并发分布式锁实战
java·redis·分布式·缓存·架构
anlogic39 分钟前
Java基础 9.10
java·开发语言·算法
yongche_shi43 分钟前
第二篇:Python“装包”与“拆包”的艺术:可迭代对象、迭代器、生成器
开发语言·python·面试·面试宝典·生成器·拆包·装包
AAA修煤气灶刘哥1 小时前
别懵!从单机锁到 Redisson,分布式锁的坑我全帮你填了
java·redis·spring cloud
jc06201 小时前
4.1-中间件之Redis
数据库·redis·中间件
Elastic 中国社区官方博客1 小时前
介绍 Python Elasticsearch Client 的 ES|QL 查询构建器
大数据·开发语言·数据库·python·elasticsearch·搜索引擎·全文检索
Hóng xīng qiáo1 小时前
swVBA自学笔记014、Lisp适合对SolidWorks进行二次开发吗 ?
开发语言·笔记·lisp