2008年02月06日

memcached-1.2.4で追加されたコマンドのメモ

はてなブックマークに登録

なぜか最近になってまた動きが活発になってきた気がするmemcachedですが、ちょっと前(2007-12-06)にリリースされたmemcached 1.2.4からプロトコルコマンドが追加されました。

  • append
  • prepend
  • gets
  • cas

今回は、これら新しく追加されたコマンドについて、軽く説明してみたいと思います。
なお、クライアントライブラリが新コマンドに対応していたりいなかったりするので、今回はクライアントライブラリを使用せず、直接memcachedにつないで、プロトコルをしゃべって動作を確認したいと思います。(memcachedプロトコルは、doc/protocol.txtに詳しい解説がありますのであわせて読むといいと思います)

で、おしゃべるにはtelnetやncでもいいんですが、今回はsocatを使います。localhostの11211に繋ぎたい場合にこんな感じで実行すると、CRLFの変換や行編集や履歴参照もできちゃうすぐれものです。

$ socat READLINE,prompt='> ' TCP4:localhost:11211,crnl

append, prepend

既にデータがある場合に、データの末尾(append)や先頭(prepend)になにかをくっつけるコマンドです。
getしてsetすれば同じことはできるんですが、append, prependを使うと一息に(atomicに)できるのがミソです。

では実際に試してみましょう。
なにはともあれ、適当なデータをsetして、

> set foo 0 0 4
> val1
STORED

apeend、prependした後、getで確認してみます。元々の「val1」の前後に「PrePre」と「ApAp」がついたのが確認でできます。

> append foo 0 0 4
> ApAp
STORED

> prepend foo 0 0 6
> PrePre
STORED

> get foo
VALUE foo 0 14
PrePreval1ApAp
END

ちなみに、存在しないキーに対してappend、prependをすると、エラー(NOT_STORED)が返されます。

> append neeeyo 0 0 1
> X
NOT_STORED

gets, cas

次はgetsとcasです。
memcachedのMLでの初出は、2007-09-08に投稿されたCAS operationというメールじゃないかと思います。
「cas」という名前は、CPU命令のCAS (Compare-and-Swap) からきているんだと思います。(参考: http://en.wikipedia.org/wiki/Compare-and-swap, http://ja.wikipedia.org/wiki/コンペア・アンド・スワップ)
「gets」という名前の由来はわかりませんが、心の中では「ゲッツ!」と発音しています。

gets, casはどういうときに使うものかというと、データを更新する場合に使います。
例えば、こんな場合にどうしたらいいか考えてみましょう。

  • あるキーのデータをgetしたあとで、新しいデータを(同じキーに)setしたい。
  • でももし、getとsetの間で他の人が同じキーを変更した場合はエラーにしたい。

setする直前に再度getして値が変わっていないか確認するという方法を思いつくかもしれませんが、再度getとsetの間にだれかに割り込まれる可能性があるので、それを排除するには再度getの後でsetする直前に再々度getする必要があり、再々度getとsetの間にだれかに割り込まれる可能性があるので、それを排除するには再々度getの後でsetする直前に再々々度getする必要が(ryとなり、きりがありません。

そこでgets, casの出番なんですが、説明するより実際に試してみた方が理解がはやいと思うのでいきます。

まずはgets。getとだいたい出力は同じなんですが、バイト数(下の例だと「14」)の後に、7という数値がついています。これがcas id呼ばれるものです。

> gets foo
VALUE foo 0 14 7
PrePreval1ApAp
END

次にcasなんですが、casは「指定したcas idが現在のcas idと一致するときのみ実行されるreplace」という説明でだいたいあってると思います。

> cas foo 0 0 4 6  # 最後の「6」がcas idの指定。でも、
> val6             # getsで確認したcas id(= 7)と異なるので、
EXISTS             # EXISTSという応答が返り、

> get foo          # データは変更されない。
VALUE foo 0 14
PrePreval1ApAp
END

> cas foo 0 0 4 99 # 同様に、より大きな数値をcas idと指定しても
> val9             # データは更新されない。
EXISTS

> cas foo 0 0 4 7  # getsで得たcas id(= 7)を指定すると、
> val7
STORED             # EXISTSではなくSTOREDが返され、

> get foo
VALUE foo 0 4
val7               # データは更新される。
END
> gets foo         # 再度gets
VALUE foo 0 4 8
val7
END

〜ここで別クライアントがキー:fooに対してデータ変更を行ったとする〜

> cas foo 0 0 4 8
> val8
EXISTS             # 別クライアントが変更したことにより、
                   # 最新のcas idが変わったため
                   # STOREDではなくEXISTSが返される。

つまり、データを得るときにgetではなくgets(ゲッツ!)を使い、データに加えてcas idも覚えておく。後、データを更新するときにはset,add,replaceではなくcasを使い、getsのときに得たcas idを指定する。STOREDが返れば更新成功、EXISTSが返った場合は、途中でだれかがデータを変更した、ということになります。


(ひ)
klab_gijutsu2 at 08:00│Comments(0)TrackBack(0)

トラックバックURL

この記事にコメントする

名前:
URL:
  情報を記憶: 評価: 顔   
 
 
 
Blog内検索
Archives
このブログについて
DSASとは、KLab が構築し運用しているコンテンツサービス用のLinuxベースのインフラです。現在5ヶ所のデータセンタにて構築し、運用していますが、我々はDSASをより使いやすく、より安全に、そしてより省力で運用できることを目指して、日々改良に勤しんでいます。
このブログでは、そんな DSAS で使っている技術の紹介や、実験してみた結果の報告、トラブルに巻き込まれた時の経験談など、広く深く、色々な話題を織りまぜて紹介していきたいと思います。
最新コメント