この記事について
サービス運用中にRedisのキャッシュ互換性で困った経験について書きます。
何が起きたのか
運用中のサービスで、APIのドメインを変更した際に、Redisのキャッシュ取得時にエラーが発生しました。
例えばUserというドメインがあり、以前のデータ構造は以下の通りです。
{
"id": 1,
"name": "Alice",
"age": 20
}
キャッシュのキーは一意のidを使用していました。ここに新たにgender
というフィールドを追加し、その変更を行なったAPIをデプロイしようとしKubernetesクラスター上で旧APIのPodと新APIのPodが混在する状況が発生した際に、旧APIのPodがidをキーとして新APIのキャッシュデータを取得しようとすると、存在しないgender
フィールドが原因でエラーが発生し、逆に新APIのPodが旧APIのキャッシュデータを取得しようとすると、存在するはずのgender
フィールドが無いためエラーが頻発しました。
このような状況ではキャッシュ取得がうまくいかず、サービス全体のパフォーマンスが低下してしまいます。そこで、この問題をどのように解決したかについて説明します。
どうやって解決したか
この問題を解決するために、新バージョンのドメインに予め追加しておいたgender
フィールドと共にversion
フィールドを追加しました。
{
"id": 1,
"name": "Alice",
"age": 20,
"gender": "Woman",
"version": 20241201
}
さらに、キャッシュキーにもバージョン情報を追加しました。新バージョンのAPIではid
とversion
がなければ、キャッシュがヒットしなくなります。
user-1-20241201
なぜversionを追加したか
version
フィールドを追加することで、新旧APIのキャッシュを区別できるようにしました。旧APIで作成・取得されるキャッシュにはversion
フィールドが無いため、新APIでは取得されません。逆に、新APIで作成・取得されるキャッシュにはversion
フィールドがあるため、旧APIでは取得されません。
versionの値はどうするか
version
の値は、APIのドメインを変更した日付を採用しました。APIのコミットハッシュを使用することも考えましたが、デプロイのたびに変わるためキャッシュの効果が薄れてしまいます。そのため、ドメインに変更があった場合にバージョンの日付を変更する運用を採用しました。
まとめ
このように、APIのドメインを変更した際にRedisのキャッシュ互換性を保つために、version
フィールドを追加し、キャッシュキーにもバージョン情報を追加することで、新旧APIのキャッシュを区別できるようになりました。