views:

1895

answers:

7

I'm looking into writing a simple synchronization ability into my app and one of the concerns that has popped up is synchronization of time between two remote computers, each with their own clock (in particular concerning the modification dates of files/objects).

I'm sure a lot of research has been done on this topic and don't want to get too theoretical, but I'm wondering if there are any accepted best practices for minimizing temporal discrepancies between remote clocks?

For example, a start is to always use universal time (UTC) as that avoids timezone problems, but there is no guarantee that two computers will have exactly the same system time. Luckily the work I'm doing isn't very fine-grained, so it's not a terribly important concern, but I'm still curious nonetheless.

One solution would be to always use the same clock on both ends, such as a global time server, rather than the local system clock. Presumably this (combined with shared resource locks) could guarantee no accidental overlap of synchronized time, but it's not very practical.

One thought that just popped into my head would be to synchronize each node (each client) with an offset calculated at some point prior, perhaps by calculating the offset of the system clock with a global time server. This would only need to be done occasionally as the offset itself would not likely change greatly over a short period of time.

Update: Let me just add that I'm not interested in actually synchronizing the system clocks of two computers--I'll presume that the operating system will handle this in most cases. This is just a question of how to ensure two instances of an application are using synchronized times, though in this day and age I suppose the system clocks would almost assuredly be synchronized to within some very small delta anyway.

+3  A: 

Synchronize them with NTP Network Time Protocol.

What platform are you on?

With NTP you can synchronize the time of your computers with atomic clocks and use the official time of the world.

some
.NET, but it's more of a theory question than anything.
chaiguy
+8  A: 

Look at "Network Time Protocol" (NTP) specification.

Mehrdad Afshari
+3  A: 

Instead of writing code to synchronise the clocks, wouldn't it be possible to just run an ntp client on both machines?

Alternatively, if the above is not possible and your app is running with sufficient privileges to set the time, I would be tempted to implement a minimal NTP client right in the application and try to sync it against a public server. Just don't hardcode someone's private server in...

Timo Geusch
I'm not super keen on changing the user's system clock.
chaiguy
A: 

any networked machine should use NTP. all modern systems include an easy way to setup this. the only issue should be choosing a specific server, if you need a little extra precision; but it's already in the millisecond range, so i don't care and usually just point to pool.ntp.org

Javier
+2  A: 

One thing we do is essentially offload all timing operations to the 'host' machine. For example, if you have 20 servers that all share a DB, use the DB's time. If you have a central server and a million client machines, then the client machines shouldn't be responsible for timing anything; do all your syncing server-side. In a truly 'distributed' environment, like a P2P network or something, use the machine that most directly 'owns' the resource in question (the actual PC the file you want to write) to syncronize/control access to the file.

GWLlosa
These are good suggestions, and more the kind of answer I was looking for. However, suppose that neither computer owns the resource and it is truly shared. Furthermore, neither computer has access to the other computer directly and so cannot use its clock.
chaiguy
+8  A: 

Relying on NTP for your application as others have recommended is the easy fudge. The correct approach is to use Lamport's distributed clock synchronization algorithm. It is explained in his classic 1978 paper Time, clocks, and the ordering of events in a distributed system.

Diomidis Spinellis
Thanks for the link, that looks very interesting!
chaiguy
+1  A: 

This is a problem I currently have to solve in respect of unsophisticated end-users who can do many things to upset the sensible suggestions made by the previous contributors. An unsophisticated end-user can do at least these things, and more:

1) Not have enough computing knowledge to be able to set up ntp time synchronisation

2) Set their computer time clock to a house clock or mobile phone clock that is incorrect

3) In Windows XP accidentally disable ntp time sync and not know how to enable it again, or have their computer date set wrongly, in which case Windows ntp doesn't work

4) The computer bios battery has gone flat so the pc always starts up in 1970!

5) The user takes their laptop abroad and temporarily sets the laptop clock to local time but does not change the time zone, so now the pc will return incorrect utc time!!!

So your program itself will have to manage the time, and of course you want to do that with minimum overhead.

Let's assume two end-users running the your programs need the programs to do something at the same absolute time in the future.

I propose this scheme, which takes some ideas from the way cron jobs work, I would be happy if anyone can suggest improvements to the idea.

1) When your application starts, it synchronises its own internal utc time to ntp via a soap call to a third party server or to your own time server (which you can yourself keep on time with ntp).

2) After that it adds on elapsed time from the system clock to maintain the time. If requirements are stringent you may need to repeat the ntp synchronisation at intervals.

3) The application then looks at a list of future jobs that it needs to do on time. It needs to know the earliest job.

4) It then creates a thread which it puts to sleep for the length of time ahead of the earliest job, less a safety margin, which depending on your requirements could be 10 minutes in advance, an hour or two in advance etc.

5) When the thread wakes up, it rechecks the absolute time with a further soap call, and then relies on the system time clock to add on elapsed time until it reaches the time when the first job should be carried out.

6) As soon as the job is triggered (run it in another thread) the time-monitoring thread calculates the next task time ahead and puts itself to sleep again for the duration.

Enhancements to the idea:

1) A user may close down your application before the due job, so you may need a background process or service, which uses the same synchronisation scheme above, to independently monitor your job lists, stored in a database or file, and start up the application in time. (In Windows, spawn the application process)

2) Your application may be adding newer, earlier jobs on the fly, or deleting jobs, so your sleeping thread will probably need to be wakeable to recalculate for the new earlier job, or for the job following the deleted job. In Win32 you would do this by your thread waiting with timeout on an Event, which you set to force it to recalculate the sleep time. In Linux no doubt there is a similar mechanism.

3) For the Soap call to get the time keep a note of when the Soap is sent and when the response is received. If the turnaround time is too long, you cannot rely on the time and may need to repeat the call, or you can compromise. For example, if the Soap says the computer clock is 5 minutes fast, but the Soap call itself took a minute to reply, then you can only say for certain that the computer clock is at least 4 minutes fast.

Sahlan Diver