当前位置: 首页 > news >正文

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.lua

return {
KEYS,
type(KEYS),
'-----',
ARGV,
type(ARGV)
}
[root@centos1 lua]# redis-cli --eval keys.lua k1 k2 , v1 v2
1) 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 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: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

<?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)
View Code

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

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

转载于:https://www.cnblogs.com/HKUI/p/9251110.html

相关文章:

  • 并发数和TPS的理解
  • java 过滤list的几种方式
  • java中的重载(overload)和重写(override)区别
  • 这是一套Java菜鸟到大牛的学习路线之高级教程,由工作了10年的资深Java架构师整理。...
  • 雷林鹏分享:PHP 多维数组
  • 联系我过户这些快到期的域名
  • Maven使用过程中遇到的问题,及解决方案
  • linux磁盘管理
  • spring配置中classpath: 与classpath*:的区别
  • 虚拟机(Virtual Machine)和容器(Container)的对比
  • Linux第四章 进程
  • css选择器有哪些
  • Hbase备份
  • 前端战五渣学前端——初探Parcel急速打包
  • Android程序员搞Web之HTNL(一)
  • 【附node操作实例】redis简明入门系列—字符串类型
  • 2019年如何成为全栈工程师?
  • angular学习第一篇-----环境搭建
  • canvas 绘制双线技巧
  • canvas绘制圆角头像
  • javascript 哈希表
  • PHP 7 修改了什么呢 -- 2
  • SegmentFault 社区上线小程序开发频道,助力小程序开发者生态
  • spring security oauth2 password授权模式
  • 从0搭建SpringBoot的HelloWorld -- Java版本
  • 分布式事物理论与实践
  • 深入 Nginx 之配置篇
  • 跳前端坑前,先看看这个!!
  • nb
  • 你对linux中grep命令知道多少?
  • # Java NIO(一)FileChannel
  • #QT(智能家居界面-界面切换)
  • #大学#套接字
  • (echarts)echarts使用时重新加载数据之前的数据存留在图上的问题
  • (八)光盘的挂载与解挂、挂载CentOS镜像、rpm安装软件详细学习笔记
  • (附源码)springboot家庭装修管理系统 毕业设计 613205
  • (附源码)流浪动物保护平台的设计与实现 毕业设计 161154
  • (转)Scala的“=”符号简介
  • .bat批处理出现中文乱码的情况
  • .cfg\.dat\.mak(持续补充)
  • .NET 4 并行(多核)“.NET研究”编程系列之二 从Task开始
  • .NET Framework 服务实现监控可观测性最佳实践
  • .NET MVC 验证码
  • .net 程序发生了一个不可捕获的异常
  • .NET 中什么样的类是可使用 await 异步等待的?
  • .Net(C#)常用转换byte转uint32、byte转float等
  • .net反编译工具
  • .net解析传过来的xml_DOM4J解析XML文件
  • .NET应用架构设计:原则、模式与实践 目录预览
  • [ 渗透工具篇 ] 一篇文章让你掌握神奇的shuize -- 信息收集自动化工具
  • [23] GaussianAvatars: Photorealistic Head Avatars with Rigged 3D Gaussians
  • [BUUCTF 2018]Online Tool
  • [BZOJ] 2427: [HAOI2010]软件安装
  • [C++]priority_queue的介绍及模拟实现
  • [CF494C]Helping People