はばばばば

長くなりそうなことや取っておきたいことを記録します

phpredisでハッシュ型の値を期限(Expire)付きで設定する

f:id:Mint0A0yama:20150223004721j:plain

万に一つでもハマる人がいそうな内容なので書いておきます。

最近(ようやく)本格的にRedisをいじり始めて、使い勝手の良さと可能性のインパクトにやられてるんですけど。

redis-cliを触ってみる

入門 : Redis のデータ構造と概念 — Redis Documentation (Japanese Translation)

> set mykey somevalue
OK
> get mykey
"somevalue"
> del mykey
(integer) 1
> get mykey
(nil)

分かりやすいなー。キャッシュ的な使用期限ってどうやって設定するんだっけ。

SETEX – Redis

set mykey somevalue
OK
> expire mykey 5
(integer) 1
> ttl mykey
(integer) 2
> ttl mykey
(integer) 1
> ttl mykey
(integer) -2
> get mykey
(nil)

なるほど、設定した後にEXPIREコマンドでキーを指定して行うのか。

SETEX – Redis

> setex mykey 5 somevalue
OK
> ttl mykey
(integer) 2
> ttl mykey
(integer) 1
> ttl mykey
(integer) -2

なるほど、SETEXコマンドだと1回で設定できるのか。

………ハッシュ型の値の期限付きってどうやって設定するんだ? HSETやHMSETには○○EXみたいなやつとかオプションとか無いんだけど?

> HMSET myhash field1 "Hello" field2 "World"
OK
> HGETALL myhash
1) "field1"
2) "Hello"
3) "field2"
4) "World"
> ttl myhash
(integer) -1
> expire myhash 5
(integer) 1
> ttl myhash
(integer) 2
> ttl myhash
(integer) 1
> ttl myhash
(integer) -2    

あー、EXPIREコマンドはハッシュ型にも効くのか。

phpredisでやってみる

phpredis/phpredis · GitHub

phpredisにも hMSet あるのか。使ってみるか。

$redis->hMset('user:1', array('name' => 'Joe', 'salary' => 2000));

設定した後にExpireすれば期限付くだろう。

$redis->expire('user:1', 5);

> ttl user:1
(integer) -1

え!?!? 効いてない!?!? ナンデ???

(しばらく色々試す)

set した後に expire した場合は有効で、文字列型には setEx も用意されてるのに、ハッシュ型には期限を設定する手段は無いのか…??? そんなわけないよな………。

(しばらく色々探す)

GitHubのIssueにすら見当たらないので気分が悪くなる)

ソースコードを読もうと思いつくがガッツリしたCだったので断念する)

(ググり続けてたら、たまたまphpredisを使ったUtilライブラリを見つける)

ktty1220/php-redisutil · GitHub

f:id:Mint0A0yama:20150223003714p:plain

…あれ? やっぱりハッシュ型でも期限設定できるのか。 ソースコード見てみよう。。

php-redisutil/RedisUtil.php at master · ktty1220/php-redisutil · GitHub

(省略)
case 'hash':
  $multi = $this->connection->multi();
  foreach ($value as $k => $v) {
    $multi->hSet((string) $key, (string) $k, (string) $v);
  }
  $result = $multi->exec();
  break;
}
(省略)
if (!is_null($result) && $expire > 0) {
  $this->connection->expire((string) $key, $expire);
}

………… multi() / exec() のトランザクションではさんで、foreachで回しながらhSet使ってる……。 ………hMSet使ってないんかい………。

半信半疑で同じような処理で書いてみたらしっかり期限設定されてました。何なんだ。