Redis の expire の仕様
# 追記 Redis2.6.10 で試したら意図通り取得出来た。
Python で Redis を使用していた時にあたった問題。
# 2.1.3 以降では発生しないよう。
こんなコード。
#!/usr/bin/env python # -*- coding: utf-8 -*- from redis import Redis client = Redis() client.select(4) client.flushdb() client.rpush('a', 'x') client.rpush('a', 'y') client.rpush('a', 'z') result = client.lrange('a', 0, -1) print result # ['x', 'y', 'z'] # クリア client.flushdb() client.rpush('a', 'x') client.rpush('a', 'y') client.rpush('a', 'z') client.expire('a', 86400) result = client.lrange('a', 0, -1) print result # ['x', 'y', 'z'] # クリア client.flushdb() client.rpush('a', 'x') client.expire('a', 86400) client.rpush('a', 'y') client.expire('a', 86400) client.rpush('a', 'z') client.expire('a', 86400) result = client.lrange('a', 0, -1) print result # ['z']
一番最後の所のように毎回キーに対して expire を設定した際に、それまでの値が消えてしまった。
最初 Python のライブラリのバグかと思ったが、redis-cli でも再現した。
$ redis-cli redis> select 4 OK redis> rpush a x (integer) 1 redis> rpush a y (integer) 2 redis> rpush a z (integer) 3 redis> lrange a 0 -1 1. "x" 2. "y" 3. "z" redis> flushdb OK redis> rpush a x (integer) 1 redis> rpush a y (integer) 2 redis> rpush a z (integer) 3 redis> expire a 86400 (integer) 1 redis> lrange a 0 -1 1. "x" 2. "y" 3. "z" redis> flushdb OK redis> rpush a x (integer) 1 redis> expire a 86400 (integer) 1 redis> rpush a y (integer) 1 redis> expire a 86400 (integer) 1 redis> rpush a z (integer) 1 redis> expire a 86400 (integer) 1 redis> lrange a 0 -1 1. "z"
揮発性のキーに対応する値に対して修正を行うような LPUSH, LSET などの操作に対しては特別なセマンティクスがあります。基本的に揮発性のキーは書き込みの対象となった場合は破壊されます。
全データ型対応の操作 — redis 2.0.3 documentation
orz
既にキーが登録してあったら、expire を付けないように回避した。