内容大纲

redis里使用eval和evalsha

redis管理Lua脚本 

php里使用redis的lua脚本

在redis里使用lua脚本的好处

1.Lua脚本在Redis中是原子执行的,执行过程中间不会插入其他命令
2.Lua脚本可以帮助开发和运维人员创造出自己定制的命令,并可以将这些命令常驻在Redis内存中,实现复用的效果。
3.Lua脚本可以将多条命令一次性打包,有效地减少网络开销

在redis中

eval的语法格式
EVAL script numkeys key [key ...] arg [arg ...]
其中:
<1> script: 你的lua脚本
<2> numkeys: key的个数
<3> key: redis中各种数据结构的替代符号
<4> arg: 你的自定义参数

eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 username age hk 20
第一个参数的字符串是script,也就是lua脚本,2表示keys的个数,KEYS[1] 就是username的占位符, KEYS[2]就是
age的占位符,ARGV[1]就是jk的占位符,ARGV[2]就是20的占位符,以此类推,所以最后的结果应该就是:{return username age hk 20}

其中要要读写的键名应该作为key参数,其它的数据都作为arg参数
eval命令依据第二个参数将后面的所有参数分别存入脚本中KEYS和ARGV两个表类型的全局变量。
当脚本不需要任何参数时也不能省略这个参数(设为0)

在cli中执行

:>eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}"  username age hk
) "username"
) "age"
) "hk"
) ""

执行Lua脚本文件

redis-cli --eval keys.lua k1 k2 , v1 v2

key和value用一个逗号隔开

keys.lua

return {
KEYS,
type(KEYS),
'-----',
ARGV,
type(ARGV)
}
[root@centos1 lua]# redis-cli --eval keys.lua k1 k2 , v1 v2
) ) "k1"
) "k2"
) "table"
) "-----"
) ) "v1"
) "v2"
) "table"

evalsha

将Lua脚本加载到Redis服务端,得到该脚本的sha1校验和,evalsha命令使用sha1作为参数可以直接执行对应的Lua脚本,
避免每次发送Lua脚本的开销。这样客户端就不需要每次执行脚本内容,而脚本也会常驻在服务端,脚本内容得到了复用
加载脚本: script load命令可以将脚本内容加载到Redis内存中

hmgetall.lua  获取多个hash key的值

--获取指定的多个hash key

local result={}
for i,v in ipairs(KEYS) do
result[i]=redis.call('HGETALL',v)
end
return result

[root@centos1 redis-lua]# redis-cli script load "$(cat hmgetall.lua)"
"032f22e507d134837f1c948f5b4f6b979b2e8beb"
得到sha1的值
在redis里执行脚本
evalsha 脚本sha1值 key个数 key列表 参数列表
evalsha 032f22e507d134837f1c948f5b4f6b979b2e8beb 2 user:1 user:2 0

127.0.0.1:> evalsha 032f22e507d134837f1c948f5b4f6b979b2e8beb  user: user:
) ) "name"
) "hk"
) "age"
) ""
) ) "name"
) "hk2"
) "age"
) ""

Redis管理Lua脚本
1.script load
此命令用于将Lua脚本加载到Redis内存中
2.script exists
scripts exists sha1 [sha1 …]
此命令用于判断sha1是否已经加载到Redis内存中
3.script flush
此命令用于清除Redis内存已经加载的所有Lua脚本,在执行script flush后,sha1不复存在 
4.script kill
此命令用于杀掉正在执行的Lua脚本

为了防止某个脚本执行时间过长导致redis无法提供服务
redis提供lua-time-limit 参数限制脚本的最长运行时间,默认为5秒
当脚本运行超过这一限制后,redis将开始接收其它命令但不会执行(以确认脚本的原子性,因为此时脚本并没有终止),而是返回busy 错误
打开2个redis客户端
redis A> eval "while true do end" 0
redis B中
127.0.0.1:6379> keys *
(error) BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE.
此时redis虽然可以接收任何命令,但实际会执行的只有2个 SCRIPT KILL or SHUTDOWN NOSAVE
127.0.0.1:6379> script kill
OK
需要注意的是 如果当执行的是修改操作,则 SCRIPT KILL 命令不会终止脚本的运行以防止脚本只执行了一部分(违背原子性的要求)
redis A>eval "redis.call('set','name','hk') while true do end" 0
redis B里

127.0.0.1:6379> keys *
(error) BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE.
127.0.0.1:6379> script kill
(error) UNKILLABLE Sorry the script already executed write commands against the dataset. You can either wait the script termination or kill the server in a hard way using the SHUTDOWN NOSAVE command.

此时只能 SHUTDOWN NOSAVE
SHUTDOWN NOSAVE 不会进行持久化的操作 与 SHUTDOWN 的区别

php里使用redis的lua脚本

lua.php

<?php
require "./vendor/autoload.php"; class HMGetAll extends \Predis\Command\ScriptCommand{ public function getKeysCount()
{
return false;
}
public function getScript(){
return
<<<LUA
local result = {}
for i ,v in ipairs(ARGV) do
result[i] =redis.call('HGETALL',v)
end
return result
LUA; }
}
$client= new \Predis\Client(
[
'scheme'=>'tcp',
'host' => '192.168.0.250',
'port' => 6379,
]
);
//定义hmgetall命令
$client->getProfile()->defineCommand("hmgetall",'HMGetAll'); var_dump($client->hgetall('user:1'));
var_dump($client->hgetall('user:2'));
//执行hmgetall $value=$client->hmgetall('user:1','user:2');
var_dump($value);

结果类似

D:\wamp64\www\cnblogs\lua\php\lua.php:32:
array (size=2)
'name' => string 'hk' (length=2)
'age' => string '20' (length=2)
D:\wamp64\www\cnblogs\lua\php\lua.php:33:
array (size=2)
'name' => string 'hk2' (length=3)
'age' => string '22' (length=2)
D:\wamp64\www\cnblogs\lua\php\lua.php:37:
array (size=2)
0 =>
array (size=4)
0 => string 'name' (length=4)
1 => string 'hk' (length=2)
2 => string 'age' (length=3)
3 => string '20' (length=2)
1 =>
array (size=4)
0 => string 'name' (length=4)
1 => string 'hk2' (length=3)
2 => string 'age' (length=3)
3 => string '22' (length=2)

参考redis入门指南(书中这块有错误 应该是ARGV而不是循环KEYS)

详细代码见  https://gitee.com/hk/cnblogs/tree/master/lua/php

redis与lua的更多相关文章

  1. PHP中使用redis执行lua脚本示例

    摸索了一下在PHP中如何使用redis执行lua脚本,写了一个脚本如下,供以后参考 <?php $redis = new Redis(); #实例化redis类 $redis->conne ...

  2. redis之lua脚本

    背景介绍 redis数据库提供了一些管理功能比如 流水线:打包发送多条命令,并在一个回复里面接收所有被执行命令的结果.事务:一次执行多条命令,被执行的命令要么就全部都被执行,要么就一个也不执行.并且事 ...

  3. Redis学习-LUA脚本

    最近在做K线的项目中,需要计算商品的分时数据.为了保证多台机器对同一商品的计算的有序性,所以在Redis中进行计算,同时为了保证在分时数据计算过程的原子性所以使用了LUA脚本,Redis内置了对LUA ...

  4. Redis进阶实践之七Redis和Lua初步整合使用

    一.引言        Redis学了一段时间了,基本的东西都没问题了.从今天开始讲写一些redis和lua脚本的相关的东西,lua这个脚本是一个好东西,可以运行在任何平台上,也可以嵌入到大多数语言当 ...

  5. Redis结合Lua脚本实现高并发原子性操作

    从 2.6版本 起, Redis 开始支持 Lua 脚本 让开发者自己扩展 Redis … 案例-实现访问频率限制: 实现访问者 $ip 在一定的时间 $time 内只能访问 $limit 次. 非脚 ...

  6. Redis进阶实践之七Redis和Lua初步整合使用(转载 7)

    Redis进阶实践之七Redis和Lua初步整合使用 一.引言 Redis学了一段时间了,基本的东西都没问题了.从今天开始讲写一些redis和lua脚本的相关的东西,lua这个脚本是一个好东西,可以运 ...

  7. Redis 与 Lua Script

    [Redis Script] 1.EVAL script numkeys key [key ...] arg [arg ...] 从 Redis 2.6.0 版本开始,通过内置的 Lua 解释器,可以 ...

  8. redis(6)lua脚本

    一.lua脚本 lua是一种轻量小巧的脚本语言,用标准的C语言编写并以源代码形式开放,其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能. lua的详细内容你可以参考lua官方网站 ...

  9. redis的lua脚本拓展,返回nil及其判断

    redis自带的lua脚本 127.0.0.1:6379> hget team wyc "{\"name\":\"wyycc\",\" ...

随机推荐

  1. zabbix负载均衡群集高可用架构

    由于服务器资源限制,将MySQL服务放在zabbix服务器上,生产环境应尽量分开

  2. [AHOI2008]上学路线

    题意:给定一个无向图,删除某些边有一定的代价,要求删掉使得最短路径减小,求最小代价. 首先要spfa求出起点到各个点的最短距离.对于一条权值为w,起点为i,终点为j的边,设dis[k]为起点到k点的距 ...

  3. 解决 vim 乱码

    打开vim安装目录下的_vimrc,在头部加上几句配置语句就能搞定: //设置默认编码 set encoding=utf-8 set fileencodings=utf-8,chinese,latin ...

  4. 数据结构与算法(python版)教程

    算法的性质 算法的描述 算法的设计与分析

  5. gif&png&jpg&webp

    几种图片格式的区别和联系 1.http://www.tuicool.com/articles/AbUvI3A

  6. 将keras模型在django中应用时出现的小问题——ValueError: Tensor Tensor("dense_2/Softmax:0", shape=(?, 8), dtype=float32) is not an element of this graph.

    本文原出处(感谢作者提供):https://zhuanlan.zhihu.com/p/27101000 将keras模型在django中应用时出现的小问题 王岳王院长 10 个月前 keras 一个做 ...

  7. Rails 5 Test Prescriptions 第6章Adding Data to Tests

    bcreate the data quickly and easily.考虑测试运行的速度. fixtures and factories.以及下章讨论的test doubles,还有原生的creat ...

  8. Learn Rails5.2-- rails base(含官方指导Debugging 摘录)

    豆知识扩展: <meta>  https://www.cnblogs.com/chentianwei/p/9183799.html css selector div > p 选择所有 ...

  9. 用jersey写简单Restful接口

    1.在myeclipse中新建一个Dynamic Web Project 2.下载jar包,地址在这里 3.restful service代码 package com.qy; import javax ...

  10. hdu5015矩阵快速幂

    参考博客:http://blog.csdn.net/rowanhaoa/article/details/39343769 反正递推关系式推了一个多小时没搞出来...太弱了 真是愧对数学系这一专业了.. ...