SODA Engineering Blog
📝

Amazon ElastiCache for Memcachedクラスタのノード自動検出とクライアント設定注意点

2023/01/29に公開

はじめに

Amazon ElastiCache for Memcachedでクラスタを構築する際のノード自動検出の仕組みとクライアント側の接続設定の注意点について説明します。

ElastiCache for Memcachedでは、クラスタを構成しているノードの情報を自動的に取得するための機能が提供されています。この機能はAuto Discoveryと呼ばれていますが、これは本家のMemcachedにはなく、ElastiCache for Memcached独自の機能です。一般的なMemcachedクライアントライブラリにはこのAuto Discoveryに対応していないものも少なくありません。したがって、Auto Discoveryに対応していないクライアントライブラリにAuto Discovery用のエンドポイントを設定してしまうと、意図しない挙動になり、クラスタのパフォーマンスが引き出せないので注意が必要です。

最初にまとめ

  • 一般的なMemcachedクライアントライブラリは、クラスタを構成するすべてのノードを事前に登録する必要がある
  • Auto Discovery機能を使う場合、これに対応したクライアントライブラリを使用する必要がある
    • クライアントライブラリには各ノードのエンドポイントではなく設定エンドポイントを登録する
  • Auto Discoveryに対応していないクライアントライブラリに設定エンドポイントを登録した場合、クライアントのノード選択はキーのハッシュ値によるものではなく、名前解決によって決定されたランダムな選択になる
    • アクセスのたびにキャッシュの保存先と取得先のノードが異なる可能性があるのでキャッシュヒット率が下がって効率が悪い
    • OSやクライアントライブラリでDNSキャッシュをしていた場合、DNSキャッシュが有効な間は同じノードにアクセスが集中してしまい負荷が分散されない

Memcachedクラスタのノード選択の仕組み

Memcachedクラスタ自身はノード選択の仕組みを提供しません。クライアントが、キャッシュキーに基づいて負荷を分散させるなんらかのアルゴリズムを用いてノードを選択します。したがって、クライアントライブラリには事前にクラスタを構成するすべてのノードのエンドポイントが登録されている必要があります。

ノード選択でよく使われるアルゴリズムとしては、キャッシュキーのハッシュ値をノード数で割った余りでノードを選択するものや、ノードの増減時にキャッシュヒット率がなるべく低下しないように工夫したコンシステントハッシングという方法があります。採用されているアルゴリズムはクライアントライブラリによって異なりますが、キャッシュキーのハッシュ値を元にノードを選択し、処理がうまく分散されるようにしている点は共通しています。

ElastiCache for Memcachedクラスタのノード自動検出の仕組み(Auto Discovery)

ElastiCache for Memcachedクラスタのノード自動検出機能をAuto Discoveryといいます。この機能はElastiCache for Memcachedの独自のものであり、本家Memcachedには存在しません。

Auto Discoveryでは、クライアントライブラリにクラスタのすべてのノードのエンドポイントを登録することはしません。代わりに、ElastiCache for Memcachedでクラスタを構築した際に提供される「設定エンドポイント」のみを登録します。

Auto Discoveryではまず設定エンドポイントをDNSで名前解決してクラスタ内のノード1つのアドレスを取得します。そしてこのアドレスを使ってノードに接続し、クラスタを構成するすべてのノードのアドレスを得ます。クラスタ内のすべてのノードは、クラスタ内の他のノードのアドレス情報を保持しています。

ここにキャッシュノード3つから構成されるクラスタがあるので、実際に動作を確認してみます。
はじめに、クラスタの各ノードのエンドポイントを名前解決してアドレスを確かめます。結果はANSWER SECTIONのみを記載しています。

# ノード1
$ dig example.utk6ty.0001.apne1.cache.amazonaws.com
;; ANSWER SECTION:
example.utk6ty.0001.apne1.cache.amazonaws.com.	15 IN A	172.31.31.59

# ノード2
$ dig example.utk6ty.0002.apne1.cache.amazonaws.com
;; ANSWER SECTION:
example.utk6ty.0002.apne1.cache.amazonaws.com.	15 IN A	172.31.1.38

# ノード3
$ dig example.utk6ty.0003.apne1.cache.amazonaws.com
;; ANSWER SECTION:
example.utk6ty.0003.apne1.cache.amazonaws.com.	15 IN A	172.31.47.83

次に、設定エンドポイントを名前解決してみます。
ノード3のアドレスが返ってきました。もう一度実行すると今度はノード2のアドレスが返ってきました。複数回実行すると、クラスタ内のノードのアドレスがランダムに返ってくることがわかります。また、結果からはTTLが15秒に設定されていることもわかります。

# 1回目
$ dig example.utk6ty.cfg.apne1.cache.amazonaws.com
;; ANSWER SECTION:
example.utk6ty.cfg.apne1.cache.amazonaws.com. 15 IN A 172.31.47.83

# 2回目
$ dig example.utk6ty.cfg.apne1.cache.amazonaws.com
;; ANSWER SECTION:
example.utk6ty.cfg.apne1.cache.amazonaws.com. 15 IN A 172.31.1.38

さらに次は、ノードに接続してクラスタをすべてのノードのアドレスを取得してみます。
telnetでノード1に接続し config get cluster コマンドを実行します。

$ telnet example.utk6ty.0001.apne1.cache.amazonaws.com 11211
Trying 172.31.31.59...
Connected to example.utk6ty.0001.apne1.cache.amazonaws.com.
Escape character is '^]'.
config get cluster
CONFIG cluster 0 199
1
example.utk6ty.0001.apne1.cache.amazonaws.com|172.31.31.59|11211 example.utk6ty.0002.apne1.cache.amazonaws.com|172.31.1.38|11211 example.utk6ty.0003.apne1.cache.amazonaws.com|172.31.47.83|11211

END

すべてのノードのアドレスが取得できていることがわかります。
Auto Discoveryは、このすべてのノードをクライアントライブラリに動的に登録することで、事前のノードの登録を不要にしています。

クライアントライブラリ接続設定注意点

先述の通り、Auto Discoveryは本家Memcachedの機能ではなくElastiCacheの拡張機能なので、正しく利用するにはこれに対応したMemcachedクライアントライブラリを使う必要があります。一般的なMemcachedクライアントライブラリにはAuto Discoveryに対応していないものも少なくないので注意が必要です。

Auto Discoveryに対応していないクライアントライブラリに、設定エンドポイントを登録して利用した場合を考えてみます(これは誤った使用方法です)。設定エンドポイントはクラスタのノードのアドレスをランダムに返します。したがって、クライアントはランダムにノードを選択することになります。これは、同じハッシュキーであってもデータ保存/取得時のアクセス時に名前解決の結果が異なる可能性があり、その結果異なるノードにアクセスすることになるので、キャッシュミスが発生することを意味します。さらに、名前解決の結果をOSやクライアントライブラリでDNSキャッシュしていた場合、DNSキャッシュが有効な間は同じノードにアクセスし続けてしまいます。これではクラスタの負荷分散の利点を享受できていません。

正しくクラスタを使うには、Auto Discoveryに対応したクライアントライブラリに設定エンドポイントを登録します。一方、非対応のクライアントライブラリを使用する場合は、事前にすべてのノードのアドレスを登録します。

参考にしたドキュメント

SODA Engineering Blog
SODA Engineering Blog

Discussion