Perl Hackers Hub
第43回 PerlでのRedis活用法(2)
前回の
Redisのデータ型
次に,
文字列型
文字列型はRedisで扱うことのできる最もシンプルなデータ型です。バイナリセーフですので,
ただし,use utf8
プラグマを宣言していると思います。そのような場合,
use utf8;
use Encode qw(encode_utf8 decode_utf8);
# 書き込むときはエンコード
$redis->set('key' => encode_utf8 '日本語');
# 読み込むときはデコード
my $val = decode_utf8 $redis->get('key');
リスト型
リスト型は複数の値を順番に並べて,
# push @key, qw(a b c); に相当
$redis->rpush(key => qw(a b c));
# pop @key; に相当
my $v = $redis->rpop('key');
# $key[1]; に相当
$redis->lindex('key', 1);
リスト型のジョブキューとしての応用
筆者の携わったサービスでは,
ジョブキューとして利用する場合,BRPOP
コマンドはRPOP
コマンドと同様にリストの末尾から値を1つ取り出すコマンドですが,BRPOP
コマンドを用いることで,
BRPOP
コマンドの簡単なサンプルを用意しました。worker.
はジョブのワーカです。ジョブキューにジョブが投入されるのを待ち,enqueue.
はジョブを投入するプログラムです。
worker.
use Redis::Fast;
my $redis = Redis::Fast->new(
server => 'localhost:6379'
);
while(1) {
my ($keyname, $job) = $redis->blpop("jobqueue", 30);
print "$keyname: $job\n";
}
enqueue.
use Redis::Fast;
my $redis = Redis::Fast->new(
server => 'localhost:6379'
);
$redis->rpush("jobqueue", "awesome job");
では,worker.
を実行してみましょう。この時点ではジョブキューに何も入っていないので,
$ perl worker.pl
次に,enqueue.
を実行します。
$ perl enqueue.pl
ジョブが投入されたので,worker.
を実行した端末に受け取ったジョブの内容が表示されるはずです。
jobqueue: awesome job
BRPOP
コマンドの動作イメージはつかめたでしょうか。この例ではワーカが1つだけでしたが,worker.
をたくさん起動してからジョブを投入したり,worker.
とenqueue.
の実行順を変えたりなどして,
ハッシュ型
ハッシュ型はPerlにおけるハッシュ変数にあたる型で,
# %key = (
# a => 1,
# b => 2,
# );
# をRedisに書き込む
$redis->hmset( key => (
a => 1,
b => 2,
) );
# $key{a} を取得
print $redis->hget('key', 'a');
セット型
セット型は値の集合を扱うための型です。セット型に保存されている値は順序を持たず,
# a, b, cを含む集合を作成
$redis->sadd(key => qw(a b c));
# 'a'が集合に含まれるか
print $redis->sismember('key', 'a');
同じ要素が重複しないことを利用して,
ただし,
集合の中からランダムに要素を取得するSRANDMEMBER
コマンドも便利です。ゲームではマッチング処理などでランダムな要素取得を多用しますが,
次のプログラムはSRANDMEMBER
コマンドの利用例です。one,
$redis->sadd(myset=>qw(one two three));
print $redis->srandmember('myset');
ソート済みセット型
ソート済みセット型はセット型と同様に集合を扱う型ですが,
# one: スコア50
# two: スコア100
$redis->zadd( key => (
50 => one,
100 => two,
) );
# 'one'の順位を取得
print $redis->zrank('key', 'one');
Luaスクリプト
Redisにはデータ保存機能だけでなく,
利点
Perlを使えば複雑なデータ処理も簡単に書くことができるのに,
それは,
Luaスクリプトの実行
Luaスクリプトの実行にはEVAL
コマンドを利用します。たとえばSET
コマンドを実行するLuaスクリプトを実行してみましょう。
my $lua = 'return redis.call("set",KEYS[1],ARGV[1])';
$redis->eval($lua, 1, 'key', 'value');
EVAL
コマンドの引数の
Luaスクリプトのキャッシュ
EVAL
コマンドを使った方法では毎回スクリプトをRedisに転送するため,SCRIPT LOAD
コマンドでスクリプトを保存したあと,EVALSHA
コマンドで呼び出せます。
# スクリプトをキャッシュに保存
my $lua = 'return redis.call("set",KEYS[1],ARGV[1])';
my $sha = $redis->script_load($lua);
# 保存したスクリプトを呼び出す
$redis->evalsha($sha, 1, 'key', 'value');
しかし今度は,EVAL
コマンドのドキュメントではこの問題を解決するために,EVALSHA
を実行してみてNOSCRIPT
のエラーが出たら,EVAL
を実行する」EVAL
コマンドはスクリプトの実行と同時にキャッシュも行うので,EVALSHA
が成功するようになります。
この処理を簡単に行えるよう筆者が開発したのが,
use Redis::Script;
my $lua = 'return redis.call("set",KEYS[1],ARGV[1])';
my $s = Redis::Script->new(script => $lua);
$s->eval($redis, ['key'], ['value']);
<続きの
本誌最新号をチェック!
WEB+DB PRESS Vol.121
2021年2月22日発売
B5判/168ページ
定価(本体1,480円+税)
ISBN978-4-297-11960-7
- 特集1
[さらに速く! さらに書きやすく!]
詳解Ruby 3
JITコンパイラ,並列プログラミング,静的型解析 - 特集2
UIKit,SwiftUI,iPadOS,ウィジェット
iOS 14最前線 - 特集3
個人と組織の目標がリンクする管理手法
OKR運用指南
バックナンバー
Perl Hackers Hub
- 第65回 依存モジュールの更新 ―update-cpanfile,GitHub Actionsで実現!(2)
- 第65回 依存モジュールの更新 ―update-cpanfile,GitHub Actionsで実現!(1)
- 第64回 少しマニアックなPerlのテクニック―特殊変数,低レベルの標準関数を使いこなす(2)
- 第64回 少しマニアックなPerlのテクニック―特殊変数,低レベルの標準関数を使いこなす(1)
- 第63回 PPIとPerl::Tidyを組み合わせて作るコード整形ツール(2)
- 第63回 PPIとPerl::Tidyを組み合わせて作るコード整形ツール(1)
- 第62回 Perl歴史散策 ―インタプリタの実装と,構文の進化をたどる(3)
- 第62回 Perl歴史散策 ―インタプリタの実装と,構文の進化をたどる(2)
- 第62回 Perl歴史散策 ―インタプリタの実装と,構文の進化をたどる(1)
- 第61回 GitHub ActionsとAmazon ECSを使ったDockerアプリケーションの自動デプロイ(3)