Redis lua脚本简要学习
Redis lua脚本简要学习
背景
上周督促客户从Windows平台升级到了Linux平台.
redis一周相安无事.
但是这周一突然又出现了卡断和慢的情况.
只能继续进行分析.
分析思路
现场日志里面出现了大量的错误提示:
BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE.
不管用chatGPT后者是其他工具都可以查询出来:
Redis执行lua脚本时间太长了. 导致其他客户端无法获取结果集.
然后计划通过redis的slowlog 查询验证一下自己的想法
分析过程
我在自己的测试机器上面执行了 slowlog get 获取如下:
10) 1) (integer) 996
2) (integer) 1685314080
3) (integer) 10513
4) 1) "EVALSHA"
2) "7ae4b3e7f4bf3b0c3470baf33dd1b4941599b520"
3) "879"
发现最近十条慢命令全是id为: 7ae4b3e7f4bf3b0c3470baf33dd1b4941599b520 的lua脚本导致的.
督促现场抓紧获取指令:
现场反馈的图片与我这边一致
但是不太一样的是:
现场有四万个键值对耗时 接近 9 秒钟.
比我这边有非常大的差距.
我这边又让研发同事去另外一个大项目查询了下: 2万个参数. 执行时间为:58毫秒左右
389654
1685325926
57581
EVALSHA
7ae4b3e7f4bf3b0c3470baf33dd1b4941599b520
20855
基本上明确是此lua脚本导致的卡顿
问题再现以及缓解
网上查了一点简单资料, 准备做一下实验
在一个redis的客户端上面你执行命令
eval "while 0==0 do end" 0
然后在另外的redis客户端验证
redis-cli
get 1
get 2
会提示: "BUSY Redis is busy running a script."
然后执行: script KILL
再执行
get 1 就可以正常给出结果了.
说明问题基本上可以再现.
缓解方式: 如果不是一个很需要数据一致性的场景, 可以进行一下SCRIPT KILL
后期解决方式, 应该可以分组,每组不超过1万或者是1000 进行处理, 循环进行清理操作.
未解决的问题
翻找了一早上资料, 没有解决如何根据evalsha 的sha1值反向获取具体的lua脚本.
chatgpt给的结果就是垃圾, 一个get 一个list命令 script 根本没有这些参数.
没办法只能求助于开发:
private final static DefaultRedisScript SessionExistRedisScript = new DefaultRedisScript<>(
"local expires = ''\n" +
"for i=1, #KEYS do\n" +
" if(redis.call('EXISTS','caf-session:sessions:'..KEYS[i]) == 0)\n" +
" then\n" +
" expires = expires..';'..KEYS[i]\n" +
" end\n" +
"end\n" +
"return expires", String.class
);
问题思考
前端时间刚整理了因为Redis的scan导致机器卡顿宕机的问题
今天早上在看ergonomics导致full GC无法提供服务的现象.
我突然感觉redis因为单线程的处理逻辑, 如果大家都需要同步的获取redis的结果
那么每次redis执行吗命令都相当于在做一次minor GC
如果是一个slowlog. 那么就相当于所有连接着一个redis的所有应用服务器一起在做STW.的full GC
所以从时间链上分析. 任何single point 都需要非常严格的重视.
所以研发写的那一套lua脚本非常值得研究与修改.
lua脚本的优点
(1) 减少网络开销: 在Redis操作需求需要向Redis发送5次请求,
而使用脚本功能完成同样的操作只需要发送一个请求即可,减少了网络往返时延。
(2) 原子操作: Redis会将整个脚本作为一个整体执行,中间不会被其他命令插入。
换句话说在编写脚本的过程中无需担心会出现竞态条件,也就无需使用事务。事务可以完成的所有功能都可以用脚本来实现。
(3) 复用: 客户端发送的脚本会永久存储在Redis中,
这就意味着其他客户端(可以是其他语言开发的项目)可以复用这一脚本而不需要使用代码完成同样的逻辑。
(4) 速度快:见 与其它语言的性能比较, 还有一个 JIT编译器可以显著地提高多数任务的性能;
对于那些仍然对性能不满意的人, 可以把关键部分使用C实现, 然后与其集成, 这样还可以享受其它方面的好处。
关于lua脚本的继续学习
前端时间想学习 openresty 使用lua脚本.
但是非常可耻的立了flag没有学习深入下去.
所以发现还是遇到问题督促学习更好.
需要拥抱问题, 不能害怕问题, 通过问题来学习和提高自己.
lua脚本的基础知识
lua脚本是解释性的语言, 跟python和shell 都比较类似.
print("hello 济南小老虎!")
就是一个最简单的 hello world的脚本.
数据类型:
nil,布尔,浮点数,字符串,函数,线程,关联数组(table等)
循环判断
while( true )
do
print("测试循环")
os.execute("sleep " .. 2)
end
Redis里面eval等学习
eval 其实一个非常不安全的命令
很多一句话木马基本上都是基于这个吗精灵来做的
在js,php,等语言里面都有存在.
redis 里面 eval 是用于调用lua脚本的命令.
eval以及script脚本可以实现很多lua脚本的调用和使用.
学习和举例如下:
script load "while (true) do end"
会返回一个hash值如下:
127.0.0.1:6379> script load "while (true) do end"
"f926d8b19784f2c8c63b04288b32cb8de66070ba"
我理解此处就像是数据库绑定变量后可以避免hard parse 的方式一样.
下次执行时可以使用
evalsha f926d8b19784f2c8c63b04288b32cb8de66070ba 0
注意需要加最后一个0 用于指代参数个数
此时就可以执行命令了
等效率执行
eval "while (true) do end" 0
# 注意执行此命令会阻塞产品的使用, 必须尽早执行kill处理.
# 因为redis默认的lua脚本超时时间是 5 seconds 所以只会kill 5s 以上的script.
# 举例如下
# 我执行删除操作. 其实一直没有返回, 因为还没到五秒
127.0.0.1:6379> script kill
OK
(2.23s)
# 执行 lua脚本的返回情况如下:
(error) ERR Error running script (call to f_f926d8b19784f2c8c63b04288b32cb8de66070ba): @user_script:1: Script killed by user with SCRIPT KILL...
(5.00s)
Redis lua脚本简要学习的更多相关文章
- Redis Lua脚本完全入门
1. 前言 Redis是高性能的KV内存数据库,除了做缓存中间件的基本作用外还有很多用途,比如胖哥以前分享的Redis GEO地理位置信息计算.Redis提供了丰富的命令来供我们使用以实现一些计算.R ...
- Redis Lua脚本调试
从版本3.2开始,Redis包含一个完整的Lua调试器,可以用来使编写复杂Redis脚本的任务更加简单. 由于Redis 3.2仍处于测试阶段,请unstable从Github 下载Redis 的分支 ...
- Redis Lua 脚本使用
本文转载自Redis Lua 脚本使用 Lua 简介 Lua语言提供了如下几种数据类型:booleans(布尔).numbers(数值).strings(字符串).tables(表格). 下面是一些 ...
- redis lua脚本学习
语法格式(常见) a = 5 -- 全局变量 local b = 5 -- 局部变量 Eval的使用 EVAL script numkeys key [key ...] arg [arg ...] 首 ...
- Redis Lua脚本原理
2.6版本之后支持嵌入Lua脚本,客户端使用Lua脚本,直接在服务器端原子的执行多条命令 Lua脚本执行过程 创建并修改Lua环境 1 创建基础Lua环境 2 载入函数库 3 创建全局表格Lua 4 ...
- 在Spring中使用Redis Lua脚本批量删除缓存
背景 之前分享了一篇利用lua脚本批量删除redis的key的文章.现在项目中我打算使用spring的缓存,而Spring缓存以前我是用ehcache来做实现的.没发现什么问题..这次我换成redis ...
- 【连载】redis库存操作,分布式锁的四种实现方式[四]--基于Redis lua脚本机制实现分布式锁
一.redis lua介绍 Redis 提供了非常丰富的指令集,但是用户依然不满足,希望可以自定义扩充若干指令来完成一些特定领域的问题.Redis 为这样的用户场景提供了 lua 脚本支持,用户可以向 ...
- redis --- lua 脚本实现原子操作
如题, 楼主的想法很简单, lua 脚本本身支持原子性, 所以把命令写进一个脚本就行, 当然后续还会优化才能放到生产上,例如缓存脚本 ,redis 本身会缓存执行过的脚本 ,这样速度更快, 再优化, ...
- Redis进阶应用:Redis+Lua脚本实现复合操作
一.引言 Redis是高性能的key-value数据库,在很大程度克服了memcached这类key/value存储的不足,在部分场景下,是对关系数据库的良好补充.得益于超高性能和丰富的数据结构,Re ...
- redis>lua脚本
String lua="local num=redis.call('incr',KEYS[1])\n"+"if tonumber(num)==1 then\n" ...
随机推荐
- 互联网公司五八同城(58.com)研发效能团队建设之路
这是「二三线中型互联网公司研发效能团队规模.职能划分和优劣势分析」的一个铺垫,一个背景.因为如果不写此篇,大家可能仅得到一些经验总结,恐怕难以获取当时为啥做出那个决定.做决定要有上下文环境,要有场景才 ...
- 教你几个部署多个nginx-ingress的注意事项
本文分享自华为云社区<nginx-ingress工作原理以及多nginx-ingress部署注意事项>,作者: 可以交个朋友. 一.nginx-ingress工作原理 nginx-ingr ...
- 【华为云技术分享】玩转物联网IoTDA服务系列三-自动售货机销售分析场景示例
摘要:物联网解决方案中,作为数据主体的"物"可能数量会非常大,产生的数据已经无法通过传统的数据处理服务进行处理.如何分析与利用这庞大的物联网设备数据对物联网企业来说又是一个新的挑战 ...
- 物联网通信技术最全科普!你一定要了解的NB-IoT
摘要: NB-IoT(窄带蜂窝物联网)产业正在迅速崛起. 我们这一期的文章主要是普及一些NB-IoT通信技术的相关知识点.也希望你能get到属于自己的知识盲点! 一.前言 NB-IoT(窄带蜂窝物联网 ...
- 看完这篇,DWS故障修复不再愁
摘要:本文详细梳理分析了DWS服务面临软硬件故障场景和对应的修复原理,希望借此能够让你对DWS的集群故障修复有个全面深入的了解. 本文分享自华为云社区<GaussDB(DWS)故障修复系统性介绍 ...
- 论文复现丨基于ModelArts实现Text2SQL
摘要:该论文提出了一种基于预训练 BERT 的新神经网络架构,称为 M-SQL.基于列的值提取分为值提取和值列匹配两个模块. 本文分享自华为云社区<基于ModelArts实现Text2SQL&g ...
- 华为云企业级Redis揭秘第17期:集群搭载多DB,多租隔离更降本
摘要:GaussDB(for Redis)支持真正可扩展的多DB,轻松实现降本增效. 本文分享自华为云社区<华为云企业级Redis揭秘第17期:集群搭载多DB,多租隔离更降本>,作者: G ...
- 最后一天,CDMP数据治理认证高分训练营(9-10月)开放报名!
大家好,我是独孤风,一位曾经的港口煤炭工人,目前在某国企任大数据负责人,公众号大数据流动主理人. 首先告诉大家一个好消息,在大家共同的努力下,我们的CDMP国际数据治理认证训练营(7-8月)基本收官, ...
- Unity3D 导出的apk进行混淆加固、保护与优化原理(防止反编译)
Unity3D 导出的apk进行混淆加固.保护与优化原理(防止反编译) 目录 前言: 准备资料: 正文: 1:打包一个带有签名的apk 2:对包进行反编译 3:使用ipaguard来对程序进行加固 ...
- 火山引擎智能外呼联合火山引擎VeDI升级服务,让企业精准营销不再难
企业营销模式正在经历一场巨变.数字化营销早已替代传统的营销方式,成为企业营销的主流方式和发展战略中不可或缺的部分.然而随着数字化营销的普及,市场迈入存量竞争时代,获客成本也逐年攀升.面对营销过程中不断 ...