计算机是如何进行时间同步的
WHY
在網絡世界中, 各個計算機之間要想協同工作, 時間同步是一個十分重要的基礎. 在計算機內部是有自己的時間的, 這個時間通過內部的晶體振蕩器差生的固定頻率, 來模擬時間流逝進行計算. 雖然頻率十分穩定, 但也是有誤差的, 雖然現在的工藝水平誤差已經十分小了. (關于震蕩的具體原理, 在此不表)
既然本地時間會產生誤差, 那么就會造成兩臺服務器的時間不一致. 要消除不一致, 就需要有一個統一的時間標準, 然后大家都以這個標準為基準時間并對自己的本地時間進行校準, 既協調國際時(UTC), 關于這個時間是怎么來的, 不是本文討論的重點.
好了, 現在, 在另一個地方, 有一個標準時間, 如何將這個標準時間通過網絡同步到你的本地計算機呢? 如何在同步的過程中, 盡量消除網絡延遲帶來的影響呢?
HOW
如果直接進行網絡請求, 然后拿到一個返回時間戳并修改本地時間可不可以呢? 顯然不行. 別忘了, 包在網絡中傳輸也是需要時間的, 這個請求從對方發出, 至到達本地計算機, 經過了多久你并不知道, 這中間的延遲會嚴重影響時間校準的結果.
OK, 現在遇到的問題就是網絡延時了, 如果能夠消除網絡延遲, 就可以精準同步了, 但以現在的技術水平是做不到的. 既然延時無法消除, 如果我們能夠知道這個延時的時間, 也可以通過計算消除延遲的影響.
包在網絡中的傳輸大致如圖:
其中各值如下:
- C1: 客戶端發出請求的本地時間
- C2: 客戶端接收到返回的本地時間
- S1: 時間服務器接收到請求的服務器時間
- S2: 時間服務器發出響應的服務器時間
- SC1: 客戶端發出請求時的服務器時間
- SC2: 客戶端接收到返回的服務器時間
- CS1: 時間服務器收到請求時的本地時間
- CS2: 時間服務器發出響應時的本地時間
我們現在的目的看起來很簡單, 就是在接受到返回的時候, 將本地時間C2 校準為SC2. 首先要明確的是, C2和SC2是不想等的, 否則二者時間相同就不需要校準了嘛.
首先, 我們本地知道的信息有: C1, C2, 可以令服務器在返回結果中, 告訴我們S1, S2. 并且, 我們假定網絡中的延時是基本固定的, 既S1-C1=C2-S2.
好了, 現在已經成功的將其轉換成了一道數學題. 是不是突然發現簡單了許多? 步驟如下:
- da = (C2 - C1) - (S2 - S1) # 總延時時長
- d = da / 2 # 單次延時時長
- SC1 = S1 - d
- SC2 = SC1 + (C2 - C1)
如何? 很巧妙的將網絡延時消除了.
以上, 就是時間同步ntp協議的內容了. 不過, 如此同步的時間也是有誤差的, 首先上面就假設了往返的網絡延時相同, 如果延時不對稱, 則同步結果就會不準確, 而且, 協議跑在應用層, 從物理層到應用層之間的時延也會影響最終結果.
應用
我們在實際實際編程中, 經常會寫入類似這樣的代碼:
$t1 = time(); // do someting... $t2 = time();如果, 在獲取$t1變量后, 正巧進行了時間同步, 那么$t2有可能小于$t1, 豈不是很詭異. 不過還好, 有不同的同步方式供我們選擇, 以下在Ubuntu系統上進行了測試.
- ntp: 時間平滑過度, 保證本地時間遞增, 一點點減少本地與遠端的時間差.
- ntpdate: 立即進行同步, 這種功能情況就可能出現上面$t2小于$t1的場景
不過, 在我的服務器Ubuntu 18上, 已經默認不再使用ntp工具了, 轉而使用timedatectl, 其內部協議是一樣的, 有關timedatectl的詳細內容可以參考一下官網的說明: https://ubuntu.com/server/docs/network-ntp
總結
以上是生活随笔為你收集整理的计算机是如何进行时间同步的的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 用数据结构c语言写成绩排序,C语言数据结
- 下一篇: 23种设计模式之工厂方法模式