Redis中lua脚本使用

10 篇文章 1 订阅
3 篇文章 1 订阅

Redis从2.6版本开始内置了一个lua脚本解释器,这让Redis在一定程度上成为一门可编程的数据库,如同Oracle的pl/sql,下面简单介绍下该特性

Redis执行lua脚本主要依靠两个命令:EVAL和EVALSHA


EVAL 和 EVALSHA 命令是从 Redis 2.6.0 版本开始的,使用内置的 Lua 解释器,可以执行 Lua 脚本。

EVAL 命令要求你在每次执行脚本的时候都发送一次脚本主体(script body)。Redis 有一个内部的缓存机制,因此它不会每次都重新编译脚本,不过在很多场合,付出无谓的带宽来传送脚本主体并不是最佳选择。

为了减少带宽的消耗, Redis 实现了 EVALSHA 命令,它的作用和 EVAL 一样,都用于对脚本求值,但它接受的第一个参数不是脚本,而是脚本的 SHA1 散列值。


EVAL的第一个参数是一段 Lua 5.1 脚本程序。 这段Lua脚本不需要(也不应该)定义函数。它运行在 Redis 服务器中。

EVAL的第二个参数是参数的个数,后面的参数(从第三个参数),表示在脚本中所用到的那些 Redis 键(key),这些键名参数可以在 Lua 中通过全局变量 KEYS 数组,用 1 为基址的形式访问( KEYS[1] , KEYS[2] ,以此类推)。

在命令的最后,那些不是键名参数的附加参数 arg [arg …] ,可以在 Lua 中通过全局变量 ARGV 数组访问,访问的形式和 KEYS 变量类似( ARGV[1] 、 ARGV[2] ,以此类推)。

Redis在lua脚本中提供了两个方法用来执行任意Redis命令:redis.call()和redis.pcall(),两者的区别是出错时前者直接报错,后者会捕获错误并返回错误信息

127.0.0.1:6379> EVAL 'return redis.call("set", KEYS[1], ARGV[1])' 1 name dog
OK
127.0.0.1:6379> get name
"dog"
127.0.0.1:6379> EVAL 'return redis.pcall("get", KEYS[1])' 1 name
"dog"
127.0.0.1:6379> 

Redis中lua脚本的应用场景:

就目前来看,通过EVAL命令和redis.call()方法可以执行任意redis命令,就给我们带来了便利,如果我们当前使用的redis客户端(比如php扩展)版本较低或是没有实现某些命令,lua脚本就派上用处了(当然php还可以使用Redis扩展中提供的rawCommand方法来执行任何原生命令,这里只是方便介绍),以下是php利用EVAL操作hyperloglogs代码演示

<?php

$redis = new Redis();
$redis->connect("127.0.0.1");

var_dump($redis->eval('return redis.call("pfadd", KEYS[1], "a", "b", "c")', array('hhl'), 1)); //执行pfadd命令

$redis->rawCommand('pfadd', 'hhl', 'c', 'd', 'e');  //同样可以执行pfadd命令

var_dump($redis->pfcount('hhl'));
var_dump($redis->eval('return redis.call("pfcount", KEYS[1])', array('hhl'), 1));  //采用lua脚本方式执行pfcount命令

$script = 'return redis.call("pfadd", KEYS[1], KEYS[2])';

$sha1 = $redis->script('load', $script);  //让redis服务器缓存该脚本并返回脚本的sha1散列值

echo "sha1: $sha1" . PHP_EOL;

for($i = 0; $i < 1000; $i++)
{
        $redis->rawCommand('evalsha', $sha1, 2, 'h1', md5($i)); //使用evalsha重复执行脚本,每次pfadd $i的md5值
}

var_dump($redis->pfcount('h1'));

$redis->close();

执行结果:

int(1)
int(5)
int(5)
sha1: 7b7ad98b87e3eea9e0f07b18f6f0e63c54ea8b32
int(1003)  //添加了1000个元素,统计却返回了1003,因为hyperloglogs的特性决定了统计不是完全精确,存在一定误差。

That's it!









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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值