📜  克里斯蒂安算法

📅  最后修改于: 2021-05-06 18:42:26             🧑  作者: Mango

Cristian算法是一种时钟同步算法,用于通过客户端进程将时间与时间服务器同步。该算法在往返时间比精度短的低延迟网络中很容易使用,而易于冗余的分布式系统/应用程序与该算法不相上下。这里的往返时间是指请求开始到相应响应结束之间的持续时间。

下面是一个模拟cristian算法工作的图示:
克里斯蒂安的事前插图

算法:

1)客户端计算机上的进程在时间将请求获取时钟时间(服务器时间)的请求发送到时钟服务器T_0

2)Clock Server侦听客户端进程发出的请求,并以Clock server time的形式返回响应。

3)客户端进程及时从Clock Server获取响应T_1并使用以下公式计算同步的客户端时钟时间。

     \[ T_{CLIENT} = T_{SERVER} + (T_1 - T_0)/2 \]

在哪里T_{CLIENT}指的是同步时钟时间,
T_{SERVER}指服务器返回的时钟时间,
T_0指的是客户端进程发送请求的时间,
T_1指的是客户端进程收到响应的时间

以上公式的工作/可靠性:

T_1 - T_0指网络和服务器将请求传输到服务器,处理请求并将响应返回给客户端进程所花费的总时间,假设网络延迟为T_0T_1大致相等。

客户端的时间最多与实际时间不同(T_1 - T_0)/2秒。使用以上语句,我们可以得出结论,同步错误最多为(T_1 - T_0)/2秒。
因此,

     \[ error\, \epsilon\, [-(T_1 - T_0)/2, \, (T_1 - T_0)/2] \]

以下Python代码说明了Cristian算法的工作原理:
以下代码用于在本地计算机上启动时钟服务器的原型:

# Python3 program imitating a clock server
  
import socket
import datetime
    
# function used to initiate the Clock Server
def initiateClockServer():
  
    s = socket.socket()
    print("Socket successfully created")
        
    # Server port
    port = 8000
  
    s.bind(('', port))
       
    # Start listening to requests
    s.listen(5)      
    print("Socket is listening...")
        
    # Clock Server Running forever
    while True: 
        
       # Establish connection with client
       connection, address = s.accept()      
       print('Server connected to', address)
        
       # Respond the client with server clock time
       connection.send(str(
                    datetime.datetime.now()).encode())
        
       # Close the connection with the client process 
       connection.close()
  
  
# Driver function
if __name__ == '__main__':
  
    # Trigger the Clock Server    
    initiateClockServer()

输出:

Socket successfully created
Socket is listening...

以下代码用于在本地计算机上启动客户端进程的原型:

# Python3 program imitating a client process
  
import socket 
import datetime
from dateutil import parser
from timeit import default_timer as timer
  
# function used to Synchronize client process time
def synchronizeTime():
  
    s = socket.socket()          
        
    # Server port
    port = 8000     
        
    # connect to the clock server on local computer 
    s.connect(('127.0.0.1', port)) 
  
    request_time = timer()
  
    # receive data from the server
    server_time = parser.parse(s.recv(1024).decode())
    response_time = timer() 
    actual_time = datetime.datetime.now()
  
    print("Time returned by server: " + str(server_time))
  
    process_delay_latency = response_time - request_time
  
    print("Process Delay latency: " \
          + str(process_delay_latency) \
          + " seconds")
  
    print("Actual clock time at client side: " \
          + str(actual_time))
  
    # synchronize process client clock time
    client_time = server_time \
                      + datetime.timedelta(seconds = \
                               (process_delay_latency) / 2)
  
    print("Synchronized process client time: " \
                                        + str(client_time))
  
    # calculate synchronization error 
    error = actual_time - client_time
    print("Synchronization error : " 
                 + str(error.total_seconds()) + " seconds")
  
    s.close()        
  
  
# Driver function
if __name__ == '__main__':
  
    # synchronize time using clock server
    synchronizeTime()

输出:

Time returned by server: 2018-11-07 17:56:43.302379
Process Delay latency: 0.0005150819997652434 seconds
Actual clock time at client side: 2018-11-07 17:56:43.302756
Synchronized process client time: 2018-11-07 17:56:43.302637
Synchronization error : 0.000119 seconds

时钟同步的即兴性:

使用网络上的迭代测试,我们可以定义一个最小传输时间,以此可以制定一个改进的同步时钟时间(减少同步误差)。
在此,通过高度自信地定义最小传输时间,我们可以说服务器时间将
总是在之后产生T_0 + T_{min}T_{SERVER}将始终在之前生成T_1 - T_{min} , 在哪里T_{min}是最短传输时间,它是的最小值T_{REQUEST}T_{RESPONSE}在几次迭代测试中。同步错误可以表述为:

    \[ error\, \epsilon\, [-((T_1 - T_0)/2 - T_{min}), \, ((T_1 - T_0)/2 - T_{min})] \]

类似地,如果T_{REQUEST}T_{RESPONSE}相差相当长的时间,我们可以替代T_{min}经过T_{min1}T_{min2} , 在哪里T_{min1}是观察到的最短请求时间,并且T_{min2}是指在网络上观察到的最短响应时间。
在这种情况下,同步时钟时间可以计算为:

     \[ T_{CLIENT} = T_{SERVER} + (T_1 - T_0)/2 + (T_{min2} - T_{min1})/2 \]

因此,仅通过将响应时间和请求时间引入为单独的时间延迟,我们就可以改善时钟时间的同步性,从而减少总体同步误差。要运行的迭代测试的数量取决于观察到的整体时钟漂移。

参考:
1)https://en.wikipedia.org/wiki/Cristian%27s_algorithm
2)https://en.wikipedia.org/wiki/Round-trip_delay_time
3)https://www.geeksforgeeks.org/socket-programming-python
4)https://en.wikipedia.org/wiki/Clock_drift