PHPRedisでLuaを使ってみたので備忘録【サンプル付き】
なぜLuaを使うのか
Luaを使うと、Redisに存在しているコマンドで実現できない動作を実現することができます。 これには、「Redis Eval」などと検索すると、参考資料が出てくるかと思います。 ※ 後述に詳細を記載。 また、「Redis Lua」で検索すると、よくAtomicな処理と出てきます。 Atomicな操作とは、調べてみると、他者が割り込むことの出来ない操作という意味だそうです。 つまり、同時にデータにアクセスされる可能性がある際に、ロックをしなくても良いということです。
実際に使ってみる
RedisでLuaを使用する際には、前述にもありました「Eval」を使用します。 例えば、以下の記述は、同じ動作をします。 (redis-cliを立ち上げて、実行します) 通常の場合
> set test 123
Evalの場合
> eval "redis.call('set','test' , 123)" 0
evalの後にある引数の文字列がLuaとなり、 Luaの中でredis.call関数を実行すると、Redisに存在するコマンドを呼び出すことができるという意味ですね。
先ほどの動きをPHPで書いてみる
通常の場合
$redis->set('test', 123);
Evalの場合
$command = “redis.call(’set', 'test', 123)";
$redis->eval($command, 0);
ここまでだと、どういう時にLuaを使うのかわかりにくいと思いますが、Luaの中で複数の処理をすることも可能です。 例えば、値をsetして、その値をgetしてみます。
$command = “
redis.call(’set', 'test', 123)
return redis.call(’get', 'test')
";
$test = $redis->eval($command, 0);
このようにした場合には、test変数に「123」が入ります。
PHPからLuaに値を渡してみる
先ほどまでの動作では、「test」というキー名をそのままLuaの中に記述しているため、 固定のキー名での動作しかせず、このままでは役に立ちません。 そのため、PHPからLuaに値を渡してみます。 Redisから試す
> eval "return redis.call('set', KEYS[1], ARGV[1])" 1 'test' 123
急にわかりづらくなりましたね。 まずevalの引数について、学びましょう。 fa-angle-right第1引数 : Lua script fa-angle-right第2引数 : キーの数 fa-angle-right第3引数(指定分) : キー fa-angle-right第4引数 : 引数 今まで第2引数で0を渡していたのは、キーがなかったからです。 例えば、キーが2つ、引数が3つとかの場合、第2引数に「2」といれてやれば、 3,4番目の値がキー、残りが引数として扱われるようです。 また、Luaに渡す値を取り出す場合には、KEYS, ARGV でそれぞれを取得することができます。 この時に、一番目の要素を取り出そうとして、KEYS[0]のように間違えないように注意が必要です。 今度は、先ほどの処理をPHPで書いてみます。 PHPの場合
$command = “redis.call(’set', KEYS[1], ARGV[1])";
$test = $redis->eval($command, 1 , 'test', 123);
書き方は、ほとんど変わらないので、簡単ですね。
キーと引数の違いについて
そもそもに「キー」と「引数」という呼び方が正式なものかもわからないですが、 この記事内では、この呼び方で統一いたします。 evalの引数として渡している、キーと引数、別に分ける必要ないのでは、と感じた方もいるかもしれません。 しかし、キーにprefixをつける等をしている場合に違いが出てくるようです。 その他にも理由があると思うのですが、知らないため、ご存知の方いれば、こっそり教えてください。