当前位置: 首页 > news >正文

高性能服务开发利器:redis+lua

Redis 与 Lua 脚本的结合,其核心价值在于 ​原子性操作​ 和 ​减少网络开销。

一、Redis 执行 Lua 脚本的优势

  1. 原子性
    • Lua 脚本在 Redis 中原子执行,避免多命令竞态条件。
  2. 减少网络开销
    • 将多个 Redis 命令合并为一个脚本,减少客户端与 Redis 之间的通信次数。
  3. 高性能
    • Redis 会将 Lua 脚本缓存(通过 SHA1 摘要),后续通过 EVALSHA 直接调用,减少传输开销。
  4. 复杂逻辑支持
    • 支持条件判断、循环等复杂逻辑,突破 Redis 单命令的限制。

二、基本用法

1. ​执行 Lua 脚本
  • ​**EVAL 命令**​:直接执行脚本。
    EVAL "return redis.call('SET', KEYS[1], ARGV[1])" 1 mykey hello
    -- KEYS[1] 对应 mykey,ARGV[1] 对应 hello
  • ​**EVALSHA 命令**​:通过 SHA1 摘要执行已缓存的脚本。
    EVALSHA a1b2c3d4... 1 mykey hello
2. ​参数传递
  • KEYS 和 ARGV 是 Redis 与 Lua 之间的参数传递约定:
    • KEYS:用于指定 Redis 键(支持多个键,常用于集群分片)。
    • ARGV:用于传递非键参数(如值、标志位等)。
  • 示例​:
    EVAL "return {KEYS[1], ARGV[1]}" 1 key1 arg1
    -- 返回 { "key1", "arg1" }
3. ​在 Lua 中调用 Redis 命令
  • 使用 redis.call() 或 redis.pcall() 执行 Redis 命令:
    -- 示例:原子递增并设置过期时间
    EVAL "local count = redis.call('INCR', KEYS[1])if count == 1 thenredis.call('EXPIRE', KEYS[1], ARGV[1])endreturn count
    " 1 my_counter 60
    • redis.call() 遇到错误会抛出异常,终止脚本;redis.pcall() 会捕获错误并返回错误表。

三、高级特性

1. ​原子性与隔离性
  • 原子性​:脚本执行期间,其他客户端命令会被阻塞。
  • 隔离性​:Lua 脚本中不能访问外部全局变量,且 Redis 会重置脚本的 Lua 环境。
2. ​脚本缓存与复用
  • 使用 SCRIPT LOAD 预先缓存脚本,获取 SHA1 摘要:
    SCRIPT LOAD "return redis.call('GET', KEYS[1])"
    -- 返回 SHA1 摘要,如 'abc123...'
  • 后续通过 EVALSHA + SHA1 执行,避免重复传输脚本内容。
3. ​错误处理
  • 抛出异常​:使用 error() 函数返回错误信息。
    EVAL "if #KEYS == 0 then error('KEYS missing') end" 0
  • 捕获异常​:在客户端检查返回值类型,例如:
    local ok, result = pcall(redis.call, 'GET', 'nonexistent_key')
    if not ok thenreturn {err = result}
    end
4. ​调试技巧
  • 日志输出​:使用 redis.log(redis.LOG_DEBUG, 'message') 输出调试信息到 Redis 日志。
  • 模拟断点​:在脚本中插入 redis.breakpoint()(需配合调试工具)。

四、性能优化

  1. 避免大循环
    • Lua 脚本执行期间会阻塞 Redis,避免在脚本中执行耗时操作(如遍历大表)。
  2. 复用脚本
    • 尽量复用已缓存的脚本(EVALSHA),减少 EVAL 的传输开销。
  3. 参数最小化
    • 减少 KEYS 和 ARGV 的数量和大小,避免内存压力。

五、常见应用场景

1. ​限流(Rate Limiting)​
-- KEYS[1]: 限流键,ARGV[1]: 时间窗口(秒),ARGV[2]: 最大请求数
local current = redis.call('GET', KEYS[1])
if current and tonumber(current) >= tonumber(ARGV[2]) thenreturn 0
elseredis.call('INCR', KEYS[1])redis.call('EXPIRE', KEYS[1], ARGV[1])return 1
end
2. ​原子操作(如扣减库存)​
-- KEYS[1]: 库存键,ARGV[1]: 扣减数量
local stock = tonumber(redis.call('GET', KEYS[1]))
if stock >= tonumber(ARGV[1]) thenredis.call('DECRBY', KEYS[1], ARGV[1])return 1  -- 成功
elsereturn 0  -- 库存不足
end
3. ​分布式锁
-- KEYS[1]: 锁键,ARGV[1]: 锁值,ARGV[2]: 过期时间(毫秒)
if redis.call('SET', KEYS[1], ARGV[1], 'NX', 'PX', ARGV[2]) thenreturn 1  -- 加锁成功
elsereturn 0  -- 加锁失败
end
4. ​批量操作(如删除匹配模式的键)​
-- 注意:慎用,可能阻塞 Redis!
local keys = redis.call('KEYS', ARGV[1])
for i, key in ipairs(keys) doredis.call('DEL', key)
end
return #keys

六、注意事项

  1. 脚本阻塞风险
    • 避免在脚本中执行 KEYS * 或大循环,防止长时间阻塞 Redis。
  2. 参数大小限制
    • Lua 脚本和参数的总大小默认限制为 1MB(可通过 client-query-buffer-limit 调整)。
  3. 集群模式
    • 在 Redis Cluster 中,脚本操作的键必须位于同一节点(通过 {} 哈希标签强制路由)。

七、调试与监控

  1. 查看脚本缓存
    redis-cli SCRIPT EXISTS sha1_value
  2. 清除脚本缓存
    redis-cli SCRIPT FLUSH
  3. 监控脚本执行
    • 通过 Redis 的 SLOWLOG 监控慢脚本。

相关文章:

高性能服务开发利器:redis+lua

Redis 与 Lua 脚本的结合,其核心价值在于 ​原子性操作​ 和 ​减少网络开销。 一、Redis 执行 Lua 脚本的优势​ ​原子性​ Lua 脚本在 Redis 中原子执行,避免多命令竞态条件。 ​减少网络开销​ 将多个 Redis 命令合并为一个脚本,减少客…...

开源智能体MetaGPT记忆模块解读

MetaGPT 智能体框架 1. 框架概述 MetaGPT 是一个​​多智能体协作框架​​,通过模拟软件公司组织架构与工作流程,将大语言模型(LLM)转化为具备专业分工的智能体,协同完成复杂任务。其最大特点是能够将​​自然语言需…...

Docker部署MySQL大小写不敏感配置与数据迁移实战20250409

Docker部署MySQL大小写不敏感配置与数据迁移实战 🧭 引言 在企业实际应用中,尤其是使用Java、Hibernate等框架开发的系统,MySQL默认的大小写敏感特性容易引发各种兼容性问题。特别是在Linux系统中部署Docker版MySQL时,默认行为可…...

【RabbitMQ】延迟队列

1.概述 延迟队列其实就是队列里的消息是希望在指定时间到了以后或之前取出和处理,简单来说,延时队列就是用来存放需要在指定时间被处理的元素的队列。 延时队列的使用场景: 1.订单在十分钟之内未支付则自动取消 2.新创建的店铺,…...

深兰科技携多款AI医疗创新成果亮相第七届世界大健康博览会

4月8日,以“AI赋能 健康生活”为主题的2025年(第七届)世界大健康博览会(以下简称健博会)在武汉隆重开幕。应参展企业武汉市三甲医院——武汉中心医院的邀请,深兰科技最新研发的新一代智慧医疗解决方案和产品在其展位上公开亮相。 本届展会吸引了来自18个…...

20周年系列|美创科技再度入围「年度高成长企业」系列榜单

近日,资深产业信息服务平台【第一新声】发布「2024年度科技行业最佳CEO及高成长企业榜」,美创科技凭借在数据安全领域的持续创新和广泛行业实践, 再度入围“年度网络安全高成长企业”、“年度高科技高成长未来独角兽企业TOP30”。 美创科技作…...

saltstack分布式部署

一、saltstack分布式 在minion数量过多时,通过部署salt代理,减轻master负载 1、在master上删除说有minion证书 2、在minion上删除旧master信息 3、安装部署salt-syndic 4、修改minion 5、在master上签署代理的证书 6、在代理上签署minion证书 7、测试...

CCRC 与 EMVCo 双认证:中国智能卡企业的全球化突围

在全球经济一体化的浪潮中,智能卡行业正经历着前所未有的变革与发展。中国智能卡企业凭借技术优势与成本竞争力,在国内市场成绩斐然。然而,要想在国际市场站稳脚跟,获取权威认证成为关键一步。CCRC 与 EMVCo 双认证,宛…...

逆向工程的多层次解析:从实现到领域的全面视角

目录 前言1. 什么是逆向工程?2. 实现级逆向:揭示代码背后的结构2.1 抽象语法树的构建2.2 符号表的恢复2.3 过程设计表示的推导 3. 结构级逆向:重建模块之间的协作关系3.1 调用图与依赖分析3.2 程序与数据结构的映射 4. 功能级逆向&#xff1a…...

【Docker项目实战】使用Docker部署ToDoList任务管理工具

【Docker项目实战】使用Docker部署ToDoList任务管理工具 一、ToDoList介绍1.1 ToDoList简介1.2 ToDoList主要特点二、本次实践规划2.1 本地环境规划2.2 本次实践介绍三、本地环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker compose 版本四、下载ToDoList镜像…...

基于SpinrgBoot+Vue的医院管理系统-026

一、项目技术栈 Java开发工具:JDK1.8 后端框架:SpringBoot 前端:Vue开发 数据库:MySQL5.7和Navicat管理工具结合 服务器:Tomcat8.5 开发软件:IDEA / Eclipse 是否Maven项目:是 二、功能介绍 (1)…...

如何进行数据安全风险评估总结

一、基于场景进行安全风险评估 一、概述 数据安全风险评估总结(一)描述了数据安全风险评估的相关理论,数据安全应该关注业务流程,以基础安全为基础,以数据生命周期及数据应用场景两个维度为入口进行数据安全风险评估。最后以《信息安全技术 信息安全风险评估规范》为参考,…...

用 npm list -g --depth=0 探索全局包的秘密 ✨

用 npm list -g --depth0 探索全局包的秘密 🚀✨ 嗨,各位开发者朋友们!👋 今天我们要聊一个超实用的小命令——npm list -g --depth0!它就像一个“全局包侦探”🕵️‍♂️,能帮你快速查出系统中…...

依靠视频设备轨迹回放平台EasyCVR构建视频监控,为幼教连锁园区安全护航

一、项目背景 幼教行业连锁化发展态势越发明显。在此趋势下,幼儿园管理者对于深入了解园内日常教学与生活情况的需求愈发紧迫,将这些数据作为提升管理水平、优化教育服务的重要依据。同时,安装监控系统不仅有效缓解家长对孩子在校安全与生活…...

新闻发稿软文发布投稿选择媒体时几大注意

企业在选择新闻稿发布媒体时,需要综合考虑以下几个关键因素: 1. 匹配媒体定位 企业应根据自身品牌定位和传播目标,选择与之契合的媒体平台。确保新闻稿的内容和风格与媒体的定位高度一致,从而提高稿件被采纳的可能性。 2. 衡量…...

[Scade One] Swan与Scade 6的区别 - signal 特性的移除

signal 特性移除 在 Scade One 引入的Swan中,移除了Scade 6中存在的signal 特性。比如 Scade 6 中的signal声明 sig sig_o;或者signal使用,比如 o sig_o; 在Swan中已经被移除。 不过Swan仍旧保留了对布尔流的emit操作,比如 emit a if c …...

亚马逊推出“站外代购革命“:跨境购物进入全平台整合时代

一、创新功能解析:平台边界消融的购物新范式 亚马逊最新推出的External Product Fulfillment(EPF)服务,正以技术创新重构全球电商格局。这项被称作"代购终结者"的功能具备三大核心突破: 全链路智能化 • 智能…...

Java 常用安全框架的 授权模型 对比分析,涵盖 RBAC、ABAC、ACL、基于权限/角色 等模型,结合框架实现方式、适用场景和优缺点进行详细说明

以下是 Java 常用安全框架的 授权模型 对比分析,涵盖 RBAC、ABAC、ACL、基于权限/角色 等模型,结合框架实现方式、适用场景和优缺点进行详细说明: 1. 授权模型类型与定义 模型名称定义特点RBAC(基于角色的访问控制)通…...

达梦数据库迁移问题总结

问题一、DTS工具运行乱码 开启图形化 [rootlocalhost ~]# xhost #如果命令不存在执行sudo yum install xorg-x11-server-utils xhost: unable to open display "" [rootlocalhost ~]# su - dmdba 上一次登录: 三 4月 9 19:50:44 CST 2025 pts/0 上…...

JS | 函数柯里化

函数柯里化(Currying):将一个接收多个参数函数,转换为一系列只接受一个参数的函数的过程。即 逐个接收参数。 例子: 普通函数: function add(a, b, c) {return a b c; } add(1, 2, 3); // 输出 6柯里化…...

Elasticsearch中的基本全文搜索和过滤

Elasticsearch中的基本全文搜索和过滤 知识点参考: https://www.elastic.co/guide/en/elasticsearch/reference/current/full-text-filter-tutorial.html#full-text-filter-tutorial-range-query 1. 索引设计与映射 多字段类型(Multi-Fields) &#xff…...

蓝桥杯嵌入式第十五届

一、底层 根据它的硬件配置可以看出来这套题目使用到了按键、LED、LCD、输入捕获这几个功能 (1)输入捕获功能 首先在CubeMx里面的配置 题目中说到了我们使用的是PA15和PB4(实际在板子上对应的的是R39和R40),所以我们…...

基于ueditor编辑器的功能开发之给编辑器图片增加水印功能

用户需求,双击编辑器中的图片的时候,出现弹框,用户可以选择水印缩放倍数、距离以及水印所放置的方位(当然有很多水印插件,位置大小透明度用户都能够自定义,但是用户需求如此,就自己写了&#xf…...

DDR中的DLL

在DDR4内存系统中,DLL(Delay Locked Loop,延迟锁相环)是一个非常重要的组件,用于确保数据信号(DQS)和时钟信号(CK)之间的同步。以下是DLL的作用以及DLL on和DLL off的影响…...

Python学习之jieba

Python学习之jieba jieba是优秀的中文分词第三方库,由于中文文本之间每个汉字都是连续书写的,我们需要通过特定的手段来获得其中的每个词组,这种手段叫做分词,我们可以通过jieba库来完成这个过程。jieba库的分词原理:利用一个中文词库,确定汉字之间的关联频率,汉字向概率大的组…...

快速幂fast_pow

快速幂算法讲解 快速幂算法是一种高效计算幂运算的算法,其核心思想是利用指数的二进制分解,把幂运算的时间复杂度从 O(p) 降低到 O(logp)。 原理 假设要计算 an,将 n 表示成二进制形式:n2k1​2k2​⋯2km​,那么 ana…...

Go并发背后的双引擎:CSP通信模型与GMP调度|Go语言进阶(4)

为什么需要理解CSP与GMP? 当我们启动一个Go程序时,可能会创建成千上万个goroutine,它们是如何被调度到有限的CPU核心上的?为什么Go能够如此轻松地处理高并发场景?为什么有时候我们的并发程序会出现奇怪的性能瓶颈&…...

42、JavaEE高级主题:WebSocket详解

WebSocket 一、WebSocket协议与实现 WebSocket是一种基于TCP协议的全双工通信协议,能够在客户端和服务器之间建立实时、双向的通信通道。通过WebSocket,客户端和服务器可以在任何时候发送数据,并立即接收到对方的响应。 1.1 WebSocket协议…...

UGUI源代码之Text—实现自定义的字间距属性

以下内容是根据Unity 2020.1.01f版本进行编写的 UGUI源代码之Text—实现自定义的字间距属性 1、目的2、参考3、代码阅读4、准备修改UGUI源代码5、实现自定义Text组件,增加字间距属性6、最终效果 1、目的 很多时候,美术在设计的时候是想要使用文本的字间…...

【AI】MCP概念

一文讲透 MCP(附 Apifox MCP Server 内测邀请) 7分钟讲清楚MCP是什么?统一Function calling规范,工作量锐减至1/6,人人手搓Manus!? | 一键链接千台服务器,几行代码接入海量外部工具…...

HarmonyOS:使用geoLocationManager (位置服务)获取位置信息

一、简介 位置服务提供GNSS定位、网络定位(蜂窝基站、WLAN、蓝牙定位技术)、地理编码、逆地理编码、国家码和地理围栏等基本功能。 使用位置服务时请打开设备“位置”开关。如果“位置”开关关闭并且代码未设置捕获异常,可能导致应用异常。 …...

深入解析原生鸿蒙中的 RN 日志系统:从入门到精通!

全文目录: 开篇语📖 目录🎯 前言:鸿蒙日志系统究竟有多重要?🛠️ 鸿蒙 RN 日志系统的基础结构📜 1. 日志的作用⚙️ 2. 日志分类 🔧 如何在鸿蒙 RN 中使用日志系统🖋️ 1…...

【前端】【Nuxt3】Nuxt3中usefetch,useAsyncData,$fetch使用与区别

一、Nuxt3 中不同数据获取方式的请求行为对比 (一)总结:请求行为一览 useFetch 和 useAsyncData 是 Nuxt 推荐的数据获取 API,自动集成 SSR 与客户端导航流程。$fetch 是更底层的请求方法,不具备自动触发、缓存等集成…...

【Linux系统】Linux基础指令

l i n u x linux linux 命令是对 L i n u x Linux Linux 系统进行管理的命令。对于 L i n u x Linux Linux 系统来说,无论是中央处理器、内存、磁盘驱动器、键盘、鼠标,还是用户等都是文件, L i n u x Linux Linux 系统管理的命令是它正常运…...

Android中Jetpack设计理念、核心组件 和 实际价值

一、Jetpack 的定义与定位(基础必答) Jetpack 是 Google 推出的 Android 开发组件集合,旨在: 加速开发:提供标准化、开箱即用的组件 消除样板代码:解决传统开发中的重复劳动问题 兼容性保障:…...

flutter开发音乐APP(前提准备)

1、项目的一些环境: 2、接口文档: 酷狗音乐 NodeJS 版 API 3、接口数据结构化 Instantly parse JSON in any language | quicktype UI样式借鉴参考: Coffee-Expert/Apple-Music-New-UI: Apple Music Clone on Flutter, with redesigned UI…...

网络协议学习

最近在适配ESP32的网络驱动,借此机会先学习一下网络通信协议。 以太网帧、IP包及TCP与UDP的报文格式 提问腾讯元宝提示词: TCP窗口是干什么的拥塞窗口是什么的...

示波器直流耦合与交流耦合:何时使用哪种?

直流耦合和交流耦合的基本区别应该在于它们如何处理信号的直流分量和交流分量。直流分量是指信号中的固定电压部分,而交流分量则是信号中变化的电压部分。 例如,一个5V的直流电压叠加了一个1V的正弦波交流信号,整个信号会在4V到6V之间波动。如…...

js解除禁止复制、禁止鼠标右键效果

有的网页会禁止复制,甚至禁止鼠标右键,如何解决 按F12进入检查模式,在控制台输入下面的js代码 1.解除禁止复制 document.addEventListener(copy,function(event){event.stopImmediatePropagation();},true); 2.解除禁止鼠标右键 document…...

如何把未量化的 70B 大模型加载到笔记本电脑上运行?

并行运行 70B 大模型 我们已经看到,量化已经成为在低端 GPU(比如 Colab、Kaggle 等)上加载大型语言模型(LLMs)的最常见方法了,但这会降低准确性并增加幻觉现象。 那如果你和你的朋友们把一个大型语言模型分…...

xwiki的权限-页面特殊设置>用户权限>组权限

官方文档https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Access%20Rights/ 他有组权限、用户权限、页面及子页面特别设置。 页面特殊设置 > 用户权限 > 组权限 XWiki提供了设置wiki范围内权限、细粒度页面级权限的能力,以及在需要更多控制的…...

Go语言比较递归和循环执行效率

一、概念 1.递归 递归是指一个函数在其定义中直接或间接调用自身的编程方法 。简单来说,就是函数自己调用自己。递归主要用于将复杂的问题分解为较小的、相同类型的子问题,通过不断缩小问题的规模,直到遇到一个最简单、最基础的情况&#x…...

Windows 图形显示驱动开发-WDDM 2.0功能_供应和回收更改

供应和回收更改 对于 Windows 显示驱动程序模型 (WDDM) v2,有关 套餐 和 回收 的要求正在放宽。 用户模式驱动程序不再需要在内部分配上使用套餐和回收。 空闲/挂起的应用程序将使用 Microsoft DirectX 11.1 中引入的 TrimAPI 删除驱动程序内部资源。 API 级别将继…...

MongoDB 新手笔记

MongoDB 新手笔记 1. MongoDB 1.1 概述 MongoDB 是一种 文档型数据库(NoSQL),数据以类似 JSON 的 BSON 格式存储,适合处理非结构化或半结构化数据。 对比 MySQL: MySQL 是关系型数据库,数据以表格形式存…...

Pytorch查看神经网络结构和参数量

基本方法 print(model) print(type(model))# 模型参数 numEl_list [p.numel() for p in model.parameters()] total_params_mb sum(numEl_list) / 1e6print(fTotal parameters: {total_params_mb:.2f} MB) # sum(numEl_list), numEl_list print(sum(numEl_list)) print(numE…...

Pytorch Dataset问题解决:数据集读取报错DatasetGenerationError或OSError

问题描述 在huggingface上下载很大的数据集,用多个parquet文件的格式下载到本地。使用load_dataset加载的时候,进度条加载到一半会报错DatasetGenerationError: An error occurred while generating the dataset;如果加载为IterableDataset&…...

学习OpenCV C++版

OpenCV C 1 数据载入、显示与保存1.1 概念1.2 Mat 类构造与赋值1.3 Mat 类的赋值1.4 Mat 类支持的运算1.5 图像的读取与显示1.6 视频加载与摄像头调用1.7 数据保存 参考:《OpenCV4快速入门》作者冯 振 郭延宁 吕跃勇 1 数据载入、显示与保存 1.1 概念 Mat 类 : Ma…...

特权FPGA之PS/2键盘解码

0 故事背景 见过这种接口的朋友们,大概都已经成家立业了吧。不过今天我们不讨论这种接口的历史,只讲讲这种接口的设计。(如果还没有成家的朋友也别生气,做自己想做的事情就对了!) 1 时序分析 数据帧格式如图…...

SpringBoot 接口限流Lua脚本接合Redis 服务熔断 自定义注解 接口保护

介绍 Spring Boot 接口限流是防止接口被频繁请求而导致服务器负载过重或服务崩溃的一种策略。通过限流,我们可以控制单位时间内允许的请求次数,确保系统的稳定性。限流可以帮助防止恶意请求、保护系统资源,并优化 API 的可用性,避…...

FPAG_BUFFER学习

在FPGA设计中,缓冲器(Buffer)是信号传输和管理的核心组件,用于处理输入/输出信号、时钟分配以及信号完整性。以下是FPGA中常见缓冲器的详细介绍,分类说明其功能、应用场景和设计注意事项: --- ### **1. 输…...