Shogo's Blog

Aug 24, 2013 - 2 minute read - perl redis

Perl の Redis ライブラリを調べた

最近Redis を使ったコードを書くようになったのですが、 キー名を毎回指定するのがだるいです。 Ruby には redis-objects というのがあって、 Redisのキーをオブジェクトとして扱うことができるようです。 きっと、Perl にも似たようなのあるだろ、って思って調べてみました。

ほしいもの

低レベルなRedisのライブラリはたいていメソッドとRedisのコマンドが一対一対応していて、 次のようなコードになると思います。

$redis->set('key-name', 'piyopiyo');
$redis->get('key_name');

でも、Redisに何か操作をしたいわけじゃなくて、 Redisのキーに対して操作をしたいので、 次のように書けるべきだと思うんです。

my $key = key($redis, 'key-name');
$key->set('piyopiyo');
$key->get();

Redis::Hash, Redis::List

Redis::HashRedis::Listは Perlのハッシュや配列と同じ操作で Redis にアクセスできるようにするライブラリ。

use utf8;
use warnings;
use strict;
use 5.014;

use Redis::Hash;

tie my %my_hash, 'Redis::Hash', 'hash_prefix', (server => 'localhost:6379');

# set hash_prefix:hogehoge piyopiyo
# set hash_prefix:fugafuga fugufugu
$my_hash{hogehoge} = 'piyopiyo';
$my_hash{fugafuga} = 'fugufugu';

# get hash_prefix:hogehoge piyopiyo
say $my_hash{hogehoge}; # piyopiyo

# keys hash_prefix:*
say join ',', keys %my_hash; #fugafuga,hogehoge

# keys hash_prefix:*
# get hash_prefix:fugafuga
# get hash_prefix:hogehoge
say join ',', values %my_hash; #fugufugu,piyopiyo

# del hash_prefix:hogehoge
delete $my_hash{hogehoge};

tie とかよくわかない。 Perl の黒魔術を見た気がしました。

普通のハッシュや配列に見えるのは面白いけど、 Redisっぽい機能がまったく使えないのはつらい。 tied(%my_hash)->cmd って書けばコマンド発行できるけど、 それなら最初から直接 Redis.pm を 使えよって話になります。

あと、tie するごとにコネクションを張り直しているようなので、 たくさんのハッシュやリストを作ると大変なことになりそうです。

Redis::Client

これも tie すると、Redis上のデータをハッシュや配列として扱うことができます。 tie できるのは String, List, Hash, Set, Zset。 それぞれがRedisで使えるデータ型に対応している。

use utf8;
use warnings;
use strict;
use 5.014;

use Redis::Client;

my $client = Redis::Client->new;
tie my $str, 'Redis::Client::String', key => 'my_string', client => $client;

$str = 'foo';
say $str;

ひとつのキーに対してひとつのオブジェクトを割り当てるのは良さげ。 また、ハッシュ型、セット型、ソート済みセット型といった、Redis特有のデータ型に対応しているのもGood。 でも、ただストアするだけならこれで十分だけど、もう少し高度な機能も使いたい・・・。

Tie::Redis

Tie::Redis も tie を使ってPerlのデータ構造っぽく扱えるようにするライブラリ。

Redis全体を一つのハッシュとして扱ったり、 Redisの文字列型、ハッシュ型、リスト型を扱えるみたい。

Redis::Object

Redis::Ojectは ORM風なRedis用ライブラリ。

package MyRedisDatabase;

use Moose;
extends qw/ Redis::Object /;

has tables => (
    isa     => 'ArrayRef[Str]',
    is      => 'ro',
    default => sub { [ qw/SomeTable/ ] },
);

__PACKAGE__->meta->make_immutable;
package MyRedisDatabase::SomeTable;

use Moose;
with qw/ Redis::Object::Table /;

has hoge => ( isa => 'Str', is => 'rw', default => 'Something' );

__PACKAGE__->meta->make_immutable;
use utf8;
use strict;
use warnings;
use 5.014;

use MyRedisDatabase;

# init database
my $db = MyRedisDatabase->new(
    server => 'localhost:6379'
);

# create item
my $item = $db->create( SomeTable => {
    hoge => "Hello",
} );

# fetch item by id
$item = $db->find( SomeTable => $item->id );

# update item
$item->hoge( "piyo" );

ORMっぽいけど、あんまり複雑な検索はできないらしい。 ここまでするなら普通にMySQLとORMつかったほうが良さそう。

まとめ

みんな tie が大好き。

tie しないのがほしいな・・・。