2010年 9月 9日 はてなブックマーク -
タグ: #memcache

安全なincrement

現在のmemcachedの最新バージョンである1.4.5ではマルチスレッド動作時にincrコマンドが正しく行われないバグがあることが知られ ています。incrコマンドを繰り返すと数値の繰り上がりにより桁数が増えます。桁数が変わるとキャッシュオブジェクトのサイズが変わ り,memcached内部のスラブの移動が必要となります。その際の動作がスレッドセーフではないため,スラブ移動中にインクリメントした情報が失われ ることがあります。

Issue 127: incr/decr operations are not thread safe.
http://code.google.com/p/memcached/issues/detail?id=127

バッドノウハウですが,incrコマンドを発行する際に十分な大きなスラブにデータが保存されるように細工することで,現在のmemcachedのバージョンでも問題を回避できます。

sub counter {
    my $self = shift;
    my $key = shift;
    my $result = $memd->incr($key, @_);  -----(1)
    if ( defined $result && ! $result ) {
        my $init = shift || 1;
        $memd->add($key, sprintf("%-20d", 0), @_ );  -----(2)
        $result = $memd->incr($key, $init, @_ );
    }
    $result;
}

上記のコードではmemcachedのincrメソッドを利用してカウンターを実装しています。まず(1)でincrを実行し,値が取得できなけれ ば,(2)で初期値をmemcachedに保存します。その際に,空白を入れて全部で20文字のキャッシュオブジェクトを生成します。20文字あれば2の 64乗までの数値が全て入るため,どんなにincrを繰り返してもキャッシュオブジェクトのサイズが変わらないので,memcachedサーバ上のスラブ が移動することがなくなり,バグを回避できます。

memcachedの活用と運用 実践編:第4回 memcachedを快適に利用するTips集 |gihyo.jp … 技術評論社

1年前 | | 2010年 9月 9日 | このエントリーを含むはてなブックマーク