memcached - a distributed memory object caching system

クラウドにおけるExtstore - Dormando (2018年8月15日)

memcachedの外部ストレージに関する入門記事では、永続メモリ、高価なNVMeデバイス、テラバイト単位のキャッシュについて説明しました。extstoreは、さまざまなクラウドベンダーの一般的なSSD搭載VMに関連があるのでしょうか?この記事では、安価なDigitalOcean VMにextstoreをインストールして構成することで、この問いに答えます。

ユースケース:セッションキャッシュ

良いか悪いかに関わらず、クラウドにおけるキー/バリューストアの大きなユースケースはセッションキャッシュです。これらのオブジェクトは一時的なものであり、頻繁に更新され、ユーザーのログインセッションに関連付けられた比較的大量のデータです。非構造化データとTTL(Time To Live)の制限により、プライマリデータベースには不向きです。

Webサイトの所有者は、セッションを処理するためだけにmemcachedインスタンスをセットアップすることがよくあります。ここではセッションデータに焦点を当てますが、インスタンスは同時に他のデータも処理できます。

問題点

1つのドロップレットから成長したWebサイトがあるとしましょう。memcached専用の3.5GBのRAMを搭載した月額20ドルのインスタンスがあります(1つが故障した場合に備えて、複数で実行することをお勧めします!)。最近、ユーザーが毎日ログインを維持できず、DBの使用量が増加していることに気付きました。

メモリ要件

多くのセッション実装では、セッションオブジェクトが失われると、ユーザーはログアウトするか、DBがそれを再生成するために大きな負荷がかかります。したがって、セッションを有用な期間保持することが重要です。

Extstoreでは、オブジェクトのキーとメタデータをRAMに保持し、値をストレージにポイントする必要があります。これは、小さなオブジェクトには不向きです。セッションデータは非常に大きくなる可能性があるため、最初に確認しましょう。

$ echo "stats slabs" | nc localhost 11211 | grep -E "total_pages|chunk_size"
[... snip ...]
STAT 26:chunk_size 27120
STAT 26:total_pages 321
STAT 27:chunk_size 33904
STAT 27:total_pages 2936
STAT 28:chunk_size 42384
STAT 28:total_pages 157
[... snip ...]

簡単なチェックで、割り当てられたメモリのほとんどが26k〜42kのメモリを使用するオブジェクトで終わっており、そのほとんどが32kであることがわかります。memcachedのキーとメタデータは、極端な場合でも300バイトを超えることはできないため、ほとんどのスペースはアイテムの値です。extstoreに適した(やや作為的な)例です!

stats itemsstats slabsのカウンターを調べてグラフ化することをお勧めします。この場合、スラブクラス26、27、28もエビクションカウントが高いことがわかりました。セッションを早期に破棄しています!

キャッシュの拡張とコスト削減

現在、20ドルのドロップレットで3.5GBのRAMキャッシュを使用しています。執筆時点では、10ドルのドロップレットには2GBのRAMと50GBのSSDバックアップディスクスペースが付属しています。利用可能なキャッシュスペースを3倍にし、コストを半分にしてみましょう。

インスタンスのセットアップ

extstoreはまだ新しいため、有効にするには自分でmemcachedをビルドする必要があるかもしれません。この記事を読む頃には不要になっている可能性があるため、何かを手動でビルドする前に、memcached -hでextstoreがサポートされているかどうかを確認してください。

この例では、DigitalOceanのUbuntu 18.04 64ビットドロップレットを使用します。これらのバイナリと構成は、最も快適に感じる方法でパッケージ化、スナップショット、または管理してください。

まず、最新のtarballを入手します。リダイレクトを修正する必要があります;)

d@blogbox:~$ wget https://memcached.dokyumento.jp/latest
[... snip ...]
latest		       100%[=========================>] 454.27K  --.-KB/s    in 0.005s

2018-08-14 04:46:27 (96.5 MB/s) - ‘latest’ saved [465169/465169]

d@blogbox:~$ tar -zxvf latest
d@blogbox:~$ ls
latest	memcached-1.5.10
d@blogbox:~$ rm latest

次に、いくつかの依存関係を取得してデーモンをコンパイルします。redhatベースのディストリビューション(centosなど)では、テストを実行するためにいくつかのperlモジュールをインストールする必要がある場合があります。

d@blogbox:~$ cd memcached-1.5.10/
d@blogbox:~/memcached-1.5.10$ sudo apt-get install build-essential libevent-dev
Reading package lists... Done
Building dependency tree... 50%
Reading state information... Done
[... snip ...]
Do you want to continue? [Y/n] y
[... snip ...]
d@blogbox:~/memcached-1.5.10$ ./configure --enable-extstore
checking build system type... x86_64-pc-linux-gnu
checking host system type... x86_64-pc-linux-gnu
[... snip ...]
configure: creating ./config.status
config.status: creating Makefile
config.status: creating doc/Makefile
config.status: creating config.h
config.status: executing depfiles commands
d@blogbox:~/memcached-1.5.10$ make
[... snip ...]
Leaving directory '/home/d/memcached-1.5.10'
make[1]: Leaving directory '/home/d/memcached-1.5.10'
d@blogbox:~/memcached-1.5.10$

オプションで、テストを実行します。 1.5.10では、ubuntu 18.04で、t/lru-maintainer.tが競合状態によって失敗する可能性があります。これはすでに修正済みであり、1.5.11で修正されます。

d@blogbox:~/memcached-1.5.10$ make test
[ might fail on t/lru-maintainer.t ]

次に、バイナリを/usr/localにインストールします。これは、configureステップで--prefixを使用して変更できます。

d@blogbox:~/memcached-1.5.10$ sudo make install

ソースtarballには、systemdサービススクリプトと構成ファイルが付属しています。それらをインストールしましょう。ファイルの編集については、以下を参照してください。

d@blogbox:~/memcached-1.5.10$ sudo cp scripts/memcached.service /etc/systemd/system/
d@blogbox:~/memcached-1.5.10$ sudo mkdir /etc/sysconfig
d@blogbox:~/memcached-1.5.10$ sudo cp scripts/memcached.sysconfig /etc/sysconfig/memcached
d@blogbox:~/memcached-1.5.10$ sudo vi /etc/systemd/system/memcached.service
d@blogbox:~/memcached-1.5.10$ sudo vi /etc/sysconfig/memcached

/etc/systemd/system/memcached.serviceの「ExecStart」行を次のように編集します

ExecStart=/usr/local/bin/memcached -p ${PORT} -u ${USER} -m ${CACHESIZE} -c ${MAXCONN} $OPTIONS

ここでは、パスに「/local/」を追加するだけです。

最後に、次のような/etc/sysconfig/memcachedを使用します

# These defaults will be used by every memcached instance, unless overridden
# by values in /etc/sysconfig/memcached.
USER="nobody"
MAXCONN="1024"
CACHESIZE="1500"
OPTIONS="-l 127.0.0.1 -o ext_path=/tmp/extstore:10G,ext_item_size=512"

# The PORT variable will only be used by memcached.service, not by
# memcached@xxxxx services, which will use the xxxxx
PORT="11211"

最後に、サービスを有効にして開始します

d@blogbox:~/memcached-1.5.10$ sudo systemctl enable memcached
Created symlink /etc/systemd/system/multi-user.target.wants/memcached.service → 
 /etc/systemd/system/memcached.service.
d@blogbox:~/memcached-1.5.10$ sudo systemctl start memcached
d@blogbox:~/memcached-1.5.10$ ps aux | grep -i memcached
nobody	 10069	0.0  0.3 1723160 7152 ?        Ssl  05:32   0:00
/usr/local/bin/memcached -p 11211 -u nobody -m 1024 -c 1024 -l 127.0.0.1 -o
ext_path=/tmp/extstore:10G,ext_item_size=512
d	 10100	0.0  0.0  14856  1048 pts/1    S+   05:33   0:00 grep --color=auto -i memcached
d@blogbox:~/memcached-1.5.10$

これで完了です!1.5GBのRAMと10GBのディスクバックアップストレージでmemcachedを構成しました。また、512バイトを超えるオブジェクトをディスクにフラッシュすることを許可するように指示しました。


自分のユースケースに合わせて実験できます(そしてそうすべきです!)。信頼性のためにキャッシュをより多くのノードに分散したい場合や、セッションが小さい(したがってより多くのRAMが必要)場合などがあるかもしれません。明確なルールはありません。

可能性は低いでしょう。memcachedは、大きなオブジェクトをすぐにディスクにフラッシュしません。可能な限りRAMに残ります。実際には、最新のオブジェクトも「ホット」であり、頻繁に読み書きされます。RAMよりも10倍多くのディスクがあっても、読み書きの9/10はRAMに留まる可能性があります。

さらに、オブジェクトが上書き、削除、またはTTLによって期限切れになった場合でも、ディスクIOは発生しません。これは、クラウドインスタンスで利用できる限られたIOでも十分に拡張できるはずです。

結論

このウォークスルーでは、理論上のWebサイトセッションキャッシュを3倍に拡張し、コストを半分にすることができました。これがすべてのユースケースを網羅するわけではありませんが、判断が迅速で、実験が安価です。

詳細なドキュメントは、Wikiで入手できます。