時系列の概要
AWS Lambda x RDS (Postgres) によるサーバーアプリケーションが停止するという問題が発生しました。
- 本番環境に対して、検証済みのバージョンをデプロイ。
- デプロイ直後に動作確認を行ったが、問題なく動作していた。
- ⭐️ 数分経過後、顧客からシステムが停止している旨の連絡を受けた。
- 実際に確認するとエラーが大量発生し、システムが停止していた。
-
cannot execute UPDATE in a read-only transaction(-> DB への書き込みが失敗)
-
「⭐️ 数分経過後」というところが今回の問題を特定するキーポイントであった。
何が起きたのか
前提
最近、クラスタにリードレプリカを追加した。
サーバーは、ライターインスタンスのエンドポイントを参照していた。
問題発生
デプロイ前後、瞬間的にライターインスタンスの負荷が上昇し、自動フェイルオーバーが発動した。
これまでリーダーだったインスタンスがライターに自動昇格し、ライター / リーダーロールが自動的に逆転してしまった。
結果、「ライターインスタンスのエンドポイント」として使っていたドメインが、リーダーインスタンスを参照するようになり、
冒頭の cannot execute UPDATE in a read-only transaction が発生。
負荷上昇およびフェイルオーバー発動までのタイムラグが、「⭐️ 数分経過後に停止」という症状につながったのだった。
なぜ起きてしまったのか
- 自動フェイルオーバーにより役割逆転する仕様を全く知らなかった... ^q^
- クラスターのライターエンドポイントを参照すべきなのを知らなかった... ^q^
根本解決
インスタンスエンドポイントの参照をやめて、クラスタエンドポイントを参照する。
クラスタのライターエンドポイントは、常にライターインスタンスを参照してくれる。
ライターとして設計したインスタンスが常にライターになるよう、自動フェイルオーバーの優先度を tier-0 にした。
0は特別な優先度であり、常にライターロールとして選択される。
変更前は1であり、状況次第でリーダーとなりうる優先度であった。
反省とまとめ
まさか勝手にロールが入れ替わり、エンドポイントの参照さきが変わるなんて、思ってもいませんでした。
これを契機により正しくRDSについて理解できました。
Postgres なのに port: 3306 使ってるのは、何だかお恥ずかしい限りです。



