TT Lab
はじめる
学ぶ 学習パス コース

見知らぬシステムの前で

反証できない仮説は当て推量だ

TT Labで続きを見る

一言でいうと

デバッグは、可能なものを1つ作り出す作業ではなく、可能な原因を1つだけ残るまで消していく作業です。消すためには、間違っていたときに何が見えるかが、あらかじめ決まっている必要があります。

なぜ必要なのか

「たまに遅いです」は診断できません。診断できるのは測定値だけです。そのため、顧客の話を受けたあとの最初の作業は、原因を探すことではなく、症状をコマンド1つで固定することです。

# 20회 반복해 실패율을 잰다
for i in $(seq 1 20); do
  curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8001/quote
done | sort | uniq -c

20回中5回が失敗するなら、障害は伝え聞いた話から数値に変わります。そしてこのコマンドは、以後のすべてのステップで、修理できたかどうかを判定する物差しとして再利用されます。直したと言うには、同じ物差しでもう一度測って0が出なければなりません。

再現できないことも情報です。特定のユーザー、特定の時間帯、特定の経路でだけ起きるという意味で、問いがそれだけ絞られます。

どう動くのか

数字が手に入ったら、次は仮説です。ところが、ほとんどの人がここで仮説と呼ぶものは、仮説ではありません。

「ネットワークの問題のようだ」は仮説ではありません。間違っていたときに何が見えるかが決まっていないので、どんな結果が出てもこの文は生き残ります。生き残る推測は、候補を減らしてくれません。

使える仮説は3行のものです。

가설:   요청이 게이트웨이와 애플리케이션 사이에서 끊긴다
맞다면: 게이트웨이 로그에 5초 타임아웃, 앱 로그에 해당 요청 아이디 없음
틀리면: 앱 로그에 요청이 들어와 있고 처리 중 실패한 흔적이 있음

このコードブロックの韓国語の3行は、順に、仮説がゲートウェイとアプリケーションの間でリクエストが途切れること、正しければゲートウェイのログに5秒のタイムアウトがありアプリのログに該当リクエストのIDがないこと、誤りならアプリのログにリクエストが入っていて処理中に失敗した痕跡があること、を述べています。

違いは後ろの2行にあります。確認することが指定されていて、予想と違う結果が出れば仮説が死にます。死ぬ仮説だけが候補を減らしてくれます。

3行を書くのに1分かかります。その1分がもったいなく見えますが、書かないと、30分後に自分がすでに除外したものをもう一度確認していることになります。複数の人が加わった障害では、効果がさらに大きくなります。除外リストが共有されないと、3人が同じことを3回確認します。

現場での姿

仮説を絞る最も信頼できる手順は、レイヤーを半分ずつ切ることです。リクエストが通る層を順に書き出し(クライアント、DNS、ロードバランサー、ゲートウェイ、アプリケーション、キャッシュ、データベース、外部連携)、ちょうど真ん中を選んで「ここまでは正常か」と問います。

8つの層を順に調べると平均4回見る必要があり、半分ずつ切れば3回以内に終わります。層が20に増えると、差は10回対5回になります。実際の障害では1回確認するのに数分かかるので、この差がそのまま復旧時間です。

ここでの核心は、正常かどうかを判定できる地点を選ぶことです。判定できない地点で切ると、半分を消せません。レイヤーを分ける目的は、正解を当てることではなく、見なくてよい場所を確定することです。

1つ例外があります。サービスがいま止まっている間は、診断より緩和が先です。ロールバックしたりトラフィックを切り替えたりして、出血を止めてから絞り込んでください。仮説をきれいに書くのは、ユーザーが待っていないときにすることです。

仮説を文として書く形式

頭の中の見当と、検証可能な仮説の違いは、文として書けるかどうかです。

❌ "DB 가 느린 것 같다"
   → 무엇을 확인하면 아닌 줄 알 수 있나? 정해져 있지 않다

✅ "결제 API 의 p95 지연 3초 중 2초 이상이 orders 테이블 조회에서 난다."
   확인 방법: 그 구간에 타이머를 넣고 100건을 재본다
   반증 조건: 조회가 200ms 이하면 이 가설은 틀렸다

このコードブロックの韓国語は、悪い例が「DBが遅いようだ」で何を確認すれば違うとわかるかが決まっておらず、良い例が「決済APIのp95レイテンシ3秒のうち2秒以上がordersテーブルの検索で生じる」で、確認方法はその区間にタイマーを入れて100件を測ること、反証条件は検索が200ms以下ならこの仮説は誤りであること、という意味です。

反証条件を先に書くことが核心です。それがないと、どんな結果が出ても「そうかもしれない」で済ませてしまい、調査が終わりません。

一度に1つだけ変える

複数を同時に変えると、何が効果があったのかわかりません。そして、たいてい1つは良くなり、1つは悪くなって、互いに相殺されます。

❌ 인덱스 추가 + 커넥션 풀 확대 + 캐시 도입 → 20% 좋아짐
   무엇 때문인가? 셋 중 하나는 오히려 해로웠을 수도 있다

✅ 인덱스 추가만 → 측정 → 되돌림 → 커넥션 풀만 → 측정 …

時間がなくて複数を一緒に入れなければならないなら、せめて元に戻せるように、それぞれを別のコミットにしておきます。あとで1つずつ外しながら確認できます。

測定を信頼できるものにする

同じ条件で3回測って、ぶれ幅を見ます。それより小さい改善は、改善ではありません。

전: 2.9s, 3.1s, 3.0s   → 폭 0.2s
후: 2.8s, 2.9s, 2.85s  → 폭 0.1s, 평균 0.15s 개선
→ 흔들림과 개선폭이 비슷하다. 아직 결론을 낼 수 없다

そして、測定そのものが対象を変えていないかを確認します。ログをオンにして測ればログが遅くなる原因になり、プロファイラーを付ければプロファイラーのコストが混ざります。できれば本番環境と同じ条件で、できなければその違いを記録に残します。

調査を終える条件

仮説の検証には終わりが必要です。次の3つのどれかなら終えます。

  1. 原因を特定し、元に戻して確認した場合: 最もよい終わり方です。
  2. 症状が消え、なぜ消えたのかがわかっている場合: 元に戻して確認するのが難しいときです。
  3. ここまで確認したが、さらに掘るコストが利益より大きい場合: これも正当な終わり方です。ただし、どこまで見たかを書いておかないと、次の人がそこから引き継げません。

3つ目を認めないと、調査が何日も長引きます。緩和策があって再発がまれなら、止めるのが正しい判断であることが多いです。

次のラボですること

「たまに動かない」という報告が入った見積もりAPIを相手に、失敗率を数字で固定し、3行の仮説を文書に書き、除外したレイヤーを根拠とともに記録したあと、同じ物差しでもう一度測って、比率が安定しているかを確認します。