利用lua脚本实现redis的事务功能
lua类,以 hset
+ expire
实现类似于 setex
的 hsetex
为例
class RedisLua
{
protected $hsetexScriptSha1 = '37f7a20a02cbe9f10e404531931ca11c3ea983ed';
// 修改lua脚本后,可以通过 $this->sha1() 重新计算对应的sha1值
protected $hsetexScript = '
redis.call("HSET", KEYS[1], ARGV[1], ARGV[2]);
redis.call("EXPIRE", KEYS[1], ARGV[3]);
return true;
';
protected $redis;
public function __construct($redis)
{
$this->redis = $redis;
}
public function hsetex($key, $field, $value, $seconds)
{
$res = $this->execLua(
$this->hsetexScript,
$this->hsetexScriptSha1,
[$key],
[$field, $value, $seconds]
);
return $res;
}
/**
* @param string $script
* @param string $sha1
* @param string[]|null $keys
* @param string[]|null $args
* @return mixed
*/
protected function execLua($script, $sha1, $keys = null, $args = null)
{
try {
return $this->redis->evalSha($sha1, array_merge($keys, $args), count($keys));
} catch (\Exception $e) {
if (0 === strpos($e->getMessage(), 'NOSCRIPT')) {
return $this->redis->eval($script, array_merge($keys, $args), count($keys));
}
return false;
}
}
public function sha1()
{
echo 'please set $this->hsetexScriptSha1';
echo PHP_EOL;
echo sha1($this->hsetexScript);
echo PHP_EOL;
}
}
使用式例
$redis = new \Redis();
$redis->connect("127.0.0.1", 6379);
$redisLua = new RedisLua($redis);
$redisLua->hsetex("zhangsan", "age", 13, 3);
$value = $redis->hGet("zhangsan", "age");
// 输出13
var_dump($value);
sleep(4);
$value = $redis->hGet("zhangsan", "age");
// 输出false
var_dump($value);