Facebookの数千台規模のmemcached運用について

Linuxのブロックデバイスレベルで実現するrsyncより高速な差分バックアップについて - ゆううきブログの続きとして、Facebook の memcached 運用に関する論文を読んだ。 タイトルなどは以下の通り。 NSDI はネットワークシステムに関する(多分)準トップレベルのカンファレンス。

  • Scaling Memcache at Facebook

Facebook のキャッシュシステムがどのようにスケールしてきたか、各スケール規模の勘所は何かについて書かれた論文だった。 内容はかなり盛りだくさんで、基本的なデータベースクエリキャッシュ戦略から、マルチリージョン分散の話まで多岐に渡る。 memcached に依存しない話も多いので、memcached というよりは、超大規模キャッシュシステムの運用例として読むのがよさそう。

論文概要

memcached はよく知られたシンプルなインメモリキャッシュシステムである。 論文では、memcached を基本単位として、世界最大のソーシャル・ネットワークを支える分散KVSをどのように構築し、スケールさせたかについて書かれている。 Facebook のキャッシュシステムは、秒間数十億リクエストを捌いていて、10億人を超えるユーザにリッチな体験を届けるために、数兆個のアイテムをキャッシュに保持している。

システムは、以下の4段階でスケールしてきた。 - 1. 数台のmemcachedサーバ - 2. 多数のmemcachedサーバを含むシングルmemcachedクラスタ - 3. マルチmemcachedクラスタ - 4. マルチリージョン

1. 数台のmemcachedサーバ

  • demand-filled look-aside cache 方式
  • 並列 memcache set 問題 (stale sets)
  • Thundering Herd 問題
  • memcache プロトコルの拡張 "leases"

2. シングルクラスタ

  • consistent-hashing
  • TCP incast congestion 問題
  • Layer 7でスライディングウィンドウでフロー制御
  • get リクエストは UDP にしてパケット減らす
  • 独自ルータを挟んでコネクション永続化

3. マルチクラスタ

  • フロントエンドクラスタ + ストレージクラスタ
  • 一貫性の保持
  • 全クラスタのキャッシュ無効化処理
  • SQL文に無効化キーを埋め込んでおきて、MySQLのコミットログをtailして埋め込みキーを無効化するデーモン

4. マルチリージョン

  • (フロントエンドクラスタ + ストレージクラスタ) x リージョン
  • リージョン間レプリ遅延を考慮して、キャッシュミス時にマスタDBをreadするかスレーブDBをreadするかマーカーをつける

Conclusion

  • キャッシュと永続ストレージを分離して、独立してスケールさせる
  • モニタリング、デバッギング、オペレーション効率を改善する機能はパフォーマンスと同じくらい重要
  • ロジックは stateless なクライアントに置くほうが混乱しない
  • システムは新機能の段階的なロールアウトとロールバックをサポートしなければならない
  • Simplicity is vital.

スライド

より具体的な内容はスライド参照。 相当はしょっているので、詳細な内容は論文参照。 はしょった内容については、後日ブログにするかも。

関連記事

感想

TCP incast問題を回避するために、TCPのスライディングウィンドウ的なロジックをアプリレイヤで実装していたりして、OSレイヤでの解決方法を大規模運用にあてはめてスケールさせているのが印象的だった。 仕事でそのロジックを実装するリソースを割けない、もしくはそもそもそんなスケール必要がないとかはあるにしても、話としては結構おもしろかった。 あと、memcached 自体には機能を追加せずに、クライアントサイドにロジックを入れていたのも気になるところだった。 Facebook はストレージにHBaseを使っている話 (The Underlying Technology of Messages)もあって、こっちはミドルウェアにロジックをもたせてたりするので、このへんの方針の違いも気になる。

関連記事にも載せてるけど、 https://www.facebook.com/publications で Facebook の出してる論文とか読めるので、いろいろ勉強になりそう。

ヘビーなGraphite運用について

"Monitoring Casual Talks #6"に参加して、「ヘビーなGraphite運用」についてしゃべってきた。 Graphite ここ数ヶ月ずっと運用してて、そこそこのリクエスト数さばけるようになるまでと冗長化の話をだいたいしてた。 Graphiteのパフォーマンス・チューニングで結構苦労してて、@sonots さんが発表されてた"GrowthForecast/RRDtool チューニング秘伝の書" がすごい参考になった。(Graphite(whisper) のデータ構造と RRdtool のデータ構造はよく似ている。) fadvise(2)とか知らなかった。 ぜひ試してみたい。

スライド

結構口頭で補足してた。Graphite 秘伝の書書きたい。

感想

今回の勉強会、かなり刺さる内容が揃っててよかった。 形式が30~100人くらいいて、数人の発表者がプレゼンするっていう感じじゃなくて、14人くらいで全員発表とかいう形式だったので、カジュアルに議論とかできてよかった。 あと、結構 Mackerel について言及していただいて関係者としては緊張感あった。 Nagios とか Zabbix の話は意外と少なめで Sensu とかあと、Docker のメトリクス収集とか、Auto Scale時のモニタリング方法とかの議論があって、みんなモダンなことにチャレンジにしててすごい。 また参加したい。

関係ないけど、今週 Docker 1.0 がリリースされて、Dockerそのもの + 周辺ツールが充実してきた感があるので、今回と同じような形式の Docker Casual とかあったらよさそう。

会場の提供/準備をしていただいた @takus さん、@sonotsさん ありがとうございました。

Mackerel を使ったサーバメトリクス可視化の背景っぽいやつ #可視化

可視化ツール現状確認会 on Zusaar

可視化ツール現状確認会で Mackerel-Based Server Metrics Visualization とかいう話をしました。 僕はアルバイト入社したときからサーバ管理ツールにずっと関わってて、周辺ツールとかもウォッチしてて、そういう流れで Mackerel がどういう位置づけにあるかみたいな話だったはず。

かつて自作社内サーバ管理ツールで、RRDtool の最悪の引数をURLクエリで互換するようなパーサ作ってたりして、異常な努力をしていましたが、ここ半年くらいで、モダンな Graphite とか Sensu をサーバ管理ツールと組み合わせようとしていて、気づいたら https://macekrel.io っていうサービスができてたという感じです。 Graphite と Sensu(Collectd) を導入しようとそれはそれで運用が思ったより面倒で、パフォーマンスがでないとかモニタリング用のサーバを用意したくないというようなことがあってかけた労力に見合わないという感じなら普通に Mackerel 使うと便利。 あと、サーバのIPアドレスとかホスト情報とサーバメトリクスビューが分散している場合(Munin と AWS consoleとか)に、統合管理するために Mackerel 使ってもらうのも便利。

ちなみに読み方はマケレルではなくてマカレル(英語読みはマッカレル?)っぽい。 なんでもいいけどとにかく RRDtool を使うべきではないと思います。

資料

軽くロードマップみたいなものも書かれています。 もうちょっと突っ込んだ使い方とか何ができるのかみたいな話は来週のモニカジで喋れたら良さそうです。

会場の提供、準備、運営をしていただいた Voyage Groupの皆様ありがとうございました。

インターネットの様子

DockerとS3を用いた、yum / apt リポジトリ作成・運用の継続的インテグレーション

Docker を用いた rpm / deb パッケージ作成の継続的インテグレーション - ゆううきブログ の続き。 前回は、rpm / deb パッケージを作るために、CentOS、Debianなど各種ディストリビューションを揃える手間をかけずに、Docker コンテナ上でパッケージングして、ついでに Jenkins で CI するみたいなことを書いた。

今回は、作成したパッケージを yum / apt リポジトリに登録して yum / apt コマンドでパッケージインストール/アップデートできるようになるまで継続的インテグレーションするという話。

問題点

  • yum / apt リポジトリ用の専用ホストを立てて、そこで apache とかで静的ファイルをホストするのはめんどくさい。
    • 特に、mackerel-agent みたいなユーザにインストールしてもらうパッケージの場合、リポジトリを公開しないといけなくて、冗長化とか面倒はさらに増える。
  • リポジトリ作成のために必要なメタファイル群を作成するために、createrepo や reprepro コマンドがインストールされた環境が必要となる。
    • OSX とかではインストールできない。(がんばったらできるのかもしれない)

Docker と S3 で解決

  • yum / apt リポジトリ用の専用ホストを立てて、そこで apache とかで静的ファイルをホストするのはめんどくさい。

前者については、S3 に静的ファイルをアップロードすることにより、サーバもたなくてよいので簡単。 手順は簡単で、S3のWebコンソールで適当にバケットを作って、createrepo または reprepro で作成したファイルをs3cmd とか aws-cli でバケットにアップロードする。 バケットには、bucket-name.s3.amazonaws.com. のようなエンドポイントがつくので、各ホストで リポジトリの設定を書くだけ。

さらに、Jenkins で master ブランチが更新されたときにパッケージの作成と同時に S3 にアップロードすることで、勝手にリポジトリに最新パッケージが入るので便利。今触ってるのは一般公開する代物なので、リリースは慎重に手でやってるけど、社内リポジトリとかならJenkinsで自動化したらよさそう)

  • リポジトリ作成のために必要なファイル群を作成するために、createrepo や reprepro コマンドがインストールされた環境が必要となる。

手元は OSX でも、Docker 上の各ディストリビューションでディストリ依存な createrepo や reprepro をインストール・実行できる。

ディレクトリ構成と Dockerfile

  • ディレクトリ構成 (yum)
tree -a
.
├── .s3cfg
├── Dockerfile
├── files
│   └── mackerel-agent-x.x.x.noarch.rpm
└── macros
  • ディレクトリ構成 (apt)

  • Dockerfile (yum)

# docker build -t 'hatena/mackerel/yum-repo' .
# docker run -t 'hatena/mackerel/yum-repo'

FROM centos
ENV PATH /usr/local/bin:/usr/sbin:/sbin:/usr/bin:/bin
RUN yum update -y
RUN rpm -ivh http://ftp.iij.ad.jp/pub/linux/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm
RUN yum install --enablerepo=epel -y createrepo s3cmd

RUN install -d -m 755 /centos/x86_64
ADD files /centos/x86_64/
RUN /usr/bin/createrepo --checksum sha /centos/x86_64

ADD .s3cfg /.s3cfg
WORKDIR /centos/
CMD /usr/bin/s3cmd -P sync . s3://yum.mackerel.io/centos/
  • Dockerfile (apt)
# docker build -t 'hatena/mackerel/apt-repo' .
# docker run -t 'hatena/mackerel/apt-repo'

FROM tatsuru/debian
ENV PATH /usr/local/bin:/usr/sbin:/sbin:/usr/bin:/bin
ENV DEBIAN_FRONTEND noninteractive

RUN apt-get -y update
RUN apt-get -y install reprepro s3cmd
RUN apt-get clean

RUN mkdir -p /deb
ADD files /deb/
WORKDIR /debian
RUN mkdir -p db dists pool
ADD conf /debian/conf
RUN reprepro includedeb mackerel /deb/*.deb
RUN reprepro export

ADD .s3cfg /.s3cfg
CMD /usr/bin/s3cmd -P sync . s3://apt.mackerel.io/debian/

リポジトリの設定

独自リポジトリなので、インストール先ホストではリポジトリを設定する必要がある。 yum / apt で、それぞれ次のように設定するとよい。

  • yum の場合

/etc/yum.repos.d/mackerel.repo

[mackerel]
name=mackerel-agent
baseurl=http://yum.mackerel.io/centos/\$basearch
  • apt の場合
echo "deb http://apt.mackerel.io/debian/ mackerel contrib" >> /etc/apt/sources.list.d/mackerel.list

所感

Docker または Vagrnat を使うと、いちいちディストリビューション環境用意しなくてよいし、余分なサーバをもたなくて済む。 これは、Virtualbox や VMware で仮想ホストを立ち上げても同じだけど、Docker や Vagrant は CLI で操作できてプログラマブル(特に Docker はREST APIがある)なので、自動化しやすい。 さらに、Docker なら毎回クリーンな環境からリポジトリを構築しやすいのでゴミが入りにくいというメリットがある。 (Vagrnat でもできるけど、壊して再構築するのに時間がかかる)

前にも書いたけど、Docker 使うと、今まで特別な環境でしかできなかったことを気軽に手元でできるようになったりする。 Docker が Immutable Infrastructure 専用の何かみたいに言われることがあって、結局まだそんなにうまく使えないよねみたいな話あるけど、用途はいろいろあると思う。

Linuxのブロックデバイスレベルで実現するrsyncより高速な差分バックアップについて

社内で論文輪読会みたいなことやってて、そこで紹介した論文の内容についてです。

最近、Graphite に保存しているデータのバックアップ(データ同期)に rsync 使ってて、かなり遅いので困ってた。 LISA っていう 大規模システム、sysadmin 系のカンファレンスがあって、ここから論文探してたら、ちょうど巨大データの高速バックアップの実装の話があったので読んでみた。

論文概要

dsync: Efficient Block-wise Synchronization of Multi-Gigabyte Binary Data - https://www.usenix.org/conference/lisa13/technical-sessions/presentation/knauth - Thomas Knauth and Christof Fetzer, Technische Universität Dresden - In Proceedings of the 27th Large Installation System Administration Conference (LISA ’13)

GB単位のデータだと、rsyncがとにかく遅い。 rsync はブロック分割されたデータのハッシュ値の比較により差分検知して、ネットワーク転送するデータ量をとにかく減らそうとしている。 その反面、同期させたいデータサイズに対してハッシュ値計算のCPU時間は線形に増加する。 さらに、ハッシュ値計算のために全データブロックを読み出す必要があり、I/Oコストも高い。 バックアップ時に、差分を事後計算しようとすると、どうしてもこうなる。 そこで発想を変えて、カーネルのブロックデバイスレベルで、更新のあったブロックを常に記録(トラッキング)しておき、バックアップ時にフラグのあったブロックだけを転送することにする。

発想自体はシンプルだけど、既存の device mapper の Snapshot 機能だけでは実現できなくて、パッチをあてる必要があったのがやや難点。 カーネルのメインラインに取り込まれてほしい。

実装はこちら。 https://bitbucket.org/tknauth/devicemapper/ Linuxカーネル 3.2 の device mapper モジュールにパッチを当てるような感じになってそう。

追記 2014/05/26 16:10

それ ZFS でできるよと DRBD でいいのでは系のコメントをいくつかいただきました。 ちなみに論文の本文には両者に関して言及があります。

"どうせブロックデバイス使うなら実績のあるDRBDでいいんじゃないかと思う。非同期モードで。" http://b.hatena.ne.jp/n314/20140526#bookmark-196769866

ZFS について

ブロックデバイスレベルで実現できてうれしい点は、ZFS など特殊なファイルシステムに依存しないことだと思います。 ext3 のような壊れにくいLinux環境で実績と運用ノウハウがある ファイルシステムを使いつつ、差分バックアップできるのは実運用上でうれしいことが結構あると思います。 あとは、ZFS で定期的に差分バックアップとるときに、スナップショット分のディスクサイズオーバヘッドが気になります。(これは論文にも比較データはないのでどれほどかわかりませんが) ちなみに dsync のオーバヘッドは、10 TiB データに対して、320 MiB 程度のようです。(ただしディスクではなくメモリオーバヘッド)

DRBD について

そもそも非同期モードだろうが同期モードだろうが、DRBD はオンラインなレプリケーションには使えても、定期バックアップに使うものではない気がします。 例えば、プライマリノードで、間違えて重要なファイルを rm してしまったときに、即座にセカンダリノードにその rm の結果が伝播してしまうので、データが壊れた時に復旧するためのバックアップ用途には向いてない気がします。

何か勘違いがありましたらご指摘いただけると幸いです。

スライド

Keynote のテンプレートは、Azusa にお世話になっています。

LISA の他の論文

LISA はオペレーションエンジニアにとって興味深い論文が結構ある。 一例をあげてみる。 今回のように実装が公開されてたいたりするので、あんまりアカデミック感がなくてよい。

所感

たまにサーバ管理ツールとか作ってて、サーバ負荷の未来予測とかサービス間のトラッフィク依存関係(AサービスがBサービスのDB引いてるとか)を可視化できたらいいねとか言ってたりしてた。 今回、LISAの論文眺めてたらちょうどそういうのあって驚きがあった。 研究の世界はできないことができるようになる系統の技術において先を行っていて、ブログとかウォッチしているだけでは追いつけないので、たまに論文もよみたい。

カーネルのI/Oシステム周りの知識に乏しいので、詳解Linuxカーネルを読みつつ知識を補填していた。

詳解 Linuxカーネル 第3版

詳解 Linuxカーネル 第3版

  • 作者: Daniel P. Bovet,Marco Cesati,高橋浩和,杉田由美子,清水正明,高杉昌督,平松雅巳,安井隆宏
  • 出版社/メーカー: オライリー・ジャパン
  • 発売日: 2007/02/26
  • メディア: 大型本
  • 購入: 9人 クリック: 269回
  • この商品を含むブログ (71件) を見る