Goの同時関数呼び出しを1回で済ませられるライブラリ 「SingleFlight」 が便利
tl;dr
- 高頻度に叩かれがちな重めの取得系関数呼び出しはSingleFlight を使おう!
動機
- Cacheが切れた途端Mysqlに大量のアクセスが流れ込み、LAが上がる現象をどう回避しようか考えていたときに、SingleFlight というライブラリを見つけたため使えるか計測してみた。
SingleFlightって何?
- 複数人が同じ関数呼び出しを同時にした場合、最初の1人だけ関数を実行し、残りの人は、最初の人が実行した関数呼び出しが終了するまで待機し、最初の1人が関数呼び出しの結果を取得したら、待機してる残りの人に結果をシェアしてくれる。
- Goからリソースへのアクセスが同時に行われても、1本だけでよくなるから嬉しい。効率的。
- もちろんイミュータブルな関数じゃないと使えない。
計測環境
計測対象
- 3本のMysqlQueryを叩き、合計が500ms位かかるGo API
計測ツール
計測コマンド
- 秒間100リクエスト を1分間 (叩きすぎかな?)
echo "GET http://localhost:1323/hoge" | vegeta attack -duration=1m -rate=100 | vegeta report -reporter=plot > plot.html
計測パターン
- そのまま
- 10秒毎で切れるMemCache を挟む
- SingleFlight を挟む
- 10秒毎で切れるMemCache + SingleFlight を挟む
計測結果
-
そのまま
-
10秒毎で切れるMemCache を挟む
-
SingleFlight を挟む
-
10秒毎で切れるMemCache + SingleFlight を挟む
結論
- 重めのMysqlを叩く + 高頻度リクエスト => SingleFlightは必須。