時刻同期とクロックドリフト(NTP/PTP/TrueTime)
サーバー間の時刻ずれが原因のログ逆転や順序バグを根本から理解。NTPの限界、PTPの高精度同期、TrueTimeが不確実性区間で外部整合性を実現する原理を時間理論から押さえられます。
- 1.物理クロックは周波数の誤差(ドリフト)で常にずれ続け、2台の差(スキュー)も時々刻々変わる。NTPはネットワーク往復の非対称性で数ミリ秒の誤差が残り、巻き戻りも起きる。
- 2.PTPはハードウェアタイムスタンプと境界/透過クロックで往復遅延の非対称を抑え、サブマイクロ秒〜ナノ秒精度を狙う。ただし対応NIC・スイッチが前提。
- 3.SpannerのTrueTimeは時刻を点でなく不確実性区間 [earliest, latest] として返し、commit-waitで区間幅ぶん待つことで外部整合性(リアルタイム順序の保存)を保証する。
なぜ物理クロックは信用できないのか
サーバーに載っている時計の正体は、水晶振動子(クリスタル)が刻む一定周波数のパルスを数えるカウンタである。問題は、この発振周波数が公称値からずれることだ。温度・電圧・経年で発振がわずかに速い/遅い状態になり、実時間に対して時計が進む速度がずれる。これを クロックドリフト(drift) と呼ぶ。
ドリフトは「速度のずれ」なので、放置すれば誤差は時間に比例して累積する。安価な水晶のドリフト率はおおむね数十〜百 ppm(parts per million)程度で、仮に 50 ppm なら 1 秒あたり 50 マイクロ秒、1 日で 4 秒以上ずれる計算になる。一方、ある瞬間に2台の時計が指す値の差そのものを クロックスキュー(skew) と呼ぶ。ドリフト率が違えばスキューは時々刻々と変化するため、「いま合わせても次の瞬間にはまたずれる」。だからこそ継続的な 時刻同期 が必要になる。
ドリフトは時計の進む「速さ」のずれ(周波数誤差)、スキューはある瞬間の値の「差」。同期とは、参照クロックを基準にスキューを縮め(オフセット補正)、さらに進む速さを合わせる(周波数補正)ことの両方を指す。片方だけでは合わせ続けられない。
NTP の仕組みと、その精度の壁
NTP(Network Time Protocol)は、上位の基準時計(stratum 0/1)から階層的に時刻を配る方式だ。クライアントはサーバーとパケットを交換し、4つのタイムスタンプから オフセット(自分の時計のずれ)と 往復遅延 を推定する。
# t1: クライアント送信時刻(クライアント時計)
# t2: サーバー受信時刻(サーバー時計)
# t3: サーバー送信時刻(サーバー時計)
# t4: クライアント受信時刻(クライアント時計)
往復遅延 delay = (t4 - t1) - (t3 - t2)
オフセット offset = ((t2 - t1) + (t3 - t4)) / 2
このオフセット式が成り立つのは 行き帰りの片道遅延が等しい という仮定の上である。ここに NTP の精度の壁がある。経路の上り下りで遅延が非対称(混雑、キューイング、非対称ルーティング)だと、その差の半分がそのままオフセットの誤差になる。さらにカーネルでのパケット処理やソフトウェアでのタイムスタンプ取得もジッタを生む。結果、公衆インターネット越しでは数ミリ秒〜数十ミリ秒、LAN 内でも数百マイクロ秒程度の残差が普通に残る。
NTP がオフセットを補正するとき、時計を一気に飛ばす(step)と過去方向にも動く。つまり壁時計(wall clock)は単調増加しない。経過時間の測定や順序判定に壁時計を使うと、補正やうるう秒の瞬間に「後のイベントの方が小さい時刻」という逆転が起きる。経過時間には必ず単調増加クロック(monotonic clock)を使う。
ミリ秒級の誤差は、分散環境で2イベントの先後を物理時刻で判定するには大きすぎる。誤差より短い間隔で起きたイベントは順序が反転しうるため、物理時刻による順序付けは原理的に当てにならない。これが論理時計(/devops/logical-clocks/)が必要になる根本理由である。
PTP:ハードウェアで非対称を潰す
PTP(Precision Time Protocol, IEEE 1588)は、NTP の誤差源を局所で潰すことで桁違いの精度を狙う。鍵は2つある。
第一に ハードウェアタイムスタンプ。NIC の PHY 直近でパケットの送受信時刻を刻むため、OS スケジューラやソフトウェア処理によるジッタを排除できる。第二に、経路上のスイッチを時刻同期の協力者にする。境界クロック(Boundary Clock) は自身が同期してから配下に再配布し、透過クロック(Transparent Clock) はパケットが自分の中に滞留した時間(residence time)を測って補正フィールドに足し込む。これにより、スイッチのキューイング遅延という非対称・変動要因がオフセット推定から差し引かれる。
| 観点 | NTP | PTP(IEEE 1588) |
|---|---|---|
| 想定到達精度 | ミリ秒級(WANで数十ms、LANで百μs級) | サブマイクロ秒〜ナノ秒級 |
| タイムスタンプ | 主にソフトウェア(カーネル/ユーザー空間) | NIC のハードウェア |
| 経路機器の関与 | なし(遅延は推定のみ) | 境界/透過クロックが滞留時間を補正 |
| 主な誤差源 | 片道遅延の非対称・ジッタ | 残る非対称・発振安定度 |
| 前提コスト | 汎用、ほぼどこでも動く | 対応 NIC・スイッチが必要 |
PTP の精度は「経路上の非対称をどこまで観測・補正できたか」で決まる。だから対応スイッチ(boundary/transparent clock)をパス上に並べるほど効く一方、未対応機器が1段でも挟まると、その滞留時間が補正されず誤差として残る。高頻度取引やセルラー基地局、分散データベースのように厳しい順序保証が要る場面で採用される。
TrueTime:誤差を消すのではなく「明示する」
Google Spanner の TrueTime は発想が違う。どれだけ同期しても物理時計の誤差はゼロにはならない、という現実を受け入れ、時刻を点ではなく区間で返す API にした。
# TrueTime.now() は1点ではなく区間を返す
TT.now() -> [earliest, latest]
# 実時間 t_abs は必ず earliest <= t_abs <= latest に入ることを保証
# 区間幅 ε = (latest - earliest) / 2 は同期誤差の上界
GPS と原子時計を基準に各データセンターの誤差上界 ε(イプシロン)を有界に保ち、典型的には数ミリ秒以内に抑える。重要なのは「真の時刻はこの区間のどこかにある」と 保証付きで 言える点だ。誤差を隠さず、上界として API に持ち込む。
これを使って Spanner はトランザクションに 外部整合性(external consistency)、すなわちリアルタイムの先後をそのままコミット順序に反映する性質を与える。仕組みが commit-wait だ。
# トランザクション T のコミット手続き(要点)
s = TT.now().latest # コミットタイムスタンプ s を区間の上端に決める
... ロックを保持したまま ...
wait until TT.now().earliest > s # s が確実に「過去」になるまで待つ
release locks; commit # 区間幅ぶん(最大 2ε 程度)待ってから確定
ポイントは、コミットタイムスタンプ s を割り当てた後、いま現在が確実に s を過ぎる(TT.now().earliest > s)まで待ってからロックを解放することにある。こうすると、もし別のトランザクション T2 が T のコミット完了を実時間で見てから始まったなら、T2 のタイムスタンプは必ず T より大きくなる。つまり 「実時間で後に始まったトランザクションには必ず後のタイムスタンプ」 が成り立ち、タイムスタンプ順 = 実時間順が保証される。
待ち時間は区間幅、おおむね 2ε に比例する。ε を小さく保つほどコミット遅延(書き込みレイテンシ)が縮む。だから TrueTime は GPS・原子時計に投資して ε を絞ることに価値がある。時刻同期の精度がそのままデータベースの性能に直結する、という珍しい設計だ。
TrueTime が実現するのはまさに線形化可能性(linearizability)に対応する強い保証で、整合性モデルの最上位に位置づけられる(/devops/consistency-models/)。誤差を「消す」のではなく「上界として明示し、その幅ぶん待つ」ことで、不確実な物理時刻から確実な順序保証を引き出した点が核心である。
まとめ
- 物理クロックは発振周波数の誤差(ドリフト)でずれ続け、2台の差(スキュー)も変動する。だから継続的な同期が要る。壁時計は補正で巻き戻るため、経過時間や順序判定には使えない。
- NTP は4タイムスタンプからオフセットを推定するが、片道遅延の非対称が誤差に直結し、現実にはミリ秒級が残る。
- PTP はハードウェアタイムスタンプと境界/透過クロックで経路の非対称を補正し、サブマイクロ秒〜ナノ秒を狙う。対応機器が前提。
- TrueTime は時刻を不確実性区間
[earliest, latest]として返し、commit-wait で区間幅ぶん待つことで外部整合性(実時間順 = コミット順)を保証する。誤差を隠さず上界として扱うのが本質。 - ミリ秒級の物理同期では分散イベントの順序付けに不十分なため、論理時計(/devops/logical-clocks/)やログ突き合わせ(/devops/log-aggregation/)では物理時刻の限界を前提に分析する必要がある。
DevOps/インフラ Article
時刻同期とクロックドリフト(NTP/PTP/TrueTime)を実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
時刻同期
比較で見る軸
難易度: advanced / カテゴリ: DevOps/インフラ / タグ数: 5
導入後に効く点
PTPはハードウェアタイムスタンプと境界/透過クロックで往復遅延の非対称を抑え、サブマイクロ秒〜ナノ秒精度を狙う。ただし対応NIC・スイッチが前提。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- advanced
- カテゴリ
- DevOps/インフラ
- タグ数
- 5
判断チェックリスト
- 自社の用途が「時刻同期 / NTP」に近いか確認する。
- 強みである「物理クロックは周波数の誤差(ドリフト)で常にずれ続け、2台の差(スキュー)も時々刻々変わる。NTPはネットワーク往復の非対称性で数ミリ秒の誤差が残り、巻き戻りも起きる。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。