关于redis:Redis-实战-14-Redis-的-Lua-脚本编程

35次阅读

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

简介

Redis 从 2.6 版本开始引入应用 Lua 编程语言进行的服务器端脚本编程性能,这个性能能够让用户间接在 Redis 外部执行各种操作,从而达到简化代码并进步性能的作用。P248

在不编写 C 代码的状况下增加新性能 P248

通过应用 Lua 对 Redis 进行脚本编程,咱们能够防止一些减慢开发速度或者导致性能降落对常见陷阱。P248

将 Lua 脚本载入 Redis P249
  • SCRIPT LOAD 命令能够将脚本载入 Redis,这个命令承受一个字符串格局的 Lua 脚本为参数,它会把脚本存储起来期待之后应用,而后返回被存储脚本的 SHA1 校验和
  • EVALSHA 命令能够调用之前存储的脚本,这个命令接管脚本的 SHA1 校验和以及脚本所需的全副参数
  • EVAL 命令能够间接执行指定的脚本,这个命令接管脚本字符串以及脚本所需的全副参数。这个命令除了会执行脚本之外,还会将被执行的脚本缓存到 Redis 服务器外面

因为 Lua 的数据传入和传出限度,Lua 与 Redis 须要进行互相转换。因为脚本在返回各种不同类型的数据时可能会产生含糊不清的后果,所以咱们应该尽量显式的返回字符串。P250

咱们能够在 官网文档 中找到 Redis 和 Lua 不同类型之间的转换表:

Redis 类型转换至 Lua 类型

RedisLua
integer replynumber
bulk replystring
multi bulk replytable (may have other Redis data types nested)
status replytable with a single ok field containing the status
error replytable with a single err field containing the error
Nil bulk replyfalse boolean type
Nil multi bulk replyfalse boolean type

Lua 类型转换至 Redis 类型

LuaRedis
numberinteger reply (the number is converted into an integer)
stringbulk reply
table (array)multi bulk reply (truncated to the first nil inside the Lua array if any)
table with a single ok fieldstatus reply
table with a single err fielderror reply
boolean falseNil bulk reply
boolean trueinteger reply with value of 1
创立新的状态音讯 P251
  • Lua 脚本跟单个 Redis 命令以及 MULTI/EXEC 事务一样,都是原子操作
  • 曾经对构造进行了批改的 Lua 脚本将无奈被中断

    • 不执行任何写命令对只读脚本:能够在脚本对运行工夫超过 lua-time-limit 选项指定的工夫之后,执行 SCRIPT KILL 命令杀死正在运行对脚本
    • 有写命令的脚本:杀死脚本将导致 Redis 存储的数据进入一种不统一的状态。在这种状况下

应用 Lua 重写锁和信号量 P254

如果咱们当时不晓得哪些键会被读取和写入,那么就应该应用 WATCH/MULTI/EXEC 事务或者锁,而不是 Lua 脚本。因而,在脚本外面对未被记录到 KEYS 参数中的键进行读取或者写入,可能会在程序迁徙至 Redis 集群的时候呈现不兼容或者故障。P254

获取锁在目前已不须要应用 Lua 脚本实现,能够间接应用 SET,并用 PXNX 选项即可在键不存在的时候设置带过期工夫的值。开释锁时为了保障开释的时本人获取的锁,须要应用 Lua 脚本实现。相干代码已在 实现主动补全、分布式锁和计数信号量 中实现。

移除 WATCH/MULTI/EXEC 事务 P258

一般来说,如果只有少数几个客户端尝试对被 WATCH 命令监督对数据进行批改,那么事务通常能够在不产生显著抵触或重试的状况下实现。然而,如果操作须要进行好几次通信往返,或者操作发生冲突的概率较高,又或者网络提早较大,那么客户端可能须要重试很屡次能力实现操作。P258

应用 Lua 脚本代替事务不仅能够保障客户端尝试的执行都能够胜利,还能升高通信开销,大幅提高 TPS。同时因为 Lua 脚本没有屡次通信往返,所以执行速度也会显著快于细粒度锁的版本。

Lua 脚本能够提供微小的性能劣势,并且能在一些状况下大幅地简化代码,但运行在 Redis 外部但 Lua 脚本只能拜访位于 Lua 脚本之内或者 Redis 数据库之内的数据,而锁或者 WATCH/MULTI/EXEC 事务并没有这一限度。P263

应用 Lua 对列表进行分片 P263

分片列表的形成 P263

为了可能对分片列表的两端执行推入操作和弹出操作,在构建分片列表时除了须要存储组成列表的各个分片之外,还须要记录列表第一个分片的 ID 以及最初一个分片的 ID。当分片列表为空时,这两个字符串存储的分片 ID 将是雷同的。P263

组成分片列表的每个分片都会被命名为 <listname>:<shardid>,并依照程序进行调配。具体来说,如果程序总是从左端弹出元素,并从右端推入元素,那么最初一个调配的索引就会逐步增大,并且新分片的 ID 也会变得越来越大。如果程序总是从右端弹出元素,并从左端推入元素,那么第一个分片的索引就会逐步缩小,并且新分片的 ID 也会变得越来越小。P264

当分片列表蕴含多个列表时,位于分片两端的列表可能是被填满的,但位于两端之间的其余列表总是被填满的。P264

将元素推入分片列表 P265

Lua 脚本依据命令 LPUSH/RPUSH 找到列表的第一个分片或者最初一个分片,而后将元素推入分片对应的列表中,若分片已达个数下限(能够取配置中的 list-max-ziplist-entries 的值 – 1 作为下限),则会主动产生一个新的分片,持续推入,并更新第一个分片或者最初一个分片的分片 ID。当推入操作执行结束后,它会返回被推入元素的数量。P265

从分片外面弹出元素 P266

Lua 脚本依据命令 LPOP/RPOP 找到列表的第一个分片或者最初一个分片,而后在分片非空的状况下,从分片外面弹出一个元素,如果列表在执行弹出操作之后不再蕴含任何元素,那么程序就对记录着列表两端分片信息的字符串键进行批改(留神只有列表端分片为空时才批改对应的字符串键,而整个列表为空时,不做调整)P267

对分片列表执行阻塞弹出操作 P267

这一段书上讲得看不懂,也不晓得为什么须要书中的花式操作能力实现。

集体感觉分片列表的阻塞弹出其实并不需要列表本身的阻塞弹出,咱们能够一直执行上述 Lua 脚本实现的弹出元素的操作,若弹出胜利,则间接返回,若弹出失败,则睡 1 ms 后继续执行弹出操作,直至弹出胜利或者达到超时工夫。这样咱们对 Redis 对操作只在 Lua 脚本中,原子性保障了肯定会弹出分片列表两端的元素。

本文首发于公众号:满赋诸机(点击查看原文)开源在 GitHub:reading-notes/redis-in-action

正文完
 0