D1のリードレプリカに6秒のラグが発生
東京のD1リードレプリカが、北米での書き込みに対して6.1秒遅延しました。
これは、誤ったインプレッションをスロットリングしているトラッカーから知りました。ドキュメントには結果整合性(eventual consistency)について記載されていますが、計画を立てるための具体的な時間は示されていません。
実態を把握するために、データの鮮度を測定するプローブ(staleness probe)を作成しました。このプローブは、UUIDとエポック(epoch)を含む行を書き込みます。そして、その行が現れるまでレプリカをポーリングし、その遅延時間を記録します。
アジアでの200回のプローブ結果:
- p50: 800ms
- p95: 3,400ms
- p99: 6,100ms
プライマリが北米にあり、ユーザーがアジアにいる場合、このラグは非常に大きくなります。
また、スキーマエラーにも直面しました。プライマリでマイグレーションを実行した後、Workerが再起動しました。最初の数リクエストが、新しいテーブルが反映される前にレプリカに到達したのです。エラー内容は「テーブルが存在しない」というものでした。テーブル自体は存在していましたが、レプリカの同期が遅れていました。
私はラグと戦うのではなく、ラグを回避するようにルーティングすることでこれを解決しました。
私の設計は以下の通りです:
- ライター(writer)が、行に
written_atエポックを追加する。 - ライターが、レスポンスに
X-D1-Written-Atヘッダーを追加する。 - リーダー(reader)が、そのヘッダーとレプリカからのデータを比較する。
- レプリカのデータがヘッダーよりも古い場合、リーダーは KV にフォールバックする。
KVは同じリージョン内であれば500ms未満で動作します。また、1日あたり最大1,000万回の読み取りまで無料です。これにより、重要なフラグに対して最新のデータを取得するための安価な手段が得られます。
KVを使用するのは、レプリカが遅延している短い期間のみです。レプリカの同期が完了すれば、ほとんどの読み取りは通常通り D1 に行われます。
詳細な記事の中で、スクリプトの全文とマイグレーションのパターンを公開しています。