场景:公司某个场景要求保留前20个最新的数据,用作查询展示,用MySQL每次频繁查询太耗费性能,所以用Redis处理一下。

直接上代码:

local key = KEYS[1] -- 定义从参数中获取的key
local value = ARGV[1] -- 定义从参数中获取的value
local maxLen= tonumber(ARGV[2]) -- 定义从参数中获取的最大长度
local result = redis.call("ZCARD", key) -- 使用ZCARD获取key对应的集合最大长度
local lastScore = result + 1 -- 累加本次保存数据的分数排序
if(result >= maxLen)  -- 如果result已经超出最大长度,则进去裁剪程序
thenlocal zrangeData = redis.call("ZRANGE", key , -1 , -1 , "WITHSCORES")[2] -- 获取集合中最后一个数据的分数,也就是最大分时lastScore = zrangeData + 1 -- 本次保存数据的分数是最大分 + 1redis.call("ZREMRANGEBYRANK", key , 0 , result - maxLen) -- 裁剪掉集合前面超出maxLen的数据,也就是旧数据
end
redis.call("ZADD", key , lastScore , value)  -- 将本次数据保存到集合中

下面根据我的业务场景,我其实是把 score 分数根据传入的时间戳作为值得,而不是上面的数字累加,因为时间戳放进来天然就能根据大小进行排序,不需要咱们自己计算一次了,上代码,自己选择合适的场景使用:

local key = KEYS[1] -- 定义从参数中获取的key
local value = ARGV[1] -- 定义从参数中获取的value
local maxLen = tonumber(ARGV[2]) -- 定义从参数中获取的最大长度
local score = tonumber(ARGV[3]) -- 使用ZCARD获取key对应的集合最大长度
redis.call("ZADD", key , score , value) -- 这里不太一样,直接把本次的数据放入进来了
local result = redis.call("ZCARD", key) -- 然后直接获取集合的长度
if(result > maxLen)  -- 超过直接裁剪,因为时间戳放进去后,直接就排好序了,放心裁剪
thenredis.call("ZREMRANGEBYRANK", key , 0 , result - maxLen) -- 裁剪掉集合前面超出maxLen的数据,也就是旧数据
end

使用Java代码调用脚本,lettuce版本(其他语言或者客户端自行搜索一下如何调用lua脚本):

public class Application {public static void main(String[] args) {RedisURI redisUri = RedisURI.builder()                    // <1> 创建单机连接的连接信息.withHost("10.0.0.155").withPort(6379).withDatabase(0).withTimeout(Duration.of(10, ChronoUnit.SECONDS)).build();RedisClient redisClient = RedisClient.create(redisUri);   // <2> 创建客户端StatefulRedisConnection<String, String> connection = redisClient.connect();     // <3> 创建线程安全的连接RedisCommands<String, String> redisCommands = connection.sync();                // <4> 创建同步命令// 循环一百次,可以验证是否保留了最大长度for (int i = 1; i <= 100; i++) {// keyString[] keys = new String[]{"imKey"};// value 、 最大长度 、时间戳String[] values = new String[]{"imValue" + i , "20",new Date().getTime() + ""};String result = redisCommands.eval("\n" +"local key = KEYS[1]\n" +"local value = ARGV[1]\n" +"local maxLen = tonumber(ARGV[2])\n" +"local score = tonumber(ARGV[3])\n" +"redis.call(\"ZADD\", key , score , value)\n" +"local result = redis.call(\"ZCARD\", key)\n" +"if(result > maxLen) \n" +"then\n" +"\tredis.call(\"ZREMRANGEBYRANK\", key , 0 , result - maxLen)\n" +"end\n", ScriptOutputType.VALUE, keys, values);System.out.println(result);}connection.close();   // <5> 关闭连接redisClient.shutdown();  // <6> 关闭客户端}}


结果满足我们的需求。

最后注意一下,程序中取出这个集合后,根据情况判断是否要倒序返回,因为这个集合越往后的数据,才是越新的。

欢迎指正,谢谢。

demo已上传至:https://github.com/qiaomengnan16/spring-boot-rest-redis-lua

Redis + Lua 实现 sorted set 集合保证固定数量的数据,并保留新数据剔除旧数据相关推荐

  1. redis lua

    redis 支持复杂数据类型  : key-value, string, list, set, hash table, sorted set, 其他有用特性:            TRANSACTI ...

  2. 电商网站如何进行库存同步处理Redis+Lua

    电商网站库存模块 库存表包含了商品的sku,商品类型,商品款号,颜色,尺码,库存数,版本号,创建时间,修改时间. 商品类型,可根据商品分为,普通商品,赠品,内卖商品,预售商品等 库存表结构 @Data ...

  3. Redis Lua 脚本常用操作总结及实现 CAS 操作

    一.什么是 Lua ?   Lua 是一个小巧的脚本语言.它是巴西里约热内卢天主教大学(Pontifical Catholic University of Rio de Janeiro)里的一个由 R ...

  4. redis+lua实现抢红包

    原创 万山红遍 redis 2018/12/29 20:08 阅读数 1.9K 需求:用户分享红包到微信群中. 每一个用户只能领取一个红包. 比如饿了么的红包分享: 在设计之前,先了解一下redis的 ...

  5. Java并发:分布式应用限流 Redis + Lua 实践

    任何限流都不是漫无目的的,也不是一个开关就可以解决的问题,常用的限流算法有:令牌桶,漏桶.在之前的文章中,也讲到过,但是那是基于单机场景来写. 之前文章:接口限流算法:漏桶算法&令牌桶算法 然 ...

  6. Redis Lua脚本中学教程(下)

    在中学教程的上半部分我们介绍了Redis Lua相关的命令,没有看过或者忘记的同学可以步行前往直接使用机票Redis Lua脚本中学教程(上).今天我们来简单学习一下Lua的语法. 在介绍Lua语法之 ...

  7. 高并发-【抢红包案例】之四:使用Redis+Lua脚本实现抢红包并异步持久化到数据库

    文章目录 导读 概述 实现步骤 注解方式配置 Redis lua脚本和异步持久化功能的开发 Service层添加Redis抢红包的逻辑 Controller层新增路由方法 构造模拟数据,测试 代码 总 ...

  8. Redis Lua脚本中学教程(上)

    失踪人口回来啦! 有读者问我为什么这么久都没有出Redis Lua中学教程,表示村头厕所已经好久没有纸了.其实我早就要写这篇中学教程了,奈何最近太忙了,就一拖再拖,直到今天我终于又开始动笔了.忘记Lu ...

  9. redis+lua实现分布式限流

    前言 之前我们谈到的限流解决方案中提到了在分布式环境下,可以使用redis结合lua进行限流,与网关层限流不同的是,基于Redis+Lua的分布式限流属于服务端限流 使用redis做限流原因 在前面的 ...

最新文章

  1. aspose.words 合并相同值的单元格_合并相同的单元格,你用了1小时,同事只要30秒,还支持自动刷新...
  2. 火狐不支持event.keyCode,用jquery中的event.which轻松解决。
  3. MySQL查询的进阶操作--排序查询
  4. 牛客题霸 SQL2 查找入职员工时间排名倒数第三的员工所有信息
  5. IT第三阶段?“智慧的运算”的未解之谜
  6. android自定义水波纹,android 自定义view-水波纹进度球
  7. rocketmq怎么保证数据不会重复_阿里架构师亲授:Kafka和RocketMQ的消息复制实现的差异点在哪?...
  8. 《spring-boot学习》-04-综合开发
  9. [国嵌攻略][125][总线设备驱动模型]
  10. PLSQL连接Oracle报错 ORA-12154 标识符
  11. shell中 if条件的格式要求
  12. 属性getter和setter
  13. N天学习一个Linux命令之grep
  14. python requests库爬取冒险岛发布站数据
  15. TIBCO Spotfire使用技巧:如何使Spotfire表或散点图中呈现链接中图片
  16. Android手机开发课程设计之记事本
  17. uv纹理坐标设定与贴图规则
  18. 虚拟机主机服务器出现SSH已启用,ESXi去掉 SSH已经启用的警告信息
  19. javascript 获取邮箱的后缀
  20. BIM+GIS技术为工程数字化转型提供了新的契机

热门文章

  1. git pull 提示错误 fatal: refusing to merge unrelated histories
  2. 暮然回首:我的10年软件开发生涯
  3. 趁着中秋节来临之际,学学如何做好团队管理
  4. 货币战争5 读书笔记
  5. 今天的码农女孩做了关于svg画图和canvas画图 2022/1/18
  6. 什么是RRU和BBU
  7. java游戏宠物进化,[娱乐][SCT]imiPet —— 动态动作模型的宠物开源,由社区维护[1.9-1.16]...
  8. 【网络】mesh和无线桥接WDS的区别
  9. 9.Excel vba开发-转换为大写
  10. Python数据分析和挖掘之入门理论+实操