php redis script,redis与lua

redis的lua脚本,php中使用redis的lua

内容大纲

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中执行250:0>eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 username age hk 20

1)  "username"

2)  "age"

3)  "hk"

4)  "20"

执行Lua脚本文件

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

key和value用一个逗号隔开

keys.luareturn {

KEYS,type(KEYS),'-----',

ARGV,type(ARGV)

}[root@centos1 lua]# redis-cli --eval keys.lua k1 k2 , v1 v21) 1) "k1"

2) "k2"2) "table"3) "-----"4) 1) "v1"

2) "v2"5) "table"

evalsha

将Lua脚本加载到Redis服务端,得到该脚本的sha1校验和,evalsha命令使用sha1作为参数可以直接执行对应的Lua脚本,

避免每次发送Lua脚本的开销。这样客户端就不需要每次执行脚本内容,而脚本也会常驻在服务端,脚本内容得到了复用

加载脚本: script load命令可以将脚本内容加载到Redis内存中

hmgetall.lua  获取多个hash key的值--获取指定的多个hash keylocal result={}for i,v in ipairs(KEYS) doresult[i]=redis.call('HGETALL',v)endreturn 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 0127.0.0.1:6379> evalsha 032f22e507d134837f1c948f5b4f6b979b2e8beb 2 user:1 user:2 1) 1) "name"

2) "hk"

3) "age"

4) "20"2) 1) "name"

2) "hk2"

3) "age"

4) "22"

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<?phprequire  "./vendor/autoload.php";class HMGetAll extends \Predis\Command\ScriptCommand{public function getKeysCount()

{return false;

}public function getScript(){return<<

local result = {}for i ,v in ipairs(ARGV) doresult[i] =redis.call('HGETALL',v)endreturn 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);

结果类似

ab6c5da0b63f4d7de1b6648cfa111bd6.png

0cd75fae0d06a6a44d2ee8997cd09f9c.pngD:\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)

View Code

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

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

©著作权归作者所有:来自51CTO博客作者hkui2010的原创作品,如需转载,请注明出处,否则将追究法律责任

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值