Memcached 公式ドキュメント まとめ

Redis本を執筆しました。Memcachedとの詳細な比較も付録で取り上げていますので、こちらも是非合わせてご覧ください。

———————————————————————————————————————————————————

memcached のWikiを一読してまとめてみました (2018/05/13 時点)

Memcached

  • 公式ページ: https://memcached.org/
  • Wiki: https://github.com/memcached/memcached/wiki

別途、Memcachedの機能のまとめ記事等は以下のURLを参照いただければと存じます。

About

Overview

  • URL: https://github.com/memcached/memcached/wiki/Overview

  • 設計哲学

    • Simple Key/Value Store: データを事前にシリアライズする必要性
    • Logic Half in Client, Half in Server: どのサーバを選ぶかは、クライアントが決める
    • Servers are Disconnected From Each Other: サーバは互いに独立して同期をしない
    • O(1): 遅いマシン上でもクエリーは1ms以下
    • Forgetting is a Feature: LRU
    • Cache Invalidation: クライアントはサーバへ直接データを無効化。全ホストにブロードキャストといったことはしない。

Release Notes

  • URL: https://github.com/memcached/memcached/wiki/ReleaseNotes

Communication, Mailing List

  • URL: https://groups.google.com/forum/#!forum/memcached

Ancient ML Archives

  • URL: http://lists.danga.com/pipermail/memcached/

IRC: – irc.freenode.net #memcached

Want to contribute to this wiki? Submit a PR!

Getting Started

Installing

  • URL: https://github.com/memcached/memcached/wiki/Install

  • バグがあった場合は、まず最新版へアップグレード

  • Memcachedは libevent 依存なので、インストールしておく

  • インストール方法

# パッケージから取得
## Debian, Ubuntu
$ apt-get install libevent-dev
$ apt-get install memcached

## Redhat/Fedora
$ yum install libevent-devel
$ yum install memcached

# ソースからビルド
wget https://memcached.org/latest
[you might need to rename the file]
tar -zxf memcached-1.x.x.tar.gz
cd memcached-1.x.x
./configure --prefix=/usr/local/memcached
make && make test && sudo make install

Tutorial (in fun story form!)

  • URL: https://github.com/memcached/memcached/wiki/TutorialCachingStory
  • データベースが負荷が高くエラーが出ているのでmemcachedの導入。
  • Memcachedをアップグレードのためにシャットダウンをするときは、DBの負荷が大丈夫か気にかける
$MEMCACHE_SERVERS = array(
    "10.1.1.1", //web1
    "10.1.1.2", //web2
    "10.1.1.3", //web3
);

:
:

$memcache = new Memcache();
foreach($MEMCACHE_SERVERS as $server){
    $memcache->addServer ( $server );
}

:
:

$huge_data_for_front_page = $memcache->get("huge_data_for_front_page");
if($huge_data_for_front_page === false){
    $huge_data_for_front_page = array();
    $sql = "SELECT * FROM hugetable WHERE timestamp > lastweek ORDER BY timestamp ASC LIMIT 50000";
    $res = mysql_query($sql, $mysql_connection);
    while($rec = mysql_fetch_assoc($res)){
        $huge_data_for_front_page[] = $rec;
    }
    // cache for 10 minutes
    $memcache->set("huge_data_for_front_page", $huge_data_for_front_page, 0, 600);
}

// use $huge_data_for_front_page how you please
### Hardware Recommendations

Hardware Recommendations

  • URL: https://github.com/memcached/memcached/wiki/Hardware

  • CPU Requirements

    • Memcachedは普通CPUをあまり使わない。
    • マルチスレッドで、デフォルトでは4ワーカースレッド
  • RAM Requirements

    • 複数のホストのメモリセクションをすべて合わせて考える。
    • すべてのホストを同じ量のメモリが利用可能なものにすると、重みなど気にしなくても良くなる。
    • メモリを過剰に割り当てるとスワップが発生するので、チューニングが必要になる
    • RAMのスピードはそこまで高速にしても効果はなさそう
    • 複数のNUMAノードにマナガって稼働させると、パフォーマンスが大幅に下がるので、numactl 等でNUMAノードにつき、1インスタンスを稼働させるようにする
  • ハードウェアレイアウト

    • Webサーバ上でMemcachedを稼働させる場合 : 残ったメモリに少し余裕を持たせて割り振る
    • データベース上にMemcachedを稼働させる場合 : あまり良くない。DBのメモリ上にインデックスやデータがある方がメリットが大きい
    • Memcached 専有 : 他のプログラムを考えなくてもよく、スケールもし易い
  • キャパシティプランニング : アプリケーション問題時に、サーバが何台ロストしても大丈夫か見積もっておくことが大事

  • ネットワーク

    • 項目の大きさの平均サイズによるが、アプリケーションはできるだけ
    • 多くのデプロイでは、それほど必要ないかも知れないが、大きい帯域幅や10gigabit ethernetが必要な状況であれば効果がある可能性がある。

Configuration

Configuring a Server

  • URL: https://github.com/memcached/memcached/wiki/ConfiguringServer

  • Commandline Arguments

    • 最新のドキュメントは、memcached -h や man memcached を参照
  • Init Scripts : scripts/ ディレクトリ以下

  • Multiple Instances

  • Networking : リスナー → TCP, UDP, UNIXソケット

  • Connection Limit

    • デフォルト 1024
    • コネクション不足は、stats コマンドの listen_disabled_num が0かそれに近いかを確認する
  • Threading

    • libevent を使用
    • ワーカースレッドによるモデルで各スレッドが並行した接続を扱う
    • デフォルトでは、4つのスレッドが割り当てられているが、激しく稼働させない限り、いじらないほうが良い。
  • Inspecting Running Configuration

$ echo "stats settings" | nc localhost 11211
STAT maxbytes 67108864
STAT maxconns 1024
STAT tcpport 11211
STAT udpport 11211
STAT inter NULL
STAT verbosity 0
STAT oldest 0
STAT evictions on
STAT domain_socket NULL
STAT umask 700
STAT growth_factor 1.25
STAT chunk_size 48
STAT num_threads 4
STAT stat_key_prefix :
STAT detail_enabled no
STAT reqs_per_event 20
STAT cas_enabled yes
STAT tcp_backlog 1024
STAT binding_protocol auto-negotiate
STAT auth_enabled_sasl no
STAT item_size_max 1048576
END

Configuring a Client

  • URL: https://github.com/memcached/memcached/wiki/ConfiguringClient

  • Common Client Configurables

    • Hashing
      • 全てのクライアントは、サーバーに渡って、ハッシュキーの手法を持っているが、クライアント間で互換性はない。
      • Perl の Cache::Memcached に対して PHP クライアントを使用しても、動作しない
    • Consistent Hashing
      • サーバの数を変更すると、通常40%以上のデータ移動が必要だが、10%未満の移動に抑えられる。
    • Configuring Servers Consistently
      • 設定ファイルの同期には、Puppet/Chef/rsync/whateverを使うと良い
    • "Weighting"
      • より大きなサーバがある場合は、重みをつけられる
    • Failure, or Failover
      • サーバが落ちた時、リストの次のサーバに再割当てが試みられる。
    • Compression
      • 圧縮していると、メモリ節約やレイテンシー減少が期待できる
      • 多くのクライアントは、アイテムの一定サイズ以上の閾値での圧縮する機能がある
    • Managing Connection Objects
      • memcached へ接続する度に初期化していたら、接続がリークするかも

External flash storage

  • URL: https://github.com/memcached/memcached/wiki/Extstore

  • memcached 1.5.4 以上で、ビルド時に ./configure –enable-extstore が必要

  • 複数インスタンスが有り、大きな値を持つ時に外部フラッシュストレージを使用

  • stats や stats slabs コマンドで、大きな chunk_size を持ったスラブクラスが、比較的高い total_pages を持っており、evictions が見られる時に有効

  • ./configure --enable-extstore && make && make test && sudo make install でビルド

  • チューニングは余裕があれば特にしない。stats コマンドの結果を監視し、ディスクにどれだけ監視されているかを見る

  • Primary tradeoffs

    • LRUの末尾からアイテムは取り出されるので、再び取り出す時、フラッシュがヒットしにくい
    • 書き込みがフラッシュより早いと、ストレージへのフラッシュより先に、LRUの末尾からevictされる
  • Performance expectations

    • 多くの操作でフラッシュが必要ない
    • フラッシュされたアイテムのみ読み込み、書き込みはLRUの末尾から。既存のフラッシュされたアイテムを圧縮し、ストレージへタッチ
    • LRU の終わりに近づいているものはヒットしにくくなる。キャッシュミスを減らすことに役立つ
    • 大きなアイテムのみフラッシュできる。アイテムサイズが小さいと、ネットワークの帯域の前にフラッシュデバイスが飽和する
  • 監視すべき項目

    • evictions
    • stats items コマンドで、高いスラブクラスで、とても低い age がないか。少ないアイテムで多くのメモリを使用している可能性
    • ディスクへの書き込みの多さ。レイテンシーのスパイク。ディスクのハング
    • ディスクへの書き込みの多さ。RAMを追加したり、圧縮設定を入れる
  • Page buckets

    • ストレージの page は、複数の buckets へ分割される
      • 特殊ではない全てのアイテム
      • 512k 以上の大きなアイテム
      • 圧縮アイテム
      • TTLの短いアイテム
  • Tuning options

    • –help や stats settings でデフォルト設定確認

    • ext_page_size, デフォルト 64M

    • ext_wbuf_size, デフォルト 8M

    • ext_threads, デフォルト 1

    • ext_item_size, デフォルト 512バイト

    • ext_low_ttl

    • 今後変更される可能性があり、バケットを多くするほうが効果的

      • ext_max_frag
      • ext_drop_unread
      • ext_compact_under
      • ext_drop_under
      • ext_recache_rate
  • Runtime tunables

    • extstore [command] [optional value].
    • command: item_size item_age low_ttl recache_rate compact_under drop_under max_frag drop_unread
  • Very high level detail

    • 1つのファイルは、一定サイズ(デフォルト 64M)のいくつかの論理ページへ分割され、Writeバッファ(8M以上)がページへ後ほどフラッシュされるオブジェクトを保存するのに使われる。
    • IOスレッドは、非同期にWriteバッファへフラッシュされ、異アイテムを読み込み直す
    • アイテムは、キーと小さいヘッダー(フラッシュで生き残るデータを扱う)でハッシュテーブルに残される。
    • ストレージエンジンヒャ、バージョン数を返納することでページをリサイクルする
  • Technical Breakdown

    • Goals

      • 大きな値がフラッシュできる。小さいものはRAM上のまま
      • 1つのキーを受けるのに1つのread
      • 非同期なドライブへのバッチ書き込み
      • 主なハッシュテーブルは管理権限
      • 新たなアイテムの書き込みは、フラッシュデバイスをブロックしない
      • ストレージからのデータをforget/evictは、ドライブを使ってはいけない
    • Assumptions

      • データのTTLが長い
      • 小さいアイテムのオーバーヘッドが、保存よりメリットがある
      • 小さいアイテムのオーバーヘッドが、ミスより良い
      • データの少数が頻繁にアクセスされる
  • Architecture

               THREADS            +            STRUCTURES
 +----------------------+         |
 |-----------|          |         |     +----------+
+------+  +--v-----+ +--v-----+   |     |hash table|
|listen|  |worker 1| |worker 2|   |     +----------+
+------+  +--------+ +--------+   |
                        +--------->     +---+
                                  |     |LRU|
+--------------+                  |     +---+
|lru maintainer+------------------>
+--------------+                  |     +--------------+
                                  |     |slab allocator|
+-----------+                     |     +--------------+
|lru crawler+--------------------->
+-----------+                     |
                                  |
+---------------+                 |
|slab page mover+----------------->
+---------------+                 |
                                  +

フラッシュの場合は、storage が LRU maintainer と似た働きをする。compaction も IO に作用する。

  • How an item flows to storage:
+--------+
|LRU tail|
+--------+
  |
  | * Is the item large?               +------>
  |                                    |
  | * Is memory low?                   | Once written to buffer:
  |                                    |
  | * Is a write buffer available?     | * Allocate new small item
  |                                    |
  |   +------------+                   | * Copy key+metadata to new item
  +--->write buffer+-------------------+ * Also contains pointer to flash:
      +------------+                       [page, offset, version]

    * IF the write buffer was full:      * Replace original with small item

     +------------+     +---------+
     |write buffer+----->IO thread|
     +------------+     +---------+

    * All writes wait during flush
  • The lifetime of a storage page
    • 1ページ辺り、デフォルト64MB。
    • 書き込みはバッファIOを使用
    • メモリストアのアイテムヘッダーには、[PAGE ID, OFFSET IN PAGE, VERSION NUMBER]
OPEN      [BUCKETS]     FULL

          +-------+
[P9]<-----+DEFAULT+---->[P0,P1,P2,P5,P6]
          +-------+

          +---------+
[P10]<----+COMPACTED+-->[P3,P4]
          +---------+

          +-------+
[P11]<----+LOW TTL+---->[P7,P8]
          +-------+


FREE: [P12,P13,...]

Usage

Clients

  • URL: https://github.com/memcached/memcached/wiki/Clients
  • Memcached API clients : リストに載せたいクライントがあればPRを

API Commands

  • URL: https://github.com/memcached/memcached/wiki/Commands

  • Standard Protocol

    • キー : 250バイトまで。スペースや、ASCIIモードの改行を含めず
    • 32bitフラグ値
    • 失効時間。30日まで。それ以上は、Unixタイムとして扱われる。
    • 64bit CAS値
    • 任意のデータ
  • コマンド

    • Storage Commands

      • set
      • add
      • replace
      • append
      • prepend
      • cas
    • Retrieval Commands

      • get
      • gets
    • delete

    • incr/decr

    • Statistics

      • stats
      • stats items
      • stats slabs
      • stats sizes
    • flush_all

  • References

    • https://github.com/memcached/memcached/wiki/Protocols

Common Client Features

  • URL: https://github.com/memcached/memcached/wiki/CommonFeatures

特徴貼り付け!!!!

  • Less Common Features

    • Get-By-Group-Key

      • Multi-Get コマンドは、複数のサーバにまたがってリクエストは非効率
    • Noreply/Quiet

      • NoreplyがASCIIかそうでないかで実装されてるかによって、トラブルシューティングが難しくなりうる
      • Noreplyは、サーバへmutationsしたいが、レスポンスを待ちたくない時に使う
    • Multi-Set

      • Multi-Setは"quiet" モードの拡張で、多くのコマンドが、バイナリプロトコルでパックされる。
      • 失敗時のとき等のみにサーバはレスポンスをする。
  • References

    • https://github.com/memcached/memcached/wiki/NewCommands

Programming With Memcached Basics

  • URL: https://github.com/memcached/memcached/wiki/Programming

  • Basic Data Caching

# perl
my $memclient = Cache::Memcached->new({ servers => [ '10.0.0.10:11211', '10.0.0.11:11211' ]});
# pseudocode
memcli = new Memcache
memcli:add_server('10.0.0.10:11211')
  • Wrapping an SQL Query
# Don't load little bobby tables
sql = "SELECT * FROM user WHERE user_id = ?"
key = 'SQL:' . user_id . ':' . md5sum(sql)
 # We check if the value is 'defined', since '0' or 'FALSE' # can be
 # legitimate values!
if (defined result = memcli:get(key)) {
	return result
} else {
	handler = run_sql(sql, user_id)
	# Often what you get back when executing SQL is a special handler
	# object. You can't directly cache this. Stick to strings, arrays,
	# and hashes/dictionaries/tables
	rows_array = handler:turn_into_an_array
	# Cache it for five minutes
	memcli:set(key, rows_array, 5 * 60)
	return rows_array
}
  • Wrapping Several Queries
sql1 = "SELECT * FROM user WHERE user_id = ?"
sql2 = "SELECT * FROM user_preferences WHERE user_id = ?"
key  = 'SQL:' . user_id . ':' . md5sum(sql1 . sql2)
if (defined result = memcli:get(key)) {
	return result
} else {
	# Remember to add error handling, kids ;)
	handler = run_sql(sql1, user_id)
	t[info] = handler:turn_into_an_array
	handler = run_sql(sql2, user_id)
	t[pref] = handler:turn_into_an_array
	# Client will magically take this hash/table/dict/etc
	# and serialize it for us.
	memcli:set(key, t, 5 * 60)
	return t
}
  • Wrapping Objects

    • シリアライズの必要があるか。コンストラクタでキャッシュからデータを取ってくる時等
    • シリアライズは、効率的にシンプルに
  • Fragment Caching

 # Lets generate a bio page!
user          = fetch_user_info(user_id)
bio_template  = fetch_biotheme_for(user_id)
page_template = fetch_page_theme
pagedata      = fetch_page_data

bio_fragment = apply_template(bio_template, user)
page         = apply_template(page_template, bio_fragment)
print "Content-Type: text/html", page
key = 'FRAG-BIO:' . user_id 
if (result = memcli:get(key)) {
	return result
} else {
	user         = fetch_user_info(user_id)
	bio_template = fetch_biotheme_for(user_id)
	bio_fragment = apply_template(bio_template, user)
	memcli:set(key, bio_fragment, 5 * 15)
	return bio_fragment
}
  • Extended Functions

    • Proper Use of add
      • 既存のキーがなければ追加することができる
     # There can be only one
    key = "the_highlander"
    real_highlander = memcli:get(key)
    if (! real_highlander) {
    	# Hmm, nobody there.
    	var = fetch_highlander
    	if (! memcli:add(key, var, 3600)) {
    		# Uh oh! Somebody beat us!
    		# We can either use the variable we fetched,
    		# or issue `get` again in case it might be newer.
    		real_highlander = memcli:get(key)
    	} else {
    		# We win!
    	    gloat
    	}
    }
    return real_highlander
    
    • Proper Use of incr or `decr
    # Got a hit!
    key = 'hits: ' . user_id
    if (! memcli:incr(key, 1)) {
    	# Whoops, key doesn't already exist!
    	# There's a chance someone else just noticed this too,
    	# so we use `add` instead of `set`
    	if (! memcli:add(key, 1, 60 * 60 * 24)) {
    		# Failed! Someone else already put it back.
    		# So lets try one more time to incr.
    		memcli:incr(key, 1)
    	} else {
    		return success
    	}
    } else {
    	return success
    }
    
  • Expiration

    • 0から30日までを指定可能
  • Key Usage

    • Avoid User Input

      • ASCIIプロトコルには、スペースや改行があるので注意。
      • バイナリプロトコルではこの必要はない。
    • Short Keys

      • 64-bit UIDは良い。
      • base64 の利用
    • Informative Keys

      • これだと、tcpdumpやstraceしてもどこから来ているかわからないので
        • key = ‘SQL’ . md5sum("SELECT blah blah blah")
      • ユニークなクエリーIDをキーに含める
        • key = ‘SQL’ . query_id . ‘:’ . m5sum("SELECT blah blah blah")

Memcached Usage FAQ

  • URL: https://github.com/memcached/memcached/wiki/ProgrammingFAQ

  • 全キーをリスト化する方法はない。デバッグインタフェースはあるが、推奨されない

  • キャッシュのダンプを取るには、-vv や -vvv でスクリーンセッションを使用するか、 MaatKit を使用する

  • キー間を渡り歩くような操作には向いていないので、Tokyo Tyrant, MySQL等を使用する

  • デバッグインターフェイス stats cachedump で取得可能だが、部分的な取得で、かつ遅い

  • memcached をセッションには使用するのは推奨されない。ハードウェアやソフトウェアアップグレードでキャッシュがの一部が消え、ログアウトされることになるので。

  • MySQLのクエリーキャッシュで、テーブル単位でキャッシュしたりすのは、静的サイトでは有効

  • memcached コマンドは、内部的には、atomic

  • 認証は、クライアントがサポートしていれば、SASL 認証が使えるかも。ただし、本当に必要な時以外に使うとレイテンシーの増加につながる

  • フェイルオーバー機能はないが、クライアントによっては、次のサーバへアクセスするという方法を取る。

  • 再起動後にデータを残しておく方法はない。今後実装予定ではあるけど。

  • データが失効しても、再度参照されるまで、curr_items は減らない。

HOWTO’s and Tricks

  • URL: https://github.com/memcached/memcached/wiki/ProgrammingTricks

  • ネームスペース

    • 機能はないが、キーのプレフィックスで簡単にシミュレーションできる
user_prefix = memcli:get('user_namespace:' . user_id)
bio_data    = memcli:get(user_prefix . user_id . 'bio')

Unixタイムを利用

# Namespace management, basic fetch.
key = 'namespace:' . user_id
namespace = memcli:get(key)
if (!namespace) {
    namespace = time()
	if (! memcli:add(key, namespace)) {
		# lost the race.
		namespace = memcli:get(key)
		# Could re-test it and jump to the start of the loop, hard fail, etc.
	}
	# Send back the new namespace.
	return namespace
}

Invalidation

key = 'namespace:' . user_id
if (! memcli:incr(key, 1)) {
	# Increment failed! Key must not exist.
	memcli:add(key, time())
}
  • Zero byte values
    • こういう実装はダメ。結果で0やfalseや空のデータが返ってくるので。
    • 空のキーは役に立つ
if (data = memcli:get('helloworld')) {
	# Yay stuff!
}
  • Reducing key size

    • メモリの節約にキーのサイズは小さくしておく。
    • 250文字まで。今後65kまで拡張予定
    • 説明的なキー名は無駄
  • Avoiding stampeding herd

    • hotなデータのキャッシュミスを避ける

    • Ghetto lock : add コマンドで減らす

    • Outside mutex : サードパーティの中央化されたmutexがある。MySQL の SELECT GET_LOCK() … RELEASE_LOCK()

    • Scaling expiration : 失効時間を指定しても、実際には、もう少し長い時間を設定されており、ソフトタイムアウトとハードタイムアウトがある。ロックに失敗して、古い方のデータを使うことがある。

    • Scaling expiration : Gearman は良くある、早くてスケーラブルなジョブサービス

  • Ghetto replication : クライアントによっては、レプリケーションをサポートしているかも。

  • "Touching" keys with add : 1週間以内に失効させたいキーがある時、add コマンドで、LRU の先頭に値を持ってくることができる。

  • References

    • http://www.maatkit.org/
    • http://dormando.livejournal.com/495593.html
    • https://github.com/memcached/memcached/wiki/SASLHowto
    • http://lists.danga.com/pipermail/memcached/2007-July/004578.html
    • http://lists.danga.com/pipermail/memcached/2007-July/004581.html
    • http://gearman.org/

Memcached Internals for End Users

  • URL: https://github.com/memcached/memcached/wiki/UserInternals

  • How Memory Gets Allocated For Items

    • -m オプションで、アイテムデータのストレージのために予約するメモリ割り当て量を指定し、主なストレージは、1MB のページへ分割される。各ページは、必要に応じて、slab classes に割り当てられ、特定の塊のサイズへ分割される。
$ ./memcached -vv
slab class   1: chunk size        80 perslab   13107
slab class   2: chunk size       104 perslab   10082
slab class   3: chunk size       136 perslab    7710
slab class   4: chunk size       176 perslab    5957
slab class   5: chunk size       224 perslab    4681
slab class   6: chunk size       280 perslab    3744
slab class   7: chunk size       352 perslab    2978
slab class   8: chunk size       440 perslab    2383
slab class   9: chunk size       552 perslab    1899
slab class  10: chunk size       696 perslab    1506
[...etc...]
  • What Other Memory Is Used
    • 各コネクションのバッファにもメモリが使われる。

Maintenance

Maintaining a Server

  • URL: https://github.com/memcached/memcached/wiki/ServerMaint

  • Important Stats

    • stats コマンド

      • curr_connections : -c オプション
      • listen_disabled_num
      • accepting_conns
      • limit_maxbytes : -m オプション
      • cmd_flush : flush_all コマンド実行時にカウントされる。
    • stats sizes コマンド : stats sizes enable

    • Slab imbalance

      • グローバルの evictions stat
      • stats items コマンド内の evicted, evicted_nonzero
      • stats slabs コマンドから total_pages stat
      • evictions が多いスラブが多いページを持っていたら、OOMになりうる
      • evictions が多いスラブがページでラインアップされなかったら、再起動
  • Stats for Application Health

  • OS Health (avoid swap!)

Maintaining a Cluster

  • URL: https://github.com/memcached/memcached/wiki/ClusterMaint

  • Upgrades : プロダクション環境では、1台だけアップグレードしてみて問題がなければ、残りへロールアウトしていくと良い。

What Performance To Expect

  • URL: https://github.com/memcached/memcached/wiki/Performance

  • Max Clients

    • 接続された各クライアントはTCPメモリを使うので、RAMから割り当てられる限りでしか接続できない。
    • 新規クライアント接続は、1つしかスレッドを使うことができないので、非常に早く接続を使いまわすとスレッドをオーバーするかも。永続接続か、UDPが代替案。
    • 高い接続切れは、OSのTCPのチューニングが必要かも
  • Maximum number of nodes in a cluster

    • From the Client Perspective
      • TCPソケットを多く確立しすぎるとRAMの無駄使い
      • 永続接続を使わないと、TCPのスリーウェイハンドシェイクのレイテンシーやパケットが余分に発生
    • The Multiget Hole
      • 特定ユーザーのプロファイルに対する全てのキーが、同一サーバ上にあると、呼び出すsyscallの数が少なくなる
    • A Well Designed Binary Protocol Client
      • バイナリプロトコルを使えば、異なるクライアントインスタンスからのリクエストを同じTCPソケットにパックできる。
    • Remember Moore’s Law
    • Economy of Scale : クラスターが大きくなってくると問題も発生するようになりがち

Troubleshooting Timeouts

  • URL: https://github.com/memcached/memcached/wiki/Timeouts

  • Troubleshooting Timeouts

      1. stats コマンドで listen_disabled_num を確認
    • 2.通常の怪しいところを確認 : スワップ。CPU(nice,renice)。64bit

      1. mc_conn_tester.pl を実行(www.memcached.org/files/mc_conn_tester.pl )
      $ ./mc_conn_tester.pl -s memcached-host -p 11211 -c 1000 --timeout 1
      Averages: (conn: 0.00081381) (set: 0.00001603) (get: 0.00040122)
      $ ./mc_conn_tester.pl --help
      Usage:
          mc_conn_tester.pl [options]
      
      Options:
          -s --server hostname
                  Connect to an alternate hostname.
      [...etc...]
      
    • パケットがドロップしている可能性

      • ファイアウォールやスロット不足、ネットワークカード等
    • TIME_WAIT バケットやローカルポートの使い切り

      • mc_conn_tester.pl で接続タイムアウトが確認できる(conn: is 0)

      • netstat -n | grep -c TIME_WAIT も確認

        !THESE ARE EXAMPLES, NOT RECOMMENDED VALUES!
        net.ipv4.ip_local_port_range = 16384 65534
        net.ipv4.tcp_max_tw_buckets = 262144
        net.ipv4.tcp_fin_timeout = 30
        net.ipv4.tcp_tw_reuse = 1
        net.ipv4.tcp_tw_recycle = 1
        

Development

Development Repos

  • URL: https://github.com/memcached/memcached/wiki/DevelopmentRepos

  • New contributors

    • コードを読み、テストを実行、mc-crusher を稼働、commit を読み、typo fixes をsubmitするのが良いスタート
  • Branches

    • master ブランチが中央レポジトリ
    • next ブランチがテストやレビューされたものがcommitされるブランチ。PR時はここからfork
  • Development work

    • リリーステスト : http://build.memcached.org:8010/
    • パフォーマンスリグレッションテスト: https://www.packet.net/
    • パフォーマンステスト: https://github.com/dormando/mc-crusher

Protocols

  • URL: https://github.com/memcached/memcached/wiki/Protocols

  • 主に2つのプロトコル

    • ASCII プロトコル
    • バイナリプロトコル
  • サブプロトコルや提案

    • SASL 認証
    • レンジ操作

Protocol

  • URL: https://github.com/memcached/memcached/blob/master/doc/protocol.txt
  • まとめをざっと外観したい場合、これをとりあえず見とく。★5

BinaryProtocolRevamped

  • URL: https://github.com/memcached/memcached/wiki/BinaryProtocolRevamped

  • memcached 1.3から導入

  • パケットのフォーマット

     Byte/     0       |       1       |       2       |       3       |
        /              |               |               |               |
       |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
       +---------------+---------------+---------------+---------------+
      0/ HEADER                                                        /
       /                                                               /
       /                                                               /
       /                                                               /
       +---------------+---------------+---------------+---------------+
     24/ COMMAND-SPECIFIC EXTRAS (as needed)                           /
      +/  (note length in the extras length header field)              /
       +---------------+---------------+---------------+---------------+
      m/ Key (as needed)                                               /
      +/  (note length in key length header field)                     /
       +---------------+---------------+---------------+---------------+
      n/ Value (as needed)                                             /
      +/  (note length is total body length header field, minus        /
      +/   sum of the extras and key length body fields)               /
       +---------------+---------------+---------------+---------------+
       Total 24 bytes
  • リクエストヘッダー
     Byte/     0       |       1       |       2       |       3       |
        /              |               |               |               |
       |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
       +---------------+---------------+---------------+---------------+
      0| Magic         | Opcode        | Key length                    |
       +---------------+---------------+---------------+---------------+
      4| Extras length | Data type     | vbucket id                    |
       +---------------+---------------+---------------+---------------+
      8| Total body length                                             |
       +---------------+---------------+---------------+---------------+
     12| Opaque                                                        |
       +---------------+---------------+---------------+---------------+
     16| CAS                                                           |
       |                                                               |
       +---------------+---------------+---------------+---------------+
       Total 24 bytes
  • レスポンスヘッダー
     Byte/     0       |       1       |       2       |       3       |
        /              |               |               |               |
       |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
       +---------------+---------------+---------------+---------------+
      0| Magic         | Opcode        | Key Length                    |
       +---------------+---------------+---------------+---------------+
      4| Extras length | Data type     | Status                        |
       +---------------+---------------+---------------+---------------+
      8| Total body length                                             |
       +---------------+---------------+---------------+---------------+
     12| Opaque                                                        |
       +---------------+---------------+---------------+---------------+
     16| CAS                                                           |
       |                                                               |
       +---------------+---------------+---------------+---------------+
       Total 24 bytes
  • References
    • memcached Binary Protocol in a Nutshell : https://www.slideshare.net/tmaesaka/memcached-binary-protocol-in-a-nutshell-presentation/

SASLAuthProtocol

  • URL: https://github.com/memcached/memcached/wiki/SASLAuthProtocol
  • References
    • SASLHowto: https://github.com/memcached/memcached/wiki/SASLHowto
    • Simple Authentication and Security Layer: https://en.wikipedia.org/wiki/Simple_Authentication_and_Security_Layer

RangeOps

  • URL: https://github.com/memcached/memcached/wiki/RangeOps
Get 	0x30 	rget
Set 	0x31 	rset
Quiet Set 	0x32 	
Append 	0x33 	rappend
Quiet Append 	0x34 	
Prepend 	0x35 	rprepend
Quiet Prepend 	0x36 	
Delete 	0x37 	rdelete
Quiet Delete 	0x38 	
Incr 	0x39 	rincr
Quiet Incr 	0x3a 	
Decr 	0x3b 	rdecr
Quiet Decr 	0x3c 	

My Twitter & RSS

Leave a Reply

Your email address will not be published. Required fields are marked *