redis lua
需求是在缓存最近一周内用户所有消息列表,考虑用Redis 存储;为每个存储一个独立Sorted Set,value 为消息体,Score 为MessageId,用以实现增量消息同步。
问题就来了:Sorted Set 怎么清理?
-设计内存容量只允许放一周内最新的,太久了缓存意义不大,太浪费。
-再者存在百万级/s群发请求,不允许写入时触发清理。
理想模型:如果使用磁盘则使用MyIsam堆表,数据按照顺序写入,再建立以uid为索引,删除却是完全顺序的。内存里面的话Hash 表 + RB 树两个维度索引,RB树可按照时间顺序清理。
解决方案:
- 写入第一条时,设置一周过期时间
判断是否第一条:zadd key 0 0 value score 返回2 说明第一条,1 不是第一条,只是多一条0的数据
- 用户每天第一次登陆,触发一次清理
清理需要遍历Sorted Set上,消息一般不小,浪费io流量了,所以考虑采用lua 脚本实现。
- 这样保证,通过pipeline只是高并发写入,同时保证活跃用户一周内消息都在内存(不活跃不保证),清理简单
清理脚本如下:
local ltime =
local dels =
local lefts =
local list = redis.call("ZRANGE", KEYS[], , -)
if(list[] == nil) then
return {-, }
end
for _,v in ipairs(list) do
if lefts == then
ltime = struct.unpack('<i', v)
if ltime < tonumber(KEYS[]) then
dels = dels +
else
lefts = lefts +
end
else
lefts = lefts +
end
end
if lefts > tonumber(KEYS[]) then
dels = dels + (lefts - tonumber(KEYS[]))
lefts = tonumber(KEYS[])
end
if lefts == then
ltime =
redis.call("DEL", KEYS[])
elseif dels > then
redis.call("ZREMRANGEBYRANK", KEYS[], , dels)
end
return {dels, ltime}
写入的消息前4byte 为little-endian 的UnixTime,Redis lua 支持struct,很简单解析出(当然也支持cjson,但速度要差一些).
清理过期数据,并返回最后一条写入的时间,应用根据返回时间适当延长过期时间。
这里因为考虑每个人消息一般不会太多,所以全部遍历,多的话可考虑分部分遍历,如10条10条来,最新的就不会被不必要的取出来了,怎么说遍历大Set还是较慢的。
clear_msgs(Uid, MaxLen, ExpireSec) ->
ToExpires = utime() - ExpireSec,
{ok, [Dels, LTime]} =
eredis:q(pooler(Uid), [<<"EVAL">>, clear_script(), <<"3">>,
?KEY_LIST(Uid), MaxLen, ToExpires]),
{ok, binary_to_integer(Dels), binary_to_integer(LTime)}.
性能:此段脚本在我机器上速度2.5w/s(列表长度10), 相比get 7w/s。速度很快,也节省网络流量。
script load
此段脚本有700多字节,每次执行会带来不少网络流量;但对性能影响较小,内部对于eval 会先sha1 脚本,从缓存获取生成好的lua 方法执行。
当然最好使用script load,节省脚本传输、脚本的sha1计算,就行存储过程一样执行。
luajit:
github讨论过 ,redis lua,相比nginx_lua 更像数据库存储过程,提供事务性的多个相关性操作,是否使用jit区别不大;
支持的库也很有限base、table、string、math、debug、cjson、struct、cmsgpack,能够做的事情不多,也尽量别把太多逻辑用lua写。
redis.log 方法:
调试大段的lua脚本,这个方法还是挺管用的。
相关参考:
官方说明:http://oldblog.antirez.com/post/scripting-branch-released.html
源码分析:http://blog.nosqlfan.com/html/4099.html
redis lua的更多相关文章
- 像调试java一样来调试Redis lua
高并发的系统中,redis的使用是非常频繁的,而lua脚本则更是锦上添花.因为lua脚本本身执行的时候是一个事务性的操作,不会掺杂其他外部的命令,所以很多关键的系统节点都会用redis+lua来实现一 ...
- Redis Lua脚本调试
从版本3.2开始,Redis包含一个完整的Lua调试器,可以用来使编写复杂Redis脚本的任务更加简单. 由于Redis 3.2仍处于测试阶段,请unstable从Github 下载Redis 的分支 ...
- 限流(三)Redis + lua分布式限流
一.简介 1)分布式限流 如果是单实例项目,我们使用Guava这样的轻便又高性能的堆缓存来处理限流.但是当项目发展为多实例了以后呢?这时候我们就需要采用分布式限流的方式,分布式限流可以以redis + ...
- 【连载】redis库存操作,分布式锁的四种实现方式[四]--基于Redis lua脚本机制实现分布式锁
一.redis lua介绍 Redis 提供了非常丰富的指令集,但是用户依然不满足,希望可以自定义扩充若干指令来完成一些特定领域的问题.Redis 为这样的用户场景提供了 lua 脚本支持,用户可以向 ...
- Redis进阶应用:Redis+Lua脚本实现复合操作
一.引言 Redis是高性能的key-value数据库,在很大程度克服了memcached这类key/value存储的不足,在部分场景下,是对关系数据库的良好补充.得益于超高性能和丰富的数据结构,Re ...
- spring boot:redis+lua实现顺序自增的唯一id发号器(spring boot 2.3.1)
一,为什么需要生成唯一id(发号器)? 1,在分布式和微服务系统中, 生成唯一id相对困难, 常用的方式: uuid不具备可读性,作为主键存储时性能也不够好, mysql的主键,在分库时使用不够方便, ...
- spring boot:redis+lua实现生产环境中可用的秒杀功能(spring boot 2.2.0)
一,秒杀需要具备的功能: 秒杀通常是电商中用到的吸引流量的促销活动方式 搭建秒杀系统,需要具备以下几点: 1,限制每个用户购买的商品数量,(秒杀价格为吸引流量一般会订的很低,不能让一个用户全部抢购到手 ...
- Redis Lua脚本完全入门
1. 前言 Redis是高性能的KV内存数据库,除了做缓存中间件的基本作用外还有很多用途,比如胖哥以前分享的Redis GEO地理位置信息计算.Redis提供了丰富的命令来供我们使用以实现一些计算.R ...
- Redis+LUA整合使用
.前言 从本章节开始我们就开始讲解一些 Redis 的扩展应用了,之前讲的主从.哨兵和集群都相当重要,也许小公司用不到集群这么复杂的架构,但是也要了解各知识点的原理,只要了解了原理,无论什么时候是有, ...
随机推荐
- jquery点滴
1.toggle 2.next prev after before 3.on 4.当我们使用jquery的attr('checked',true)或者attr('checked','checked') ...
- DataSet与DataTable与DataRow的关系
1. 添加数据: DataRow dr=MyDataSet.Tables["User"].NewRow(); dr["UserName"] = "张三 ...
- MVC项目中,如何访问Views目录下的静态文件!
<!--注意,是system.webServer节点,而非system.web--><system.webServer> <handlers> <add na ...
- angular服务二
angular服务 $http 实现客户端与服务器端异步请求 get方式 test.html <!DOCTYPE html> <html lang="en"> ...
- Python 3.5源码编译安装
系统环境:CentOS 6.8-Minimal 安装Python依赖包: [root@Python src]# yum install zlib-devel bzip2-devel openssl-d ...
- HP 820 G2变色龙安装10.11.6基本完美
初始状态: 一块ssd硬盘,MBR格式分区,安装了WIN7 64位. 不想动win系统,因此就安装在硬盘的扩展分区 电脑配置: cpu: i7-5600u 声卡: ALC280 显卡: HD55 ...
- Reset Identity Column Value in SQL Server (Identity Reset)
前言:今天在群里看到有人在问SQL Server自增值重置问题(sqlserver identiy column value reset ) 闲话少说,直接上代码: 正文: --create tabl ...
- 12月15日smarty模板基本语法
smarty基本语法: 1.注释:<{* this is a comment *}>,注意左右分隔符的写法,要和自己定义的一致. <{* I am a Smarty comment, ...
- Web Map Gis 开发系列索引
Google Map API Version3 :代码添加和删除marker标记 谷歌地图地理解析和反解析geocode.geocoder详解 Google map markers 百度与谷歌地图瓦片 ...
- UML大战需求分析--阅读笔记3
这次阅读的是第四章,流程分析利器之 – 活动图.对需求有两种分析的方式:结构建模与行为建模.活动图是行为建模中经常使用的一种图.由流程图发展而来. 活动图中有一些名词:开始状态.结束状态.活动.判断. ...