502 lines
35 KiB
HTML
502 lines
35 KiB
HTML
|
|
|||
|
<!DOCTYPE html>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<html lang="en">
|
|||
|
<head>
|
|||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|||
|
|
|||
|
<title>9.5. Timing in Distributed Environments — Computer Systems Fundamentals</title>
|
|||
|
|
|||
|
<link rel="stylesheet" href="_static/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous" />
|
|||
|
<link rel="stylesheet" href="_static/css/pygments.css" type="text/css" />
|
|||
|
<link rel="stylesheet" href="_static/css/normalize.css" type="text/css" />
|
|||
|
<link rel="stylesheet" href="../../../JSAV/css/JSAV.css" type="text/css" />
|
|||
|
<link rel="stylesheet" href="../../../lib/odsaMOD-min.css" type="text/css" />
|
|||
|
<link rel="stylesheet" href="_static/css/jquery-1.11.4-smoothness-ui.css" type="text/css" />
|
|||
|
<link rel="stylesheet" href="../../../lib/odsaStyle-min.css" type="text/css" />
|
|||
|
<link rel="stylesheet" href="_static/css/csf.css" type="text/css" />
|
|||
|
|
|||
|
<style>
|
|||
|
.underline { text-decoration: underline; }
|
|||
|
</style>
|
|||
|
|
|||
|
<script type="text/javascript">
|
|||
|
var DOCUMENTATION_OPTIONS = {
|
|||
|
URL_ROOT: './',
|
|||
|
VERSION: '0.4.1',
|
|||
|
COLLAPSE_INDEX: false,
|
|||
|
FILE_SUFFIX: '.html',
|
|||
|
HAS_SOURCE: true
|
|||
|
};
|
|||
|
</script>
|
|||
|
|
|||
|
<script type="text/x-mathjax-config">
|
|||
|
MathJax.Hub.Config({
|
|||
|
tex2jax: {
|
|||
|
inlineMath: [['$','$'], ['\\(','\\)']],
|
|||
|
displayMath: [ ['$$','$$'], ["\\[","\\]"] ],
|
|||
|
processEscapes: true
|
|||
|
},
|
|||
|
"HTML-CSS": {
|
|||
|
scale: "80"
|
|||
|
}
|
|||
|
});
|
|||
|
</script>
|
|||
|
<link rel="shortcut icon" href="_static/favicon.ico"/>
|
|||
|
<link rel="index" title="Index" href="genindex.html" />
|
|||
|
<link rel="search" title="Search" href="search.html" />
|
|||
|
<link rel="index" title="Computer Systems Fundamentals" href="index.html" />
|
|||
|
<link rel="next" title="6. Reliable Data Storage and Location" href="DistDataStorage.html" />
|
|||
|
<link rel="prev" title="4. Limits of Parallelism and Scaling" href="Scaling.html" />
|
|||
|
|
|||
|
</head><body>
|
|||
|
|
|||
|
<nav class="navbar navbar-expand-md navbar-dark navbar-custom fixed-top">
|
|||
|
|
|||
|
<a class="navbar-brand py-0" href="index.html"><img src="_static/CSF-Logo-Square-Text.png" alt="OpenCSF Logo" height="40em" class="py-1 px-2 mb-0 align-center rounded-lg bg-white" /></a>
|
|||
|
<!-- Show a navbar toggler on mobile -->
|
|||
|
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#defaultNavbars" aria-controls="defaultNavbars" aria-expanded="false" aria-label="Toggle navigation">
|
|||
|
<span class="navbar-toggler-icon"></span>
|
|||
|
</button>
|
|||
|
<div class="collapse navbar-collapse" id="defaultNavbars">
|
|||
|
<ul class="navbar-nav mr-auto">
|
|||
|
<li class="nav-item dropdown">
|
|||
|
<a class="nav-link dropdown-toggle jmu-gold rounded" href="DistTiming.html#" id="navbarDropdownChapters" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Contents</a>
|
|||
|
<div class="dropdown-menu scrollable-menu" role="menu" aria-labelledby="navbarDropdownChapters">
|
|||
|
<a class="dropdown-item" tabindex="-1" href="DistTiming.html#"><b>Chapter 1</b></a>
|
|||
|
<a class="dropdown-item" href="IntroConcSysOverview.html"> 1.1. Introduction to Concurrent Systems</a>
|
|||
|
<a class="dropdown-item" href="SysAndModels.html"> 1.2. Systems and Models</a>
|
|||
|
<a class="dropdown-item" href="Themes.html"> 1.3. Themes and Guiding Principles</a>
|
|||
|
<a class="dropdown-item" href="Architectures.html"> 1.4. System Architectures</a>
|
|||
|
<a class="dropdown-item" href="StateModels.html"> 1.5. State Models in UML</a>
|
|||
|
<a class="dropdown-item" href="SequenceModels.html"> 1.6. Sequence Models in UML</a>
|
|||
|
<a class="dropdown-item" href="StateModelImplementation.html"> 1.7. Extended Example: State Model Implementation</a>
|
|||
|
<div class="dropdown-divider"></div>
|
|||
|
<a class="dropdown-item disabled"><b>Chapter 2</b></a>
|
|||
|
<a class="dropdown-item" href="ProcessesOverview.html"> 2.1. Processes and OS Basics</a>
|
|||
|
<a class="dropdown-item" href="Multiprogramming.html"> 2.2. Processes and Multiprogramming</a>
|
|||
|
<a class="dropdown-item" href="KernelMechanics.html"> 2.3. Kernel Mechanics</a>
|
|||
|
<a class="dropdown-item" href="Syscall.html"> 2.4. System Call Interface</a>
|
|||
|
<a class="dropdown-item" href="ProcessCycle.html"> 2.5. Process Life Cycle</a>
|
|||
|
<a class="dropdown-item" href="UnixFile.html"> 2.6. The UNIX File Abstraction</a>
|
|||
|
<a class="dropdown-item" href="EventsSignals.html"> 2.7. Events and Signals</a>
|
|||
|
<a class="dropdown-item" href="Extended2Processes.html"> 2.8. Extended Example: Listing Files with Processes</a>
|
|||
|
<div class="dropdown-divider"></div>
|
|||
|
<a class="dropdown-item disabled"><b>Chapter 3</b></a>
|
|||
|
<a class="dropdown-item" href="IPCOverview.html"> 3.1. Concurrency with IPC</a>
|
|||
|
<a class="dropdown-item" href="IPCModels.html"> 3.2. IPC Models</a>
|
|||
|
<a class="dropdown-item" href="Pipes.html"> 3.3. Pipes and FIFOs</a>
|
|||
|
<a class="dropdown-item" href="MMap.html"> 3.4. Shared Memory With Memory-mapped Files</a>
|
|||
|
<a class="dropdown-item" href="POSIXvSysV.html"> 3.5. POSIX vs. System V IPC</a>
|
|||
|
<a class="dropdown-item" href="MQueues.html"> 3.6. Message Passing With Message Queues</a>
|
|||
|
<a class="dropdown-item" href="ShMem.html"> 3.7. Shared Memory</a>
|
|||
|
<a class="dropdown-item" href="IPCSems.html"> 3.8. Semaphores</a>
|
|||
|
<a class="dropdown-item" href="Extended3Bash.html"> 3.9. Extended Example: Bash-lite: A Simple Command-line Shell</a>
|
|||
|
<div class="dropdown-divider"></div>
|
|||
|
<a class="dropdown-item disabled"><b>Chapter 4</b></a>
|
|||
|
<a class="dropdown-item" href="SocketsOverview.html"> 4.1. Networked Concurrency</a>
|
|||
|
<a class="dropdown-item" href="FiveLayer.html"> 4.2. The TCP/IP Internet Model</a>
|
|||
|
<a class="dropdown-item" href="NetApps.html"> 4.3. Network Applications and Protocols</a>
|
|||
|
<a class="dropdown-item" href="Sockets.html"> 4.4. The Socket Interface</a>
|
|||
|
<a class="dropdown-item" href="TCPSockets.html"> 4.5. TCP Socket Programming: HTTP</a>
|
|||
|
<a class="dropdown-item" href="UDPSockets.html"> 4.6. UDP Socket Programming: DNS</a>
|
|||
|
<a class="dropdown-item" href="AppBroadcast.html"> 4.7. Application-Layer Broadcasting: DHCP</a>
|
|||
|
<a class="dropdown-item" href="Extended4CGI.html"> 4.8. Extended Example: CGI Web Server</a>
|
|||
|
<div class="dropdown-divider"></div>
|
|||
|
<a class="dropdown-item disabled"><b>Chapter 5</b></a>
|
|||
|
<a class="dropdown-item" href="InternetOverview.html"> 5.1. The Internet and Connectivity</a>
|
|||
|
<a class="dropdown-item" href="AppLayer.html"> 5.2. Application Layer: Overlay Networks</a>
|
|||
|
<a class="dropdown-item" href="TransLayer.html"> 5.3. Transport Layer</a>
|
|||
|
<a class="dropdown-item" href="NetSec.html"> 5.4. Network Security Fundamentals</a>
|
|||
|
<a class="dropdown-item" href="NetLayer.html"> 5.5. Network Layer: IP</a>
|
|||
|
<a class="dropdown-item" href="LinkLayer.html"> 5.6. Link Layer</a>
|
|||
|
<a class="dropdown-item" href="Wireless.html"> 5.7. Wireless Connectivity: Wi-Fi, Bluetooth, and Zigbee</a>
|
|||
|
<a class="dropdown-item" href="Extended5DNS.html"> 5.8. Extended Example: DNS client</a>
|
|||
|
<div class="dropdown-divider"></div>
|
|||
|
<a class="dropdown-item disabled"><b>Chapter 6</b></a>
|
|||
|
<a class="dropdown-item" href="ThreadsOverview.html"> 6.1. Concurrency with Multithreading</a>
|
|||
|
<a class="dropdown-item" href="ProcVThreads.html"> 6.2. Processes vs. Threads</a>
|
|||
|
<a class="dropdown-item" href="RaceConditions.html"> 6.3. Race Conditions and Critical Sections</a>
|
|||
|
<a class="dropdown-item" href="POSIXThreads.html"> 6.4. POSIX Thread Library</a>
|
|||
|
<a class="dropdown-item" href="ThreadArgs.html"> 6.5. Thread Arguments and Return Values</a>
|
|||
|
<a class="dropdown-item" href="ImplicitThreads.html"> 6.6. Implicit Threading and Language-based Threads</a>
|
|||
|
<a class="dropdown-item" href="Extended6Input.html"> 6.7. Extended Example: Keyboard Input Listener</a>
|
|||
|
<a class="dropdown-item" href="Extended6Primes.html"> 6.8. Extended Example: Concurrent Prime Number Search</a>
|
|||
|
<div class="dropdown-divider"></div>
|
|||
|
<a class="dropdown-item disabled"><b>Chapter 7</b></a>
|
|||
|
<a class="dropdown-item" href="SynchOverview.html"> 7.1. Synchronization Primitives</a>
|
|||
|
<a class="dropdown-item" href="CritSect.html"> 7.2. Critical Sections and Peterson's Solution</a>
|
|||
|
<a class="dropdown-item" href="Locks.html"> 7.3. Locks</a>
|
|||
|
<a class="dropdown-item" href="Semaphores.html"> 7.4. Semaphores</a>
|
|||
|
<a class="dropdown-item" href="Barriers.html"> 7.5. Barriers</a>
|
|||
|
<a class="dropdown-item" href="Condvars.html"> 7.6. Condition Variables</a>
|
|||
|
<a class="dropdown-item" href="Deadlock.html"> 7.7. Deadlock</a>
|
|||
|
<a class="dropdown-item" href="Extended7Events.html"> 7.8. Extended Example: Event Log File</a>
|
|||
|
<div class="dropdown-divider"></div>
|
|||
|
<a class="dropdown-item disabled"><b>Chapter 8</b></a>
|
|||
|
<a class="dropdown-item" href="SynchProblemsOverview.html"> 8.1. Synchronization Patterns and Problems</a>
|
|||
|
<a class="dropdown-item" href="SynchDesign.html"> 8.2. Basic Synchronization Design Patterns</a>
|
|||
|
<a class="dropdown-item" href="ProdCons.html"> 8.3. Producer-Consumer Problem</a>
|
|||
|
<a class="dropdown-item" href="ReadWrite.html"> 8.4. Readers-Writers Problem</a>
|
|||
|
<a class="dropdown-item" href="DiningPhil.html"> 8.5. Dining Philosophers Problem and Deadlock</a>
|
|||
|
<a class="dropdown-item" href="CigSmokers.html"> 8.6. Cigarette Smokers Problem and the Limits of Semaphores and Locks</a>
|
|||
|
<a class="dropdown-item" href="Extended8ModExp.html"> 8.7. Extended Example: Parallel Modular Exponentiation</a>
|
|||
|
<div class="dropdown-divider"></div>
|
|||
|
<a class="dropdown-item disabled"><b>Chapter 9</b></a>
|
|||
|
<a class="dropdown-item" href="ParallelDistributedOverview.html"> 9.1. Parallel and Distributed Systems</a>
|
|||
|
<a class="dropdown-item" href="ParVConc.html"> 9.2. Parallelism vs. Concurrency</a>
|
|||
|
<a class="dropdown-item" href="ParallelDesign.html"> 9.3. Parallel Design Patterns</a>
|
|||
|
<a class="dropdown-item" href="Scaling.html"> 9.4. Limits of Parallelism and Scaling</a>
|
|||
|
<a class="dropdown-item" href="DistTiming.html"> 9.5. Timing in Distributed Environments</a>
|
|||
|
<a class="dropdown-item" href="DistDataStorage.html"> 9.6. Reliable Data Storage and Location</a>
|
|||
|
<a class="dropdown-item" href="DistConsensus.html"> 9.7. Consensus in Distributed Systems</a>
|
|||
|
<a class="dropdown-item" href="Extended9Blockchain.html"> 9.8. Extended Example: Blockchain Proof-of-Work</a>
|
|||
|
<div class="dropdown-divider"></div>
|
|||
|
<a class="dropdown-item disabled"><b>Appendix A</b></a>
|
|||
|
<a class="dropdown-item" href="CLangOverview.html"> A.1. C Language Reintroduction</a>
|
|||
|
<a class="dropdown-item" href="Debugging.html"> A.2. Documentation and Debugging</a>
|
|||
|
<a class="dropdown-item" href="BasicTypes.html"> A.3. Basic Types and Pointers</a>
|
|||
|
<a class="dropdown-item" href="Arrays.html"> A.4. Arrays, Structs, Enums, and Type Definitions</a>
|
|||
|
<a class="dropdown-item" href="Functions.html"> A.5. Functions and Scope</a>
|
|||
|
<a class="dropdown-item" href="Pointers.html"> A.6. Pointers and Dynamic Allocation</a>
|
|||
|
<a class="dropdown-item" href="Strings.html"> A.7. Strings</a>
|
|||
|
<a class="dropdown-item" href="FunctionPointers.html"> A.8. Function Pointers</a>
|
|||
|
<a class="dropdown-item" href="Files.html"> A.9. Files</a>
|
|||
|
</div>
|
|||
|
</li>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
</ul>
|
|||
|
</div>
|
|||
|
|
|||
|
<ul class="navbar-nav flex-row ml-md-auto d-none d-md-flex">
|
|||
|
<li class="nav-item"><a class="nav-link jmu-gold" href="https://w3.cs.jmu.edu/kirkpams/OpenCSF/Books/csf/source/DistTiming.rst"
|
|||
|
target="_blank" rel="nofollow">Show Source</a></li>
|
|||
|
|
|||
|
</ul>
|
|||
|
</nav>
|
|||
|
|
|||
|
|
|||
|
<div class="container center">
|
|||
|
«  <a id="prevmod" href="Scaling.html">9.4. Limits of Parallelism and Scaling</a>
|
|||
|
  ::  
|
|||
|
<a class="uplink" href="index.html">Contents</a>
|
|||
|
  ::  
|
|||
|
<a id="nextmod" href="DistDataStorage.html">9.6. Reliable Data Storage and Location</a>  »
|
|||
|
|
|||
|
</div>
|
|||
|
<br />
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<script type="text/javascript" src="_static/js/jquery-2.1.4.min.js"></script>
|
|||
|
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
|||
|
<script type="text/javascript" src="_static/js/jquery-1.11.4-ui.min.js"></script>
|
|||
|
<script type="text/javascript" src="_static/js/forge-0.7.0.min.js"></script>
|
|||
|
<script type="text/javascript" src="../../../JSAV/lib/jquery.transit.js"></script>
|
|||
|
<script type="text/javascript" src="../../../JSAV/lib/raphael.js"></script>
|
|||
|
<script type="text/javascript" src="../../../JSAV/build/JSAV-min.js"></script>
|
|||
|
<script type="text/javascript" src="_static/js/config.js"></script>
|
|||
|
<script type="text/javascript" src="../../../lib/odsaUtils-min.js"></script>
|
|||
|
<script type="text/javascript" src="../../../lib/odsaMOD-min.js"></script>
|
|||
|
<script type="text/javascript" src="_static/js/d3-4.13.0.min.js"></script>
|
|||
|
<script type="text/javascript" src="_static/js/d3-selection-multi.v1.min.js"></script>
|
|||
|
<script type="text/javascript" src="../../../lib/dataStructures.js"></script>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<div class="container">
|
|||
|
|
|||
|
<script>ODSA.SETTINGS.DISP_MOD_COMP = true;ODSA.SETTINGS.MODULE_NAME = "DistTiming";ODSA.SETTINGS.MODULE_LONG_NAME = "Timing in Distributed Environments";ODSA.SETTINGS.MODULE_CHAPTER = "Parallel and Distributed Systems"; ODSA.SETTINGS.BUILD_DATE = "2021-06-01 15:31:51"; ODSA.SETTINGS.BUILD_CMAP = false;JSAV_OPTIONS['lang']='en';JSAV_EXERCISE_OPTIONS['code']='java';</script><div class="section" id="timing-in-distributed-environments">
|
|||
|
<h1>9.5. Timing in Distributed Environments<a class="headerlink" href="DistTiming.html#timing-in-distributed-environments" title="Permalink to this headline">¶</a></h1>
|
|||
|
<p>As we have noted in this and previous chapters, concurrency and parallelism
|
|||
|
introduce an element of nondeterminism that can complicate the design,
|
|||
|
implementation, and execution of software. Once multiple threads or processes
|
|||
|
are running independently, the order in which key events are processed can
|
|||
|
become unpredictable. However, as individual computers possess a single,
|
|||
|
universal system clock that can be shared, it would be straightforward to use
|
|||
|
synchronization primitives to keep an orderly log of key events, as shown in
|
|||
|
<a class="reference external" href="DistTiming.html#cl9-8">Code Listing 9.8</a>.</p>
|
|||
|
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl9-8"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
|
|||
|
2
|
|||
|
3
|
|||
|
4
|
|||
|
5
|
|||
|
6
|
|||
|
7
|
|||
|
8
|
|||
|
9
|
|||
|
10
|
|||
|
11
|
|||
|
12
|
|||
|
13
|
|||
|
14
|
|||
|
15
|
|||
|
16
|
|||
|
17
|
|||
|
18
|
|||
|
19
|
|||
|
20
|
|||
|
21</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 9.8:</span>
|
|||
|
<span class="cm"> Sample routine for atomic log file append </span>
|
|||
|
<span class="cm"> */</span>
|
|||
|
|
|||
|
<span class="kt">void</span>
|
|||
|
<span class="nf">append_log</span> <span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="n">message</span><span class="p">)</span>
|
|||
|
<span class="p">{</span>
|
|||
|
<span class="cm">/* Uses a global variable for locking the log */</span>
|
|||
|
<span class="n">pthread_mutex_lock</span> <span class="p">(</span><span class="n">log_lock</span><span class="p">);</span>
|
|||
|
<span class="k">struct</span> <span class="n">timespec</span> <span class="n">current_time</span><span class="p">;</span>
|
|||
|
<span class="n">clock_gettime</span> <span class="p">(</span><span class="n">CLOCK_MONOTONIC</span><span class="p">,</span> <span class="o">&</span><span class="n">current_time</span><span class="p">);</span>
|
|||
|
<span class="kt">FILE</span> <span class="o">*</span><span class="n">file</span> <span class="o">=</span> <span class="n">fopen</span> <span class="p">(</span><span class="n">SYSTEM_LOG_FILE</span><span class="p">,</span> <span class="s">"a"</span><span class="p">);</span>
|
|||
|
<span class="k">if</span> <span class="p">(</span><span class="n">file</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span>
|
|||
|
<span class="p">{</span>
|
|||
|
<span class="n">fprintf</span> <span class="p">(</span><span class="n">file</span><span class="p">,</span> <span class="s">"%lld.%09ld %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span>
|
|||
|
<span class="p">(</span><span class="kt">long</span> <span class="kt">long</span><span class="p">)</span> <span class="n">current_time</span><span class="p">.</span><span class="n">tv_sec</span><span class="p">,</span>
|
|||
|
<span class="n">current_time</span><span class="p">.</span><span class="n">tv_nsec</span><span class="p">,</span> <span class="n">message</span><span class="p">);</span>
|
|||
|
<span class="n">fclose</span> <span class="p">(</span><span class="n">file</span><span class="p">);</span>
|
|||
|
<span class="p">}</span>
|
|||
|
<span class="n">pthread_mutex_unlock</span> <span class="p">(</span><span class="n">log_lock</span><span class="p">);</span>
|
|||
|
<span class="p">}</span>
|
|||
|
</pre></div>
|
|||
|
</td></tr></table></div>
|
|||
|
<p>The challenge of logging events in distributed environments is much more
|
|||
|
difficult, as there is no universal clock that can be used. Each system has its
|
|||
|
own internal system clock, but these clocks may be misconfigured or naturally
|
|||
|
drift over time. This problem could potentially be addressed by synchronizing
|
|||
|
the system clocks to agree on the time. However, as the system becomes larger
|
|||
|
and the physical distance between nodes increases, delays in the network can
|
|||
|
become unpredictable and too difficult to counteract. The solution in that case
|
|||
|
would be to give up on trying to synchronize the clocks and focus on a coherent
|
|||
|
ordering of events instead.</p>
|
|||
|
<div class="section" id="clock-synchronization">
|
|||
|
<h2>9.5.1. Clock Synchronization<a class="headerlink" href="DistTiming.html#clock-synchronization" title="Permalink to this headline">¶</a></h2>
|
|||
|
<div class="figure mb-2 align-right" id="id2" style="width: 23%">
|
|||
|
<span id="ntpsequence"></span><a class="reference internal image-reference" href="_images/CSF-Images.9.7.png"><img class="p-3 mb-2 align-center border border-dark rounded-lg" alt="Sequence of messages and events in NTP" src="_images/CSF-Images.9.7.png" style="width: 90%;" /></a>
|
|||
|
<p class="caption align-center px-3"><span class="caption-text"> Figure 9.5.1: Sequence of messages and events in NTP</span></p>
|
|||
|
</div>
|
|||
|
<p>One approach to solving the timing problem in distributed environments is to
|
|||
|
synchronize the clocks on all nodes with a centralized server.
|
|||
|
<a href="DistTiming.html#ntpsequence">Figure 9.5.1</a> shows the exchange of messages in the
|
|||
|
<a class="reference internal" href="Glossary.html#term-network-time-protocol"><span class="xref std std-term">Network Time Protocol (NTP)</span></a>, one solution built on this idea. In NTP, each
|
|||
|
node will occasionally poll the server, keeping track of the times when certain events
|
|||
|
occur. Specifically, the client records $T_1$ as the time that it sent the poll
|
|||
|
message. The server received the message at $T_2$ according to its internal clock,
|
|||
|
sending the response back at time $T_3$ (according to the server’s clock). The
|
|||
|
client then records $T_4$ as the time that it received the response from the
|
|||
|
server. Based on this information, the client would calculate two values:</p>
|
|||
|
<center>
|
|||
|
<span class="math inline">$\large \mbox{offset} =
|
|||
|
\displaystyle\frac{(T_2 - T_1) + (T_3 - T_4)}{2}$</span><br /><br />
|
|||
|
<span class="math inline">$\large \mbox{delay} =
|
|||
|
(T_4 - T_1) - (T_3 - T_2)$</span>
|
|||
|
</center>
|
|||
|
<br /><p>The delay is used to eliminate the time that it takes for the messages to travel
|
|||
|
through the network from consideration. The offset is used to detect the clock
|
|||
|
skew between the nodes. For instance, assume $T_1 = 20$, $T_2 = 30$, $T_3 = 32$,
|
|||
|
and $T_4 = 46$. Then the offset would be calculated as $(10 - 14)/2 = -2$, and
|
|||
|
the delay would be $26 - 2 = 24$. The message from client to server was measured
|
|||
|
as taking 10 time units, whereas the response took longer (14 time units). One
|
|||
|
possible cause is that the client’s clock is ahead of the server’s clock. If the
|
|||
|
client’s clock was adjusted back so that $T_1 = 18$ and $T_4 = 44$, then the
|
|||
|
offset would be 0, as the two messages would be measured as taking 12 time units
|
|||
|
in each direction. The client passes the offset and delay values, along with
|
|||
|
previous measurements, through a suite of protocols to filter and select the
|
|||
|
most accurate values. The client then combines these <em>survivor</em> offsets to
|
|||
|
adjust the system clock time and frequency. The protocol can then be repeated
|
|||
|
until the offset is sufficiently small. <a class="footnote-reference" href="DistTiming.html#f50" id="id1">[1]</a></p>
|
|||
|
</div>
|
|||
|
<div class="section" id="logical-clocks-and-lamport-timestamps">
|
|||
|
<h2>9.5.2. Logical Clocks and Lamport Timestamps<a class="headerlink" href="DistTiming.html#logical-clocks-and-lamport-timestamps" title="Permalink to this headline">¶</a></h2>
|
|||
|
<p>As systems grow larger and nodes increase in physical distance, trying to
|
|||
|
synchronize the internal clocks of nodes in the system becomes unmanageable. The
|
|||
|
number of messages needed for protocols like NTP impose a significant burden on
|
|||
|
the network that would interfere with other work. An alternative approach is to
|
|||
|
establish a reasonable understanding of the sequence of events using
|
|||
|
<a class="reference internal" href="Glossary.html#term-logical-clock"><span class="xref std std-term">logical clocks</span></a>. A logical clock uses messages, not real time
|
|||
|
measurements, to track the relative, logical ordering of events. These messages
|
|||
|
are <a class="reference internal" href="Glossary.html#term-asynchronous"><span class="xref std std-term">asynchronous</span></a>, in the sense that there are no timing guarantees;
|
|||
|
network and other processing delays introduce random timing differences between
|
|||
|
when a message is sent and received.</p>
|
|||
|
<p><a class="reference internal" href="Glossary.html#term-lamport-timestamp"><span class="xref std std-term">Lamport timestamps</span></a> are a simple approach to logical clocks. Each process
|
|||
|
(a task running on a separate node) maintains an internal counter of events that
|
|||
|
it experiences. These events could be a local action or computational result
|
|||
|
that is relevant to the system as a whole. Whenever a local event occurs, or a
|
|||
|
process sends or receives a message, this internal counter is incremented. When
|
|||
|
processes send messages, they append their counter. Given their distributed
|
|||
|
nature, processes can only observe local events and messages they send or
|
|||
|
receive; they cannot be aware of messages received by other processes or events
|
|||
|
that occur elsewhere in the system. <a class="reference external" href="DistTiming.html#cl9-9">Code Listing 9.9</a> shows the basic
|
|||
|
algorithm for receiving a message with a Lamport timestamp. The message’s
|
|||
|
timestamp is compared with the local process’s counter, and the local timestamp
|
|||
|
is updated to be the greater of the two. The timestamp is then incremented,
|
|||
|
keeping track of the event of receiving the message.</p>
|
|||
|
<div class="highlight-c border border-dark rounded-lg bg-light px-0 mb-3 notranslate" id="cl9-9"><table class="highlighttable"><tr><td class="linenos px-0 mx-0"><div class="linenodiv"><pre class="mb-0"> 1
|
|||
|
2
|
|||
|
3
|
|||
|
4
|
|||
|
5
|
|||
|
6
|
|||
|
7
|
|||
|
8
|
|||
|
9
|
|||
|
10</pre></div></td><td class="code"><div class="highlight bg-light"><pre class="mb-0"><span></span><span class="cm">/* Code Listing 9.9:</span>
|
|||
|
<span class="cm"> Reading a message from a socket with a Lamport timestamp attached</span>
|
|||
|
<span class="cm"> */</span>
|
|||
|
|
|||
|
<span class="kt">ssize_t</span> <span class="n">bytes</span> <span class="o">=</span> <span class="n">read</span> <span class="p">(</span><span class="n">socketfd</span><span class="p">,</span> <span class="o">&</span><span class="n">message</span><span class="p">,</span> <span class="k">sizeof</span> <span class="p">(</span><span class="n">message</span><span class="p">));</span>
|
|||
|
<span class="cm">/* Update local timestamp if message has greater value */</span>
|
|||
|
<span class="k">if</span> <span class="p">(</span><span class="n">message</span><span class="p">.</span><span class="n">timestamp</span> <span class="o">></span> <span class="n">local_timestamp</span><span class="p">)</span>
|
|||
|
<span class="n">local_timestamp</span> <span class="o">=</span> <span class="n">message</span><span class="p">.</span><span class="n">timestamp</span><span class="p">;</span>
|
|||
|
<span class="cm">/* Increment local timestamp */</span>
|
|||
|
<span class="n">local_timestamp</span><span class="o">++</span><span class="p">;</span>
|
|||
|
</pre></div>
|
|||
|
</td></tr></table></div>
|
|||
|
<div class="figure mb-2 align-right" id="id3" style="width: 45%">
|
|||
|
<span id="logicalclocks"></span><a class="reference internal image-reference" href="_images/CSF-Images.9.8.png"><img class="p-3 mb-2 align-center border border-dark rounded-lg" alt="Events and messages using logical clocks" src="_images/CSF-Images.9.8.png" style="width: 95%;" /></a>
|
|||
|
<p class="caption align-center px-3"><span class="caption-text"> Figure 9.5.2: Events and messages using logical clocks</span></p>
|
|||
|
</div>
|
|||
|
<p>As an example, consider a cloud computing system that provides
|
|||
|
Internet-accessible data storage service. <a href="DistTiming.html#logicalclocks">Figure 9.5.2</a>
|
|||
|
shows a sample sequence of events that may occur; the numbers in brackets denote
|
|||
|
the Lamport timestamps. Process A provides an interface for users and receives a
|
|||
|
request for the files “foo” and “zoo”; this request constitutes a local event
|
|||
|
for A, which has the timestamp 1. A then sends a message to process B (timestamp
|
|||
|
2) and another to process C (timestamp 3); receiving these messages occur at
|
|||
|
times 3 and 4, respectively. Note that process B has no knowledge of the message
|
|||
|
sent to C, so B’s local timestamp only reflects its knowledge of the message it
|
|||
|
received.</p>
|
|||
|
<p>After receiving their messages from process A, processes B and C concurrently
|
|||
|
load the two files requested. C sends the contents of “zoo” to B (timestamp 6)
|
|||
|
and B receives this message. Note that B’s timestamp jumps from 4 to 7 when this
|
|||
|
happens, reflecting the timestamp it observes in the message from C. B then
|
|||
|
merges the files (timestamp 8) and sends the result to A.</p>
|
|||
|
<p>With logical clocks, it is critical to note that an earlier timestamp does not
|
|||
|
necessarily guarantee that an event occurred before one with a later timestamp.
|
|||
|
Consider process B’s perspective in <a href="DistTiming.html#logicalclocks">Figure 9.5.2</a>. B
|
|||
|
observes the local logical ordering of events at timestamps 3, 4, and 7.
|
|||
|
However, B cannot know if “foo” was loaded before or after “zoo.” In fact, B
|
|||
|
cannot even know that the message it received from A was sent before the message
|
|||
|
from A to C. B can only observe the logical ordering of events within its own
|
|||
|
time line. If B later receives a message from A with a timestamp greater than
|
|||
|
11, it knows that message comes after the message when it sent foo+zoo to A.
|
|||
|
However, if B’s next interaction with C is receiving a message with timestamp
|
|||
|
11, B cannot determine precisely when this message was sent; it’s possible that
|
|||
|
C experienced several events before B merged the files at timestamp 8.</p>
|
|||
|
<p>In summary, logical clocks provide a mechanism for processes to exchange
|
|||
|
information about the relative ordering of events based on their perspectives.
|
|||
|
If processes A and B exchange messages back and forth, they can determine the
|
|||
|
relative ordering of these events. Once a third process C starts exchanging
|
|||
|
messages with A, process A will be able to determine the relative ordering of
|
|||
|
these messages, but neither B nor C would have the full view of the exchanges.</p>
|
|||
|
</div>
|
|||
|
<div class="section" id="vector-clocks">
|
|||
|
<h2>9.5.3. Vector Clocks<a class="headerlink" href="DistTiming.html#vector-clocks" title="Permalink to this headline">¶</a></h2>
|
|||
|
<p><a href="DistTiming.html#logicalclocks">Figure 9.5.2</a> illustrates one of the shortcomings of
|
|||
|
logical clocks with Lamport timestamps. Note that process A’s timeline jumps
|
|||
|
from timestamp 3 to the message it receives from B with timestamp 9. Given only
|
|||
|
this information, process A could not distinguish this sequence of events from a
|
|||
|
different timeline in which B experienced only local events. That is, the
|
|||
|
timestamp that process A observes in the message from B does not even provide
|
|||
|
assurance that B received the original message from A, nor does it suggest that
|
|||
|
B has been communicating with C. Lamport timestamps alone do not provide
|
|||
|
sufficient information to distinguish these scenarios.</p>
|
|||
|
<div class="figure mb-2 align-right" id="id4" style="width: 50%">
|
|||
|
<span id="vectorclocks"></span><a class="reference internal image-reference" href="_images/CSF-Images.9.9.png"><img class="p-3 mb-2 align-center border border-dark rounded-lg" alt="The events of :num:`Figure #LogicalClocks` with vector clocks" src="_images/CSF-Images.9.9.png" style="width: 95%;" /></a>
|
|||
|
<p class="caption align-center px-3"><span class="caption-text"> Figure 9.5.3: The events of <a href="DistTiming.html#logicalclocks">Figure 9.5.2</a> with vector clocks</span></p>
|
|||
|
</div>
|
|||
|
<p><a class="reference internal" href="Glossary.html#term-vector-clock"><span class="xref std std-term">Vector clocks</span></a> extend the basic idea of logical clocks with more
|
|||
|
information to address this problem. Whereas logical clocks kept only a single
|
|||
|
counter to establish the relative ordering of events, vector clocks use one
|
|||
|
counter per process. When a process sends a message, it appends the vector of
|
|||
|
counters from its perspective, implicitly acknowledging its understanding of the
|
|||
|
other process’s timestamps. <a href="DistTiming.html#vectorclocks">Figure 9.5.3</a> illustrates the
|
|||
|
same sequence of events from <a href="DistTiming.html#logicalclocks">Figure 9.5.2</a>, using vector
|
|||
|
clocks instead of Lamport timestamps. When process B receives the first message
|
|||
|
from A, B increments its own counter in the vector.</p>
|
|||
|
<p><a href="DistTiming.html#vectorclocks">Figure 9.5.3</a> illustrates a key strength of vector clocks
|
|||
|
with the message from process C to B containing the contents of zoo. This
|
|||
|
message contains the vector [3,0,3], indicating that C believes process A’s
|
|||
|
timestamp is at least 3. But B had previously received the vector [2,0,0] from
|
|||
|
process A, so process B knows that A’s message to C was sent after A’s message
|
|||
|
to B. Note, though, that process B cannot be certain about the order of events
|
|||
|
that C experienced. That is, the vector [2,0,0] was A stating it believed C’s
|
|||
|
timestamp was 0. The best that process B can state is that the message it
|
|||
|
received from C had been sent after A sent the first message to B. For an
|
|||
|
asynchronous system, this claim is the best that can be made.</p>
|
|||
|
<table class="docutils footnote" frame="void" id="f50" rules="none">
|
|||
|
<colgroup><col class="label" /><col /></colgroup>
|
|||
|
<tbody valign="top">
|
|||
|
<tr><td class="label"><a class="fn-backref" href="DistTiming.html#id1">[1]</a></td><td>For more specifics on how the offset and delay are used, see the NTP
|
|||
|
homepage available at <code class="docutils literal notranslate"><span class="pre">https://www.eecis.udel.edu/~mills/ntp/html/warp.html</span></code>.</td></tr>
|
|||
|
</tbody>
|
|||
|
</table>
|
|||
|
<div
|
|||
|
id="TimingSumm"
|
|||
|
class="embedContainer"
|
|||
|
data-exer-name="TimingSumm"
|
|||
|
data-long-name="Distributed timing questions"
|
|||
|
data-short-name="TimingSumm"
|
|||
|
data-frame-src="../../../Exercises/ParallelDistributed/TimingSumm.html?selfLoggingEnabled=false&localMode=true&module=DistTiming&JXOP-debug=true&JOP-lang=en&JXOP-code=java"
|
|||
|
data-frame-width="950"
|
|||
|
data-frame-height="550"
|
|||
|
data-external="false"
|
|||
|
data-points="1.0"
|
|||
|
data-required="True"
|
|||
|
data-showhide="show"
|
|||
|
data-threshold="3"
|
|||
|
data-type="ka"
|
|||
|
data-exer-id="">
|
|||
|
|
|||
|
<div class="center">
|
|||
|
<div id="TimingSumm_iframe"></div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<div class="container">
|
|||
|
|
|||
|
<div class="mt-4 container center">
|
|||
|
«  <a id="prevmod1" href="Scaling.html">9.4. Limits of Parallelism and Scaling</a>
|
|||
|
  ::  
|
|||
|
<a class="uplink" href="index.html">Contents</a>
|
|||
|
  ::  
|
|||
|
<a id="nextmod1" href="DistDataStorage.html">9.6. Reliable Data Storage and Location</a>  »
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
</div>
|
|||
|
|
|||
|
<br />
|
|||
|
|
|||
|
<div class="row jmu-dark-purple-bg">
|
|||
|
<div class="col-md-12">
|
|||
|
<center>
|
|||
|
<a id="contact_us" class="btn button-link-no-blue jmu-gold" rel="nofollow" href="mailto:webmaster@opencsf.org" role="button">Contact Us</a>
|
|||
|
<a id="license" class="btn button-link-no-blue jmu-gold" rel="nofollow" href="https://w3.cs.jmu.edu/kirkpams/OpenCSF/lib/license.html" target="_blank">License</a>
|
|||
|
</center>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<script src="_static/js/popper.js-1.14.7-min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
|
|||
|
<script src="_static/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
|
|||
|
</body>
|
|||
|
</html>
|