今回は、1.4になってアップデートされた新機能を中心に紹介します。
memcachedとは?
memcachedとは、主にデータベースへの負荷を下げ、かつWebアプリケーションのスケーラビリティをコストパフォーマンス良く向上させる高性能な分散キャッシュサーバです。memcachedの基本や概要に関しては、以前ミクシィ運用グループの長野と執筆した「memcachedを知り尽くす」をご覧ください。
memcached 1.4の特徴
1.4、5つの特徴
memcached 1.4の大きなニュースの1つはバイナリプロトコルの正式導入です。また、他にも色々と嬉しい機能や改修が施されています。詳しくは1.4のリリースノートに記述されていますが、要約すると以下の5点が上げられます。
- バイナリプロトコルの正式導入
- パフォーマンス向上
- 統計システムの強化
- 報告されたバグの修正
- テストの強化
入手先
memcached 1.4は以下のURLから入手できます。
それでは、先の5つの特徴のうち、バイナリプロトコル関連の話題についてさらに詳しく説明します。
バイナリプロトコルとは?
通常、人間がコミュニケーションを取る際、意思を表現するために使うものが「自然言語」です。コンピュータは、この自然言語をそのまま理解することはできず、自然言語を何らかの標準・ルールに沿ってエンコードし、根本的には2進数に変換することで扱えるようになります。この2進数のデータが「バイナリ」と呼ばれるものです。
一方、プロトコルとは「会話のルール」に当たるものです。たとえば、私たちの日常生活で、「醤油を取ってください」というメッセージに対して、メッセージを受けた相手が醤油を取ってくれるやりとりが成立するのは、受け答えの基本概念があるためであり、この基本概念、すなわちルールの部分が、プロトコルに当たります。
コンピュータにおいて、メッセージのやりとりを実現するため、または失敗した場合に失敗であることを認識するために必要な明確なルール・手順の集まりのことを「プロトコル」と呼びます。
したがって、バイナリプロトコルとはバイナリでコンピュータ同士がやりとりを確実に行うための手段を意味します(曖昧なやりとりは存在しません)。ただし、すべてのバイト列の表現が共通ではないため、ソフトウェア設計者や開発者は、実行環境の記憶装置上で展開されるバイトの順番(これをEndianess/Byte Orderと呼ぶ) などを意識する必要があります。
memcachedのバイナリプロトコルでは、ネットワーク技術で標準的なNetwork Byte Order (big endian)を採用しています。
コンピュータがバイナリプロトコルを喜ぶ理由
計算コストの軽減
テキストデータとは、人間の自然言語における文字に相当するものです。テキストデータによるリクエストを受けたコンピュータは、まずリクエストを内部で理解できるようにテキストデータの意味を文字列処理で解析し、そこに含まれた情報を扱えるようにします(これを一般的にパースと呼びます)。
ここで、バイナリで構築されたリクエストを受信した場合を想定してみます。前述の通り、コンピュータがテキストデータを認識するにはコンピュータ内部での変換処理が必要となりますが、バイナリであれば直接扱うことが出来るため、文字列処理を行うコストを削減できます。
一般的に、リクエストを頻繁に受けないソフトウェアであれば、こういった処理部分に関しての性能向上のインパクトは小さいですが、memcachedのように並走して秒間何万ものリクエストを受けうるソフトウェアでは、1つ1つの計算量の減少により消費電力の軽減やスループット向上につながります。
拡張性の確保
また、新たなバイナリプロトコルの利点として、拡張が容易である点があります。なぜなら、バイナリプロトコルの場合、プロトコルメッセージ内のメッセージフィールドを自由に拡張できるからです。もちろん厳密に言えば、テキストプロトコルでも設計次第で拡張性に優れた仕様を作ることが可能ですが、memcachedの実装面においてはバイナリ処理のほうが容易です。この拡張性もバイナリプロトコルが開発された理由の1つであり、次回にバイナリプロトコル特有の機能をご紹介いたします。
バイナリプロトコルの注意点
むろん、バイナリプロトコルは良いことばかりではなく、人間が理解しづらいという注意点があります(とくに手動でのデバッグが面倒な点など)。
この他、memcachedバイナリプロトコルの詳しい仕様については、次回にご紹介いたします。
テキストプロトコルも話せるバイリンガル
memcached 1.4から正式にバイナリプロトコルが導入されましたが、今までのテキストプロトコルとの互換性は失っていません。したがって、プロダクションで導入しているmemcachedを最新版にアップデートしてもアプリケーションが壊れることはありません。注意点としては、以前のステーブルシリーズ(1.2)まで可能であった、deleteコマンドに秒間を表す整数、もしくはUNIX timeを追加することにより、その間は削除したキーに対してaddとreplaceコマンドを無効にするという機能が削減されました。
現代のハードウェアにより適したコード
続いて、ハードウェアの観点から見たmemcahed 1.4について解説します。
最近では、少し古いと呼ばれる一般ハードウェアでもコアが2つ搭載されています。旧シリーズのmemcachedでは、ビルド時にマルチスレッドのビルドを指定することができたのですが、時代の流れにのって、1.3の開発シリーズからデフォルトでマルチスレッドのビルドが行われるようになりました。
SMPアーキテクチャを効率的に利用するためには、ハードウェアの進化に頼ることではなく、きちんとしたソフトウェアデザインを行うことが重要です。そのため、並列プログラミングでは、グローバル変数の利用(厳密には更新)を避け、ロックの粒度をなるべく細かく、またはロックレスな設計をすることが重要なのです。
さて、初代memcachedはシングルスレッドの設計を基に開発されており、マルチスレッドビルドが可能になったのは、実はつい最近のことでした(2007年5月リリースの1.2.2より)。つまり、マルチスレッド化が後付けだったこともあり、memcachedの中では粒度の大きいグローバルロックが複数使われているため、現状のmemcachedはマルチコアのマシンではスケールしづらいという課題がありました。
今回の1.4では、複数あるロックの中で、stats(統計)情報を守っていたstats lockが排除されました。このstats情報の更新はほぼすべてのアクションに対して行われるものなので、memcachedがモダンハードウェアでスケールするための弊害の1つでしたが、これが解消されたことになります。
このロックを排除するソリューションは、Facebook社が自社用に改造したブランチを参考にしており、統計情報を各スレッドに持たせ、書き込みをロックレスにし、stats情報の要求がクライアントから送られた時のみ、statsの更新処理をブロックするというものです。
それでも、memcachedにはハッシュテーブルの更新を守るcache_lockなどの粒度が大きいグローバルロックが存在します。現在コミュニティ内では、cache_lockを不要にするために各スレッドにハッシュテーブルを持たせるなどの実験が行われており、今後まだまだ改善されていく予定です。
長い道のり
バイナリプロトコルの提案は2007年に行われ、Yahoo! Inc.で開催されたmemcached Hackathonで本格的な仕様策定がはじまりました。その後、Facebook、MySQL、Sun Microsystemsにて開催されたHackathonで議論が続き、開発用シリーズとしてmemcached 1.3(コミュニティの開発ブランチ)が誕生しました。そういった背景があり、バイナリプロトコルの導入はリリースまで2年かかったプロジェクトなのです。
次回予告
今回は、1.4の特徴として、バイナリプロトコルおよび現代ハードウェアを意識したソースコード、その開発背景について紹介しました。次回は、バイナリプロトコルの詳細な仕様の解説やクライアントライブラリやLLを使ったmemcachedの扱い方を紹介します。