关于redis:Redis-Lua-教程

48次阅读

共计 3020 个字符,预计需要花费 8 分钟才能阅读完成。

lua-redis

简介

在 Redis 中应用 Lua 脚本在业务开发中是比拟常见的事件,应用 Lua 的长处 有以下几点。

  1. 对于与屡次 redis 指令的发送,应用 Lua 脚本能够 缩小网络的开销 。当网络传输慢或者响应要求高的场景中尤为要害。
    Lua 脚本能够将多个申请通过脚本模式一次进行解决,缩小网络的相干时延。Redis 还提供了 Pipeline 来解决这个问题,
    然而在后面指令会影响前面指令逻辑的场景下,Pipeline 并不能满足。
  2. 原子操作。在 Lua 脚本中会将整个脚本作为一个整体来执行,两头 不会被其余指令而打断 ,因而 保障了原子性
    因而在咱们写 Lua 脚本时,无需思考竞争而导致的整体数据 状态不统一 的问题,并且无需应用事务。并且因为此个性,
    需确保脚本尽可能不要运行工夫过长,要确保脚本执行的粒度最小化。
  3. 复用和封装。针对于一些 通用能力 的性能,把这些放到 redis 脚本中去实现。
    其余客户端调用雷同的脚本代码,从而达到逻辑的 复用

比照 Lua 脚本与事务:

Lua 脚本自身也能够看作为一种事务,而且应用脚本起来更简略,并且可管制的流程更灵便。

在应用 Redis 事务的时候会遇到两种 问题

  • 事务在调用 EXEC 之前,产生了语法错误(如参数数量,参数名等问题)或者服务器内存等问题。
    遇到这一类问题是,会在服务器运行这些指令前发现这些问题(2.6.5 之后),并且终止此次的事务。
  • 事务执行 EXEC 调用之后的失败,如事务中某个键的类型谬误的问题。两头指令的谬误并不会终止前面的流程,
    也不会导致后面指令的回滚。然而在 Lua 脚本中,你能够齐全管制这些。

Lua-Redis 指令教程

注入和应用脚本:

  1. 运行脚本时把脚本发送到 Redis(网络开销较大)

    EVAL script numkeys [key ...] [arg ...]
    
    # 运行脚本
    redis> EVAL "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second
    
    # 运行只读脚本,脚本须要不蕴含任何批改内容的操作。这个指令能够随便被 kill 掉,# 而且不会影响到正本的 stream。这个指令能够在 master 和 replica 上执行。redis> EVAL_RO "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second
  2. 上传脚本,之后应用 SHA1 校验和来调用脚本。(潜在碰撞问题,在应用时个别会漠视)

    SCRIPT LOAD script
    EVALSHA sha1 numkeys key [key ...] arg [arg ...]
    
    redis> SCRIPT LOAD "return'hello moto'""232fd51614574cf0867b83d384a5e898cfd24e5a"
    
    # 运行脚本
    redis> EVALSHA 232fd51614574cf0867b83d384a5e898cfd24e5a 0
    "hello moto"
    
    # 运行只读脚本,脚本须要不蕴含任何批改内容的操作。这个指令能够随便被 kill 掉,# 而且不会影响到正本的 stream。这个指令能够在 master 和 replica 上执行。redis> EVALSHA 232fd51614574cf0867b83d384a5e898cfd24e5a 0
  3. 其余一些指令
  4. SCRIPT DEBUG 用来调试脚本 Document
  5. SCRIPT EXISTS 通过校验值用来查看脚本是否存在 Document
  6. SCRIPT FLUSH 革除脚本 Document
  7. SCRIPT KILL 停到当初执行中的脚本,默认脚本没有写操作 Document
  8. 留神点
  9. 运行脚本须要严格依照 Keys 和 Args 的要求来进行传参。
    所有操作到的 redis key 应放到 Keys 对象中,否则可能会影响到在 redis 集群中谬误体现。

    # Bad
    > eval "return redis.call('set','foo','bar')" 0
    OK
    
    # Good
    > eval "return redis.call('set',KEYS[1],'bar')" 1 foo
    OK

调用 redis 指令

在 redis lua 脚本中最罕用的就是调用 redis 原生的指令。有以下两个指令:

  1. redis.call(command, key, arg1, arg2…): 当调用产生谬误时,主动终止脚本,强制把相干 Lua 谬误返回给客户端。
  2. redis.pcall(command, key, arg1, arg2…): 当调用产生谬误时,会进行谬误拦挡,并返回相干谬误。

当调用 redis.call 和 redis.pcall 指令时 Redis Reply 会转换为 Lua 类型,当 Lua 脚本返回时,会将 Lua 类型转换为 Redis Reply。
因而这两种类型的转换是须要通晓的。能够浏览此文档理解 Redis 协定。Link

  • Redis integer reply: 如 EXISTS…
  • Redis bulk reply: 如 GET…
  • Redis multi bulk reply: 如 LRANGE…
  • Redis status reply: 如 SET…
  • Redis error reply: 指令谬误 …
转换表
  • Redis 回复类型转 Lua 类型转换表:

         Redis integer reply   ->   Lua number
    
            Redis bulk reply   ->   Lua string
    
      Redis multi bulk reply   ->   Lua table (may have other Redis data types nested)
    
          Redis status reply   ->   Lua table with a single ok field containing the status
    
           Redis error reply   ->   Lua table with a single err field containing the error
    
        Redis Nil bulk reply   ->   Lua false boolean type
    
    Redis Nil multi bulk reply   ->   Lua false boolean type
  • Lua 类型类型转 Redis 回复转换表:

                  Lua number   ->   Redis integer reply (the number is converted into an integer)
    
                  Lua string   ->   Redis bulk reply
    
           Lua table (array)   ->   Redis multi bulk reply (truncated to the first nil inside the Lua array if any)
    
           Lua table with      ->   Redis status reply
           a single ok field
    
           Lua table with      ->   Redis error reply
           a single err field
    
           Lua boolean false   ->   Redis Nil bulk reply.
  • 注意事项
  1. Lua 只有 一个数字类型 ,Lua number。没有辨别 integer 和 floats,因而将 永远转换 Lua numbers 为 integer 回复
    如果须要 floats 类型,请 return 字符串。(ZSCORE 指令就是这么实现的)
  2. 因为 Lua语义 起因,Lua array 不能够有 nils。当 redis reply 转换到 Lua array 时会 终止运行
  3. Lua Table 蕴含 keys(和其 values),转换成 redis reply 将 不会蕴含 keys
RESP3 – Redis 6 协定

如须要理解请查看官网文档 Link

示例

Link

Reference:

  • Redis Lua 实战 Link
  • Redis 官网文档 Link

正文完
 0