読者です 読者をやめる 読者になる 読者になる

テストステ論

高テス協会会長が, テストステロンに関する情報をお届けします.

(akashic report) メタデータキャッシングの実装

(akashic report) メタデータキャッシングの構想 - テストステ論

akashic-storageの難しいところは, 分散環境でも動作させたいというところにあり, 他ノードとの通信が不可能である以上たぶん理論的には穴があるのですが, 近似によって現実的にはおkでしょうというところを探るところにあります. またそれは楽しみでもあります.

(akashic report) メタデータキャッシングの構想 - テストステ論

この前構想について書きましたが, 実際に実装した方法は, Wikiより:

akashic-storage stores every metadata as files so it causes more than one file reads against the backing store per a GET request. Depending on the backing store type, the extra file reads other than the data file causes non-negligible performance damage. This typically matters when the filesystem is distributed because it may pay for extra communications between the cluster nodes.

This is where metadata caching comes. Because the files managed under akashic-storage are immutable, never overwritten partially, they are mostly safely cacheable. Caching small metadata on the RAM can effectively eliminate the extra overhead.

The caching mechanism akashic-storage implements is perfectly workable if the backing store is the local filesystem and only one akashic-storage instance has exclusive access to the backing store.

The problem only occurs when multiple akashic-storage instances share the same distributed filesystem and then a client replace the existing resources (by "PUT Bucket acl" API for example). Since it uses a pair of (BasicFileAttributes#fileKey, #creationTime) as the lookup keys. Theoretically, there is some potential hole that the read cache metadata is stale.

The key consists of two information - fileKey and creationTime. fileKey is a unique identifier of the file in the filesystem. It's typically inode-number. But the problem is fileKey may be reused depending on the implementation specific. So replacing a file many times may finally give us the same fileKey that was seen before, which potentially leads to stale metadata read. This is why I pair the fileKey with the creationTime. With the timestamp, we can enhance the uniqueness of the key.

However, the problem is creationTime is resolution of a second. Therefore, with pairing the two values though, it's not the perfect solution against the case that the user replace the resource very frequently and the same fileKey appears within a second.

Considering that this is only a use case of insanity, I am confident the solution is almost perfect.

端的にいうと,

  • (fileKey, creationTime)のペアをキーとすることにした
  • 単一環境では間違いなく動作する. 問題は分散環境
  • これによってcreationTimeの精度1秒以内でfileKeyが再利用されない場合は正しく動作することになる. これはほぼ100%大丈夫
  • (書いてないけど) backing storeが要件を満たすかチェックするツールは作ります
  • (書いてないけど) 最悪, fileKeyがnullの場合も, 1秒以上replaceされなければ耐え得る

実際は, あらゆるファイルを追記していけばキャッシュも安全に出来るはずで, 実際に少し前はそう実装していたのですが, やりすぎと判断して今の実装になっています. 性能は当然ですが, 他にも犠牲になるものがあるので, シンプルであることを重視しています. そのためにキャッシングが安全でなくなり, 結果として現実的にはまぁ安全でしょうという線で妥協することになったのですが, 性能ゲインを考えると, 提供する価値があります. ちなみに, 実際にbucketだとかobjectをreplaceしたい人自体が現実的にはあまり居ないと思っています.