首页 > 数据库 >Redis使用Lua脚本

Redis使用Lua脚本

时间:2024-02-17 10:11:25浏览次数:24  
标签:脚本 end KEYS Redis redis ARGV Lua call local

Redis使用Lua脚本

Redis使用lua脚本的优点

  1. 减少网络开销:将原来多次请求的逻辑封装为脚本在服务器上执行,只需1次请求就能完成,减少了网络往返时延;
  2. 原子操作:Redis会将整个脚本作为一个整体执行,中间不会被其他命令插入;
  3. 复用性:客户端发送的脚本会永久保存在Redis中,其他客户端可以复用此脚本。

脚本相关命令

序号 命令及描述
1 EVAL script numkeys key [key ...] arg [arg ...] 执行 Lua 脚本。
2 EVALSHA sha1 numkeys key [key ...] arg [arg ...] 执行 Lua 脚本。
3 SCRIPT EXISTS script [script ...] 查看指定的脚本是否已经被保存在缓存当中。
4 SCRIPT FLUSH 从脚本缓存中移除所有脚本。
5 SCRIPT KILL 杀死当前正在运行的 Lua 脚本。
6 SCRIPT LOAD script 将脚本 script 添加到脚本缓存中,但并不立即执行这个脚本。

示例

Hash对象中field对应value值累加

  1. 编写Lua脚本(keyOpt.lua):

    # keyOpt.lua  39bf38f32e2ca17550d789091a8d5d2635f5d3c0
    
    if redis.call('EXISTS', KEYS[1]) == 1 then
    local res =redis.call(ARGV[4],KEYS[1],ARGV[1],ARGV[2])
    return res
    else
    local res =redis.call(ARGV[4], KEYS[1],ARGV[1],ARGV[2])
    redis.call('EXPIRE', KEYS[1],ARGV[3])
    return res
    end
    
  2. 将Lua脚本加载到redis服务器

    redis-cli script load "$(cat keyOpt.lua)"
    

    ​ ![img](file:///D:/Users/Documents/SuningImFiles/sn23070650/picRec/202401/20240129170421099.png)

    执行成功后会返回sha码,客户端使用EVALSHA sha1 numkeys key [key ...] arg [arg ...] 命令即可执行此脚本。

使用hset存储每人的id,len+1=新id

# getSeq.lua 6ba13ea07df8502ac7e64097243d9c7ada0da3af

local seq= redis.call('HGET',KEYS[1],ARGV[1])
if(seq) then
return seq
else
if redis.call('EXISTS', KEYS[1]) == 1 then
local len= redis.call('HLEN',KEYS[1])+1
redis.call('HSET',KEYS[1],ARGV[1],len)
return len
else
redis.call('HSET',KEYS[1],ARGV[1],1)
redis.call('EXPIRE', KEYS[1],ARGV[2])
return 1
end
end

cd nm 一次存10个

# hmset.lua  56695193392ef6e730563f93008e0390f6c37416

local isext=redis.call('EXISTS', KEYS[1])
local i=1
while(i <= (ARGV[2]-0)) do
if ARGV[2]-i+1>=10 then
redis.call('HMSET',KEYS[1],ARGV[i*2+1],ARGV[i*2+2],ARGV[i*2+3],ARGV[i*2+4],ARGV[i*2+5],ARGV[i*2+6],ARGV[i*2+7],ARGV[i*2+8],ARGV[i*2+9],ARGV[i*2+10],ARGV[i*2+11],ARGV[i*2+12],ARGV[i*2+13],ARGV[i*2+14],ARGV[i*2+15],ARGV[i*2+16],ARGV[i*2+17],ARGV[i*2+18],ARGV[i*2+19],ARGV[i*2+20])
i=i+10
else
redis.call('HSET',KEYS[1],ARGV[i*2+1],ARGV[i*2+2])
i=i+1
end
end
if isext~=1 then
redis.call('EXPIRE', KEYS[1],ARGV[1])
end
return 'OK'

保存uid 一次存10个

# sadd.lua  ccf4438961c6a4f8568cf91e02c989d714d5a54f
a892a3d41922c56bd3201de672fdca7df2c1cf08

local isext=redis.call('EXISTS', KEYS[1])
local res=0
local i=1
while(i<=(ARGV[2]+0)) do
if ARGV[2]-i+1>=10 then
res =res+ redis.call('SADD', KEYS[1],ARGV[i+2],ARGV[i+3],ARGV[i+4],ARGV[i+5],ARGV[i+6],ARGV[i+7],ARGV[i+8],ARGV[i+9],ARGV[i+10],ARGV[i+11])
i=i+10
else
res =res+ redis.call('SADD', KEYS[1],ARGV[i+2])
i=i+1
end
end
if isext ~= 1 then
redis.call('EXPIRE', KEYS[1],ARGV[1])
end
return res

HLL 去重计算

# setHll.lua  122144b94eba6eaedbb203fefa67096c9969702d

local res = 0
local isext1 = redis.call('EXISTS', KEYS[1])
local isext2 = redis.call('EXISTS', KEYS[2])
local i = 1
while(i <= (ARGV[5] + 0)) do
    if ARGV[5]-i+1 >= 10 then
        redis.call('PFADD', KEYS[1],ARGV[i+5],ARGV[i+6],ARGV[i+7],ARGV[i+8],ARGV[i+9],ARGV[i+10],ARGV[i+11],ARGV[i+12],ARGV[i+13],ARGV[i+14])
        i = i+10
    else
        redis.call('PFADD', KEYS[1],ARGV[i+5])
        i = i+1
    end
end
local uvCount = redis.call('PFCOUNT',KEYS[1])
if ARGV[1] ~= 'ZADD' then
    res = redis.call(ARGV[1],KEYS[2],ARGV[4],uvCount)
else
    res = redis.call(ARGV[1],KEYS[2],uvCount,ARGV[4])
end
if isext1 ~= 1 then
    redis.call('EXPIRE', KEYS[1],ARGV[2])
end
if isext2 ~= 1 then
    redis.call('EXPIRE', KEYS[2],ARGV[3])
end
return res

访问频率控制

local times = redis.call('incr',KEYS[1])

if times == 1 then
    redis.call('expire',KEYS[1], ARGV[1])
end

if times > tonumber(ARGV[2]) then
    return 0
end
return 1

标签:脚本,end,KEYS,Redis,redis,ARGV,Lua,call,local
From: https://www.cnblogs.com/coke0914/p/18017742

相关文章

  • 【Redis】【高性能】Redis 批量查询技巧
    1  前言Redis,我们做开发的想必都用过,他是一种缓存,主要用于快速响应结果嘛。比如我们要获取商品的详情,有日销量、月销量、库存数量、评价数量,这些数据都在Redis缓存中,那么我们是要拿四趟?还是一趟呢?当然是一趟最好呀。接下来我们来看看为什么我们要一趟这么做,以及怎么做。2  ......
  • MSSQL Server 备份数据库脚本
    备份数据库脚本,实现如下脚本1.定时备份2. 平日以N开头,周一以W开头,每月1号以M开头,每年1月1日以Y开头, (保留最近7天,4周,12月和10年的备份)3.每周一还原备份到test库,并将密码改为123 declare@bakfilevarchar(100),@dbvarchar(100),@prevarchar(......
  • 性能测试-性能压测脚本的生成以及完善和增强
    1.通过JMeter代理服务器录制脚本为什么用JMeter做性能测试时要 设置客户端的代理JMeter在进行性能测试时,设置客户端代理的主要目的是为了监听和记录浏览器在相应端口的操作。通过设置代理,JMeter可以捕获和记录用户的网络请求和响应,从而模拟用户在真实场景中的行为,对系统进行性......
  • Hydro/vijos美化脚本
    安装方法:先按照此处的方法安装Stylus打开https://userstyles.world/style/14641/hydrovijos点击蓝色的install就可以了。Stylus装不了的可以用油猴。油猴发布地址:https://greasyfork.org/zh-CN/scripts/487267-hydro-vijos%E7%BE%8E%E5%8C%96使用效果:有建议欢迎私信联系h......
  • 细扣Redis Cluster原理
    细扣RedisCluster原理RedisCluster是Redis提供的一种分布式数据存储解决方案,它能够将大量数据分布到多个节点上,实现高可用性和水平扩展。以下是RedisCluster的工作原理及其如何保证数据安全、一致性以及避免脏数据问题的详细解释:工作原理数据分片(Slot分配):RedisClu......
  • Redis
    ubuntu安装redis:sudoapt-getupdatesudoapt-getinstallredis-serverredis-server即可启动从打印的信息可以看到端口信息netstat-tulnp也可查看程序的端口号redis-cli连上redissetname"alexli"setage22getnamegetagekeys*查看所有的keysets......
  • dotnet aspnet redis 缓存 分布式缓存
    分布式缓存\appsettings.Development.json{"Logging":{"LogLevel":{"Default":"Information","Microsoft.AspNetCore":"Warning"}}}分布式缓存\appsettings.json{"Logg......
  • Linux Bash Shell 脚本入门(2)——GNU
    ​LinuxBashShell脚本入门(2)——GNU目录LinuxBashShell脚本入门(2)——GNUGNU与LinuxGNUGNU的组成ShellGNOME桌面环境XWindow软件GNOME可点击内容,大部分来自维基百科,可以点击了解详情。GNU与LinuxGNUGNU操作系统起源于GNU计划,由理查德·斯托曼在麻省理工学院人工智能......
  • springboot整合redis报错:链接失败;org.springframework.data.redis.RedisConnectionFai
    错误原因:开启了保护模式解决方案:关闭保护模式和防火墙具体步骤:1、打开你的redis配置文件,做出如下修改2.开启进程守护yes代表开启守护进程模式。在该模式下,redis会在后台运行,并将进程pid号写入至redis.conf选项pidfile设置的文件中,此时redis将一直运行,除非手动kill该进程。3.......
  • Linux Bash Shell 脚本入门(1)——Linux内核功能介绍
    ​LinuxBashShell脚本入门(1)——Linux内核功能介绍目录LinuxBashShell脚本入门(1)——Linux内核功能介绍前言Linux初探Linux系统架构linux内核系统内存管理软件程序管理硬件设备管理文件管理系统前言本文为《Linux命令行与shell脚本编程大全》第四版的读书笔记,突发奇想想......