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

このブログ記事について

このページは、Masahiro Naganoが2012年11月27日 10:14に書いたブログ記事です。

ひとつ前のブログ記事は「isucon2 を開催しました。あるいは、優勝組の5倍のスコアを出す方法」です。

次のブログ記事は「DBI->connect 時に使う鉄板オプションを教えて!」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

ウェブページ

OpenID対応しています OpenIDについて
Powered by Movable Type 4.27-ja