複数EC2インスタンスからアクセス可能なキャッシュとしてEFSを利用し、数百GB以上のデータを定常的に運用している。その中でいくつかハマりポイントが見つかったので書いておく。
EFSとは
えごったーでは、ツイッターAPIのデータのキャッシュとしてEFSを利用している。EFSは簡単に言うと、複数EC2インスタンスに同時にマウントできるEBS。その他の特徴は下記の通り。
- 複数EC2インスタンスに同時にマウントできる共有ストレージサービス
- 内部的にはNFS
- フルマネージド、複数AZへの冗長化あり
- アクセス速度は、ローカルストレージ(=EBS)よりは遅い、(使い方によるが)S3よりは早い
- EBS > EFS > S3
- 料金は、EBSよりも高い、S3よりはもちろん安い
- EFS > EBS > S3
- 保存するデータ量に応じてサイズが自動で増減する
この中でも サイズが自動で増減する点が他にはない特徴かつ非常に役に立つ点 。自動で増加するサービスは多いが、減少するサービスは比較的珍しい。柔軟性が高い分、EBSよりも料金が高くなっている。
ただし、良い点だけでなく注意が必要な点もいくつかある。それを順に書いていく。
注意点
この規模のデータになると通常のファイルシステム(ext4など)でもそれなりに遅くなります。EFSだけが遅いというわけではない点にご注意ください。
データが大きくなるとファイルの一覧表示(ls)に数十分以上の時間がかかるようになる
今回、EFSには183GBのデータを保存している。
$ df -h
ファイルシス サイズ 使用 残り 使用% マウント位置
ap-northeast-1b.fs-00000000.efs.ap-northeast-1.amazonaws.com:/ 8.0E 183G 8.0E 1% /efs
すると、ファイルの一覧表示ができなくなってしまう。
$ ls /efs/cache
# 結果が返ってこない
ディレクトリ構造は一例として下記の通り。1, 2, 3, 4がファイルで中身はJSONが入っている。ファイル数は250万ほどある。
$ tree /efs/cache
├── 032
│ └── 320
│ └── 1
├── 033
│ └── 330
│ └── 2
├── 034
│ └── 340
│ └── 3
├── 035
│ └── 350
│ └── 4
もちろん、ディレクトリのサイズ表示(du -sh)もできない。
$du -sh /efs/cache
# 結果が返ってこない
ファイルの一覧表示ができないと困るのは有効期限切れのキャッシュを削除するとき
似たような例として、Redis等のキャッシュシステムではキーの一覧表示は非常に負荷がかかる処理であり、本番環境では実行しないように注意する必要があることはよく知られている。
それと同様に、lsをしなければよいと思うかもしれないが、それではうまくいかないケースがある。
Redisは有効期限切れのキャッシュの削除を自動で行う仕組みが用意されているが、 ファイルシステムベースのキャッシュは有効期限切れのキャッシュの削除を次回アクセス時に行う実装になっていることがある 。
つまり、ある時点で作ったキャッシュは削除されずにずっと残り続ける。それではデータが増えすぎてしまうため、定期的に削除する必要があるが、ファイルシステムベースのキャッシュは有効期限切れキャッシュの探索にlsと類似する仕組みを用いることがあり、このケースに当たると利用しないキャッシュがいつまでも削除されないことになってしまう。
一例として、Rails(ActiveSupport)のFileStoreは上記のような実装になっており、EFSをキャッシュ保存先として利用していると、データが大きくなるにつれ下記のコードで有効期限切れのキャッシュ削除をすることができなくなってしまう。
ActiveSupport::Cache::FileStore.new(dir).cleanup
# 一覧表示ができないためそもそも始まりすらしない
この問題に対して、えごったーでは、定期的にキャッシュを保存するディレクトリを変更することで対処している。
# 1月のキャッシュ。2月になったらrmで削除可能
/efs/cache/201901
# 2月のキャッシュ
/efs/cache/201902
ただし、EFSに数百GBのデータを保存すると、ファイルの削除にも非常に時間がかかるため、rmの実行にも注意が必要となる。
データが大きくなるとファイルの削除(rm)にも数十分以上の時間がかかるようになる
183GBのデータをrmで単純に削除すると、約3時間かかることになる。この点も注意してEFSを運用する必要がある。
$ time rm -rf /efs/cache
real 183m54.272s
user 0m9.202s
sys 1m33.282s
注意点
この規模のデータをrmで削除すると、通常のファイルシステム(ext4など)でもそれなりに遅くなります。EFSだけが遅いというわけではない点にご注意ください。