利用lua脚本实现redis的事务功能

lua类,以 hset + expire 实现类似于 setexhsetex 为例

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);

results matching ""

    No results matching ""