23 ポイント 投稿者 xguru 2023-04-13 | 6件のコメント | WhatsAppで共有
  • RabbitMQを撤去し、PostgresDB上のSQLベースのキューに置き換え
  • 置き換えには半日ほどしかかからず、ソースコードは580行削減
  • それ以上に重要だったのは、安定性と復元力(Resiliency)が大幅に向上したこと
  • これはRabbitMQのようなキューシステムの問題を語る話ではなく、単純さを維持するための取り組みの一環
    • この記事を書いたPrequelは、大規模データパイプラインによってB2B SaaS企業が顧客のDBと同期するのを支援する製品
  • RabbitMQ + AQMP + Helm + GoLangラッパーで構成していたが、しばらくはうまく動いていたものの、問題が出始めた
    • メッセージ配送の遅延が長すぎて、メッセージがキャンセルされる事態が発生
    • コンシューマーがメッセージをプリフェッチすることで、現在のメッセージを完了するまで次のメッセージを抱え込む状況が発生
    • このプリフェッチを0にすると無限大になってしまうため、プリフェッチを無効化できない
    • メッセージを受け取って処理する作業の多くが長時間の処理(データ転送)であることから生じた問題
  • 何が起きているのかは正確に把握できたが、すぐに直す方法はなかった。本番環境の顧客に影響が出ていたため、待つことは不可能だった
  • そこでPostgresで1つのシンプルなテーブルを使い、読み書きする方式で動かすことにした
    • 読み書き時のRow-Level Lockを使って、1つのコンシューマーだけが作業を読み取れるよう保証
    • ばかばかしいほどシンプルだが、完璧に動作している
  • アプリケーションの状態がRabbitMQとPostgresに分断されず、1つに統合される利点もある

6件のコメント

 
galadbran 2023-04-15

私も MySQL で row level lock を使ってキューを直接実装し、長年プロダクトで問題なく動かしているのですが、
単純に複数のワーカーにキューに似た機能を提供しつつ、キュー内での待機中・進行中・失敗(完了なら削除)といった状態を含む payload を一緒に保存できることを望んでいました。

本文で短期間のうちに RabbitMQ から DB に切り替えたことを見ると、あえて別個の専用キューサービスの汎用性や多様な機能、設定の自由度が必要ではなかったからではないかと思います。

 
pseudojo 2023-04-15

手動ACK送信とDBトランザクションの間でズレが生じて問題になったようですが、
これをエンジニアリングで解決するのではなく、RabbitMQ自体を取り除く形にしたのが面白いですね。
RabbitMQに罪はないはずですが…

 
laracool 2023-04-13

https://news.ycombinator.com/item?id=35526846
コメントに多くの意見がありますね。

 
dddddd 2023-04-13

似たような方式で動作する https://github.com/pjongy/jasyncq のようなものもありますね

 
laracool 2023-04-13

同時に select される可能性がありそうですが、それをどのように解決したのか気になりますね。

 
dddddd 2023-04-13

row level lockと書かれていますね