Memcached 公式ドキュメント まとめ
Redis本を執筆しました。Memcachedとの詳細な比較も付録で取り上げていますので、こちらも是非合わせてご覧ください。
---------------------------------------------------------------------------------------------------------------------------------------------------------
memcached のWikiを一読してまとめてみました (2018/05/13 時点)
Memcached
- 公式ページ: https://memcached.org/
- Wiki: https://github.com/memcached/memcached/wiki
別途、Memcachedの機能のまとめ記事等は以下のURLを参照いただければと存じます。
- Dive Deep Memcached ~ 入門から実装の確認まで ~
- Redis / Memcached Source Code Reading – Overview –
- Dive Deep Memcached ~ SETコマンド実行時の動作 ~
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 へ接続する度に初期化していたら、接続がリークするかも
- Hashing
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の短いアイテム
- ストレージの page は、複数の buckets へ分割される
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 }
- Proper Use of add
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")
- これだと、tcpdumpやstraceしてもどこから来ているかわからないので
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 : クラスターが大きくなってくると問題も発生するようになりがち
- From the Client Perspective
Troubleshooting Timeouts
URL: https://github.com/memcached/memcached/wiki/Timeouts
Troubleshooting Timeouts
- stats コマンドで listen_disabled_num を確認
2.通常の怪しいところを確認 : スワップ。CPU(nice,renice)。64bit
- 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