memcachedのキャッシュキーにsha1やmd5のhash値を使うとtcpdumpや解析ツールで覗きにくくなるので、cacheには出来るだけわかりやすい名前をつけて下さい。というハナシ
下のようなコードのように
sub cache {
state $cache = Cache::Memcached::Fast->new({
namespace => 'db:',
});
}
sub key {
my ($self,$key) = @_;
sha1_hex($key);
}
sub cached_member {
my ($self, $member_id) = @_;
my $key = $self->key('member:'.$member_id);
my $member = $self->cache->get($key);
if ( !$member ) {
#DBから取得
}
$member;
}
sub cached_foo {
my ($self, $member_id) = @_;
my $key = $self->key('foo:'.$member_id);
my $foo = $self->cache->get($key);
if ( !$foo ) {
#DBから取得
}
$fooo;
}
全てのキーをsha1_hexでhash化してしまうと、全てのキーが
[0-9a-f]{40}
に統一されてしまい、解析ツールでみてもどれがどのキャッシュだか分からなくなってしまいます
例えば tcpdumpとpt-query-digestをつかった解析
$ sudo tcpdump -s 65535 -x -nn -q -tttt -i any -c 50000 port 11211 > /tmp/tcpdump.txt
$ perl ./pt-query-digest --type memcached /tmp/tcpdump.txt
以下がその一部
# Query 1: 17.17 QPS, 0.02x concurrency, ID 0x47FBFB3C523D96F9 at byte 4709526
# This item is included in the report because it matches --limit.
# Scores: Apdex = 1.00 [1.0], V/M = 0.00
# Query_time sparkline: | .^-_ |
# Time range: 2012-11-27 00:24:21.435633 to 00:24:32.733516
# Attribute pct total min max avg 95% stddev median
# ============ === ======= ======= ======= ======= ======= ======= =======
# Count 28 194
# Exec time 56 218ms 30us 23ms 1ms 4ms 2ms 490us
# Query size 67 3.04M 0 50.26k 16.06k 40.32k 14.86k 15.96k
# Boolean:
# Memc error 1% yes, 98% no
# Memc get 100% yes, 0% no
# Memc miss 1% yes, 98% no
# String:
# Hosts 10.x.x.x (80/41%), 10.x.x.x (30/15%)... 5 more
# key print db:?
# Query_time distribution
# 1us
# 10us ############################
# 100us ################################################################
# 1ms #########################################
# 10ms #
# 100ms
# 1s
# 10s+
get db:237c9527d4fae433391649ee6bdc92c8bfdb2624
注目するのは「key print」の行。全部、「db:?」でまとめられてしまうので、何のキャッシュを取得しようとしているのか分からなくなってしまい、キャッシュの取得に無駄がないかなど調査が不能になります。
memcachedのkeyにhash値を使うのはおそらく、memcached injectionを避けるためだと予想するのですが、それならば、URI escapeをするだけで十分です。その上でescape後のkeyの長さが250文字を超えるようであれば、仕方なくhash値を使うという実装の方がオススメです
use URI::Escape;
sub key {
my ($self,$key) = @_;
$key = uri_escape($key,"\x00-\x20\x7f-\xff");
if ( length($key) > 200 ) { #namespace分の余裕
$key = sha1_hex($key);
}
$key
}
この辺のモジュールを使うといろいろ面倒をみてくれます
Happy memcache:D