はじめに
こんにちは。コミューンでTechLeadをしているまつむらと申します。
今回は直近で私が取り組んだ取り組んだコミューンの技術的負債「水平スケーリング問題」の解消についてご紹介します。
発生した問題
水平スケーリング問題とは?
ひとことで言ってしまうと、単一のボトルネックにより水平スケーリングを行ってもパフォーマンスやスループットが改善しない状況です。 実際に発生していたケースについてもう少し具体的に書くと
- ある処理において、とても寿命の長いデータベース(RDB)のトランザクションが貼られている
- その処理の前半において、あるデータベースのテーブル(レコード)をロックしている
- 別のプロセスが同様の処理をしようとしても、データベースのロック待ちが発生する
ということが発生していました。 このような状態では、水平スケーリングしても(すなわちサーバ台数を増やしても)データベースのロック待ちがボトルネックになるため、 処理速度や処理可能数が向上しない状況になってしまっています。
どうして発生したか?
コミューンはローンチから5年以上経ちました。ゆえに以下のようなソースコードが散見されます。
- 4年以上前にコミットされたソースコード
- その一部は4年以上残り続けているTODOコメントやFIXMEコメント
- コミット主は今の結構えらい人
- あるいはもはや誰かわからない。聞くところによると一時期いた業務委託の人らしい
- 見るからに後付けで機能拡張されている
- それらが多重に重なりあって芸術品となっている
- 仕様解釈が実装箇所によって異なる(どっちが正しいんだ?)
- 当たり前のようにテストは書かれていない
どう取り組んだか
結論だけ言ってしまうと、トランザクションを細かく分離しました。 またイベント駆動型アーキテクチャへの切替を進めました。
仕様の分解
コミューンが提供しているのはコミュニティプラットフォームです。 そのため、コミュニティ活動を盛り上げる行動にはアドバンテージがつくようになっています。 例えば投稿に「いいね」をすると、いいねした人・された人両方にポイントが加算されるようになっています。 このように、表面上は単純な1つの機能に対し、多くの付随機能が動くようになっています。
もともとこれらすべての操作が1つのトランザクションで動いていました。 これらについて、トランザクションを分割しました。 加えてポイント処理など共通化できる部分についてはイベント駆動型で動くようにしました。
その結果、メイン機能のAPIレスポンスを早く返せることになったので、ユーザー体験の向上にも寄与できました。
リファクタリングという名のほぼ作り直し
付随機能をイベント化(すなわち非同期で実行)するまではよかったのですが、 一部機能において、付随機能の結果をAPIの戻り値にしている箇所がありました。 イベント化(非同期化)してしまうと、APIの戻り値にその結果を載せることはできません。 なので、既存機能との互換性を担保するべく、別の口のAPIを作成することにしました。
こうなるともはや作り直しというレベルです。 ゼロベースで理想的なアーキテクチャにて実装し直しました。
そして4年前の古いコードとは決別…はまだできていないのですが(すべての機能でイベント化できたわけではないので)、 ソースコードをきれいにする第一歩を着実に踏み出せたと思います。
まとめ
データベースのロックがボトルネックとなり水平スケーリングができない問題に立ち向かうことで、
- 動作の高速化
- 古いソースコードの削除
- よりメンテ性の高いコードの新規作成
ができました。
このようにコミューンでは、これからの開発を加速するための技術的負債の返済にも積極的に取り組んでいます。
最後に
コミューンでは恥ずかしながら多くの技術的負債が残されています。 簡単なリファクタリングではなく、リアーキテクチャやデータ再設計などから考えてくださる人を探しています。
興味を持ってくださった方は是非以下のフォームから申し込みください!