首页 > 编程语言 >Lua script attempted to access a non local key in a cluster node 问题解决

Lua script attempted to access a non local key in a cluster node 问题解决

时间:2023-08-02 17:46:19浏览次数:45  
标签:node 脚本 non hash human lua redis cluster key

一、问题描述

最近优化公司需要对不同的业务系统的缓存工具提供一个标准化的解决方案。各个业务系统将缓存数据通过map结构进行存储,然后在缓存系统中将这些map获取出来,然后保存在redis数据库中。技术经理想到的最好解决方案是将map集合直接存储在redis的hash表中。但是要求对hash表中的每个元素设置缓存时间。

存在问题:
1)如果要往hash表添加数据,可以通过hmset命令,但是该命令无法设置过期时间;
2)hash中的每个key-value键值对也无法设置过期时间;

二、解决思路

我第一时间想到的是,在程序中遍历map集合获取每一个key-value,然后在把每一个key-value添加到redis中,然后设置过期时间。但是技术经理说,如果map集合数据量很大时候,这样的性能肯定不行。所以只能够想其他方法。

经过讨论之后,暂时想到两种解决方案:

  • 方案一:定义两个hash(hash_a和hash_b),hash_a用于保存缓存数据,hash_b用于保存每个key的过期时间。当执行查询时候,先查询该hash_b中每个key的过期时间,如果该过期时间大于当前时间,代表该key过期,那么就直接返回;如果没有过期,则通过key查询hash_a,得到缓存数据后返回给用户;
  • 方案二:编写一个lua脚本,该脚本从hash表中读取缓存数据,然后在调用setex方法重新将每一个key-value添加到redis中,并指定缓存时间。由于lua脚本在redis中本地运行,因此执行脚本的性能会很高。

  • 方案三:使用Pipeline实现。首先将后台的map数据读取出来,然后使用setex命令将每个map元素添加到pipeline中。添加完成后再一次性将所有命令发送到redis中批量执行。

综合考虑,方案一操作比较繁琐,需要同时多两个hash进行操作。方案三redis集群不支持使用pipeline,所以最终选择方案二来实现。

三、代码实现

假设redis中有以下数据:

# 添加数据
hmset human name zhongliwen age 30

按照方案二,lua脚本要实现的功能是将每一个属性读取出来,这里有name和age。然后执行setex命令将它们重新添加到redis中。

这个脚本比较简单。但是如果是刚学lua的同学,可能在编写时候遇到各种问题,需要有耐心慢慢调试。这里简单说明一下上面的lua代码:
```lua
# 定义变量,用于存储hash对象的所有属性名称。
local result = redis.call('hkeys', KEYS[1])

# 循环遍历result,k代表table的下标,v代表hash对象每个属性名称。
for k, v in ipairs(result) 
do 
  # 获取hash对象指定属性的值
  local val = redis.call('hget', KEYS[1], (v))
   
  # 将属性添加到redis中,并指定ARGV[1],ARGV[1]代表过期时间。
  redis.call('setex', v, ARGV[1], val) 
end

上面就是lua脚本的全部代码。编写完成后,在redis集群的任意节点上编译该脚本。

script load "local result = redis.call('hkeys', KEYS[1]) for k, v in ipairs(result) do local val = redis.call('hget', KEYS[1], (v)) redis.call('setex', v, ARGV[1], val) end"

script load命令用于将脚本代码添加到缓存,执行该命令后会得到一串数字。通过这串数字可以在redis本地或客户端执行脚本的代码。

调用脚本的代码:

evalsha cd1e27f9d2b4844f55a1a94586cc46ee351f36f1 1 human 30

cd1e27f9d2b4844f55a1a94586cc46ee351f36f1 就是要执行的lua脚本hash。数字1代表后面只有1个参数,human就是要传递给lua脚本的参数,前面指定数字1,这里就只能有一个参数。数字30代表额外附加的参数。

但是,当执行上面脚本时候遇到了问题:

ERR Error running script (call to cd1e27f9d2b4844f55a1a94586cc46ee351f36f1): @user_script:1: @user_script: 1: Lua script attempted to access a non local key in a cluster node

这个问题的原因是在redis集群环境下,如果通过lua脚本对redis的key进行操作时候,必须要保证这些key是在同一个slot中。如果是单机环境是不会出现这个问题。

解决办法是在存储数据的时候,需要对key进行处理。redis规定key中{...}部分用于计算slot槽的位置。所以,可以在每个key中添加相同的{...},这样它们就会存储到同一个slot槽中。如果使用使用hash结构,那么要保证key和field都是保存在同一个slot槽中。

因此,执行hmset命令如下:

hmset human{human} name{human} zhongliwen age{human} 30

上面的key和field后面都添加了{human},redis会通过{human}来计算存储到哪个slot中。这样可以保证lua脚本操作的key都是存储在同一个slot里面。

 

标签:node,脚本,non,hash,human,lua,redis,cluster,key
From: https://www.cnblogs.com/fnlingnzb-learner/p/17601342.html

相关文章

  • 推荐一个node版本的管理工具--NVM
    前言当公司项目较多且不同项目使用不同的node版本才能启动时,我们就有必要使用nvm进行Node版本的切换,方便我们快速启动不同的项目。参考博客:https://blog.csdn.net/weixin_53667605/article/details/130603686 nvm常用指令nvmoff//禁用node.......
  • VisionOn 一款集流程图、思维导图、白板于一体的轻量级在线制图工具
    VisionOn一款集流程图、思维导图、白板于一体的轻量级在线图形工具在工作和学习过程中,通过可视化的图形,有助于清晰高效地表达我们的灵感、想法、思想。工欲善其事,必先利其器。目前,思维导图软件已经有Xmind、Mindnode、MindMeister、亿图图示、Gitmind,流程图软件包括Microso......
  • VisionOn:新一代在线制图工具,简单易用又高颜值
    VisionOn一款集流程图、思维导图、白板于一体的轻量级在线图形工具在工作和学习过程中,通过可视化的图形,有助于清晰高效地表达我们的灵感、想法、思想。工欲善其事,必先利其器。目前,思维导图软件已经有Xmind、Mindnode、MindMeister、亿图图示、Gitmind,流程图软件包括Micr......
  • This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its de 错
    这是我们开启了bin-log,我们就必须指定我们的函数是否是1DETERMINISTIC不确定的2NOSQL没有SQl语句,当然也不会修改数据3READSSQLDATA只是读取数据,当然也不会修改数据4MODIFIESSQLDATA要修改数据5 CONTAINS SQL包含了SQL语句其中在function里面,只有DETERMINISTIC,......
  • NodeJS系列(7)- Ant Design Pro 简介
    AntDesignPro是基于AntDesign和umi的封装的一整套企业级中后台前端/设计解决方案,致力于在设计规范和基础组件的基础上,继续向上构建,提炼出典型模板/业务组件/配套设计资源,进一步提升企业级中后台产品设计研发过程中的『用户』和『设计者』的体验。AntDesign是一套企业级......
  • 论文解读()《Cluster Alignment with a Teacher for Unsupervised Domain Adaptation》
    Note:[wechat:Y466551|付费咨询,非诚勿扰]论文信息论文标题:ClusterAlignmentwithaTeacherforUnsupervisedDomainAdaptation论文作者:ZhijieDeng,YucenLuo,JunZhu论文来源:2020ICCV论文地址:download 论文代码:download视屏讲解:click1介绍     2方法2.......
  • [8月摸鱼计划] win7下安装nodejs
    win7下安装nodejs16.4.0参考:https://blog.csdn.net/weixin_43211696/article/details/1183460331、nodejs下载地址:https://nodejs.org/dist/v13.9.0/https://nodejs.org/dist/latest-v16.x/2、通过以上路径,分别下载下面资源包:node-v13.9.0-x64.msinode-v16.14.0-win-x64.zip3、双击......
  • 基于NodeJS电子商城管理系统
    随着Internet的发展,人们的日常生活已经离不开网络。未来人们的生活与工作将变得越来越数字化、网络化和电子化。电子商城,它将是直接市场营销的最新形式。本论文是以构建电子商城管理系统为目标,使用Node.js制作,由前台和后台两大部分组成。着重论述了系统设计分析,系统的实现包括前台:......
  • Cluster机制剖析1——进程复制
    Forkfork()是类UNIX系统父进程复制子进程的系统调用,在Node里通过libuv实现了对不同平台(unix,linux,windows)的封装。引用百度百科的一段话来描述fork的特性:fork之后的子进程是父进程的副本,它将获得父进程数据空间、堆、栈等资源的副本。注意,子进程持有的是上述存储空间的“副本”,......
  • [Docker] Docker Node.js project tips
    BasicnodeimageFROMnode:12-stretchCOPYindex.jsindex.jsCMD["node","index.js"]Builddockerimage:dockerbuild-tmy-node-app.--initdockerrunmy-node-app,afterdockerisrunning,youpressCTRL+C,itdoesn'texit......