`
jahu
  • 浏览: 61060 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

redis之lua脚本系列问题

 
阅读更多

1,redis加入了lua虚拟机,可以执行lua脚本。为复杂的redis操作提供了解决方案。性能方面也不错。

2,lua执行是原子性。

3,redis加入 lua是一件伟大的事情。

 

以前使用redis lua脚本。只是解决一些简单的事情。这次需要处理复杂的事情。遇到了很多问题。

1,方法的定义。

        这次lua脚本需要多个操作。通过参数需要执行不同的操作。不想以 if else if 进行处理。需要定义方法。普通的方式定义方法是有问题的。

 

全局变量保护

为了防止不必要的数据泄漏进 Lua 环境, Redis 脚本不允许创建全局变量。如果一个脚本需要在多次执行之间维持某种状态,它应该使用 Redis key 来进行状态保存。

企图在脚本中访问一个全局变量(不论这个变量是否存在)将引起脚本停止, EVAL 命令会返回一个错误:

redis 127.0.0.1:6379> eval 'a=10' 0
(error) ERR Error running script (call to f_933044db579a2f8fd45d8065f04a8d0249383e57): user_script:1: Script attempted to create global variable 'a'

Lua 的 debug 工具,或者其他设施,比如打印(alter)用于实现全局保护的 meta table ,都可以用于实现全局变量保护。

实现全局变量保护并不难,不过有时候还是会不小心而为之。一旦用户在脚本中混入了 Lua 全局状态,那么 AOF 持久化和复制(replication)都会无法保证,所以,请不要使用全局变量。

  

 

  解决方法,redis已经提供,

 

void scriptingEnableGlobalsProtection(lua_State *lua) {
    char *s[32];
    sds code = sdsempty();
    int j = 0;

    /* strict.lua from: http://metalua.luaforge.net/src/lib/strict.lua.html.
     * Modified to be adapted to Redis. */
    s[j++]="local dbg=debug\n";
    s[j++]="local mt = {}\n";
    s[j++]="setmetatable(_G, mt)\n";
    s[j++]="mt.__newindex = function (t, n, v)\n";
    s[j++]="  if dbg.getinfo(2) then\n";
    s[j++]="    local w = dbg.getinfo(2, \"S\").what\n";
    s[j++]="    if w ~= \"main\" and w ~= \"C\" then\n";
    s[j++]="      error(\"Script attempted to create global variable '\"..tostring(n)..\"'\", 2)\n";
    s[j++]="    end\n";
    s[j++]="  end\n";
    s[j++]="  rawset(t, n, v)\n";
    s[j++]="end\n";
    s[j++]="mt.__index = function (t, n)\n";
    s[j++]="  if dbg.getinfo(2) and dbg.getinfo(2, \"S\").what ~= \"C\" then\n";
    s[j++]="    error(\"Script attempted to access unexisting global variable '\"..tostring(n)..\"'\", 2)\n";
    s[j++]="  end\n";
    s[j++]="  return rawget(t, n)\n";
    s[j++]="end\n";
    s[j++]="debug = nil\n";
    s[j++]=NULL;

    for (j = 0; s[j] != NULL; j++) code = sdscatlen(code,s[j],strlen(s[j]));
    luaL_loadbuffer(lua,code,sdslen(code),"@enable_strict_lua");
    lua_pcall(lua,0,0,0);
    sdsfree(code);
}

 定义一个table类型的局部变量。

 

然后通过setmeatable 把局部变量与_G进行版本。

可以局部变量,就可以绑定方法了。

 

 

2,返回

      执行方法的返回,是无效的。需要在脚本末端,执行 return “data” ,返回数据。脚本末端没有return

 

3,命令属性。

     因为需要要执行time 命令,结果报错

Write commands not allowed after non deterministic commands. Call redis.replicate_commands() at the start of your script in order to switch to single commands replication mode

   找了好久,重要找到问题在哪里了。redis的命令是分种类的。

#define CMD_WRITE 1                   /* "w" flag */
#define CMD_READONLY 2                /* "r" flag */
#define CMD_DENYOOM 4                 /* "m" flag */
#define CMD_NOT_USED_1 8              /* no longer used flag */
#define CMD_ADMIN 16                  /* "a" flag */
#define CMD_PUBSUB 32                 /* "p" flag */
#define CMD_NOSCRIPT  64              /* "s" flag */
#define CMD_RANDOM 128                /* "R" flag */
#define CMD_SORT_FOR_SCRIPT 256       /* "S" flag */
#define CMD_LOADING 512               /* "l" flag */
#define CMD_STALE 1024                /* "t" flag */
#define CMD_SKIP_MONITOR 2048         /* "M" flag */
#define CMD_ASKING 4096               /* "k" flag */
#define CMD_FAST 8192                 /* "F" flag */

 

详细分类请看,server.h 或

http://blog.csdn.net/wtyvhreal/article/details/43193591

 

REDIS_CMD_NOSCRIPT 类型的命令,是无法执行的。

REDIS_CMD_RANDOM 类型的命令,执行会后无法执行 REDIS_CMD_WRITE命令,这也是一致报错的原因。最后删除了time命令,client传递时间戳。

 

4,KEYS, ARGV, 都是table类型,是可以迭代的。

分享到:
评论

相关推荐

    redis.lua lua脚本语言

    lua链接redis的工具驱动代码

    SpringBoot+Redis执行lua脚本的方法步骤

    SpringBoot+Redis 执行 Lua 脚本的方法步骤 以下是 SpringBoot+Redis 执行 Lua 脚本的方法步骤的知识点总结: 1. 背景:在开发中,我们需要一次性操作多个 Redis 命令,但是这些操作不具备原子性,而 Redis 的事务...

    基于redis和lua脚本的分布式锁的实现

    “基于Redis和Lua脚本的分布式锁的实现” 基于Redis和Lua脚本的分布式锁的实现是使用Redis和Lua脚本来实现分布式锁的技术。分布式锁是指在分布式系统中,多个节点之间需要协调和同步的机制,以避免同时访问共享资源...

    java+redis+lua实现重复提交操作拦截.zip

    - Redis支持在服务器端执行Lua脚本,这可以减少网络通信次数,提高性能和原子性。 - 在这个项目中,可能会有一个Lua脚本,用于在Redis中执行锁定和解锁操作,确保整个过程的原子性。例如,脚本可能会检查key是否...

    Java学习资料-Spring Boot - 结合 Redis 使用 Lua脚本

    结合Redis使用Lua脚本可以提升应用的性能和可靠性,特别是在处理高并发、复杂业务逻辑以及事务处理时。以下是对这个主题的详细阐述: 首先,让我们深入了解一下使用Lua脚本在高并发场景中的价值。在并发环境中,...

    Redis+LUA脚本实现限流

    Redis+LUA脚本实现限流测试视频

    Spring Boot通过自定义注解和Redis+Lua脚本实现接口限流教程配套源码

    该源码对应个人博客【Spring Boot通过自定义注解和Redis+Lua脚本实现接口限流】教程的相关源码,小伙伴可以自行下载学习!不需要积分!不需要积分!不需要积分! 如果相关资源对您有所帮助,希望一键三连给博主一...

    Redis执行Lua脚本的好处与示例代码

    例如,如果需要执行一系列连续的Redis命令,如设置、获取和计算,这些命令可以通过一个Lua脚本一次性发送到服务器,减少了网络延迟和多次请求的开销。 2. **原子操作**: Redis将整个Lua脚本视为一个原子操作,这...

    SpringBoot-redis-lua

    1. **Lua脚本优点**: Lua脚本在Redis中执行是原子性的,能确保在并发环境下数据的一致性。此外,通过减少网络往返,提高了数据操作的效率。 2. **`EVAL`命令**: Redis提供了`EVAL`命令来执行Lua脚本。Lua脚本作为...

    redis-lua-debugger.zip

    rld 是一个非交互的调试工具,用于调试 Redis 的 Lua 脚本,这里有篇详细介绍的文章。 rld 特性包括: 易于安装,只有 6kB 可打印输出到本地和远端 跟踪执行的代码行 先进的数值变化的自动监控机制报告 报告...

    redis面试题之LUA脚本.zip

    例如,使用LUA脚本可以确保在增加用户积分时不会因并发问题而重复计分。 通过理解和掌握这些知识点,你将能够在面试中自信地讨论Redis中的LUA脚本,并在实际项目中有效地利用这一功能。在面试准备时,除了理论知识...

    秒杀系统,高并发,Redis,Lua脚本,Golang,Gin.zip

    秒杀系统,高并发,Redis,Lua脚本,Golang,Gin.zip

    redis和lua

    1. **Lua 脚本执行**: Redis 支持使用 Lua 脚本来执行一系列操作,保证原子性。这在需要复杂逻辑且保证一致性的场景中非常有用,如计数、操作多个键等。 2. **优化性能**: 由于 Lua 脚本在服务器端执行,减少了网络...

    31拓展 10:法力无边 —— Redis Lua 脚本执行原理(1).md

    使用Lua脚本可以解决很多传统Redis命令无法直接处理的问题,例如: - 实现复杂的事务操作。 - 创建自定义的命令。 - 减少客户端与服务器之间的通信次数,从而减少延迟。 - 使用Lua脚本的原子性保证来保证数据的一致...

    Golang使用lua脚本实现redis原子操作

    Golang与Redis结合使用Lua脚本,能够有效地实现原子操作,从而提高系统的稳定性和效率。 首先,Redis是一个开源的键值存储系统,它广泛用于数据缓存、消息队列以及复杂的数据结构存储。Lua是一种轻量级的脚本语言,...

    phpredis执行LUA脚本示例代码

    LUA脚本在Redis中的使用是为了实现原子操作,确保数据一致性,尤其是在处理多个操作时。本篇文章主要探讨如何通过phpredis执行LUA脚本来实现特定的Redis操作。 首先,我们需要了解LUA脚本的基本结构。在示例代码中...

    lua-redis:lua reis nginx 配制 及 redis.lua 脚本

    lua reis nginx 配制 及 redis.lua 脚本 redis.lua 脚本 支持 get, post redis 的hash, 及 集合 命令 开启redis的密码认证auth nginxlua.conf 配制 lua地址: 示列: redis_lib.php 为PHP类包 redis_lua 类

    nginx+lua+redis 集群 连接插件和脚本

    在这个“nginx+lua+redis集群”解决方案中,提供的连接插件可能是指Nginx与Redis之间的通信模块,例如lua-redis-pconnector,这个插件允许Nginx通过Lua脚本直接与Redis进行交互。而脚本部分可能包括了处理业务逻辑、...

    【Redis开发】lua脚本开发nginx 与 redis 模块

    【Redis开发】lua脚本开发nginx 与 redis 模块 (Lua script development nginx and Redis modules) 文件列表: lua_files (0, 2017-05-21) lua_files\access_control.lua (1813, 2017-05-21) lua_files\app_redis_...

    dappFinance#Note#【Redis】Redis执行Lua脚本Demo1

    1. 减少网络开销:本来多次网络请求的操作,可以用一个请求完成,原先多次请求的逻辑放在redis服务器上完成 2. 原子操作:Redis会将整个脚本作为一个整体

Global site tag (gtag.js) - Google Analytics