Un système réparti est constitué de N composants (processus ou sites)
communiquant par messages (et uniquement de cette manière).
Chacun de ces composants agit comme un automate : il réalise des
opérations qui modifient son état. Les opérations réalisées par
un des composants sont naturellement ordonnées par l'ordre dans lequel
elles sont réalisées : si il s'agit d'un processus abritant
plusieurs activités (threads), sur un système monoprocesseur,
c'est l'ordre de l'exécution des instructions des instructions sur ce
processeur qui ordonne les événements.
La définition de l'ordre des
événements sur un système multi-processeurs (fortement et a fortiori
faiblement couplés) est plus problématique du fait de la difficulté de
maintenir une notion de temps absolu cohérente.
Lamport a proposé de définir pour ce type de systèmes une notion de temps logique permettant de comparer logiquement des événements du point de vue de leur ordre d'exécution : d'une part, sur un site, les événements locaux peuvent être ordonnés en se basant sur l'ordre de leur exécution (ou le temps absolu s'il est défini) et d'autre part l'émission d'un message sur le site émetteur précède toujours sa réception sur le site récepteur. Cela correspond à la notion de précédence causale.
De manière plus formelle :
Cette relation définit un ordre partiel des événements.
Des événements
e et
e'
non comparables sont dits concurrents,
ce qu'on note e||e'.
A un événement e on peut alors associer trois ensembles d'événements :
Considérons la figure suivante décrivant un ensemble d'événements
dans un système de 3 sites :
La relation de dépendance causale directe y correspond au graphe
Considérons l'événement
p.
Il appartient à son propre passé et est
précédé directement par o et
y.
- On a Passé(p) = {p} + Passé(o) + Passé(y)
Le calcul de Passé(p) suppose donc le calcul de celui de
o et
y.
- On a Passé(o) = {o} + Passé(n) + Passé(d)
En pousuivant le calcul:
- Passé(n) = {n} + Passé(m)
- Passé(m) = {m} + Passé(l) + Passé(a)
- Passé(l) = {l} + Passé(k)
- Passé(k) = {k} + Passé(j) + Passé(u)
- Passé(j) = {j}
- Passé(u) = {u}
- Passé(a) = {a}
- Passé(d) = {d} + Passé(c)
- Passé(c) = {c} + Passé(b)
- Passé(b) = {b} + Passé(a) + Passé(j)
- Passé(y) = {y} + Passé(x)
- Passé(x) = {x} + Passé(w) + Passé(n)
- Passé(w) = {w} + Passé(v)
- Passé(v) = {v} + Passé(u) + Passé(l)
Par conséquent Passé(p) =
{a, b, c, d, j, k, l, m, n, o, p, u, v, w, x, y}
Par un calcul analogue, on obtient:
Futur(p) = {g, h, i, p, q, r, s, t, C, D}
Finalement les événements n'appartenant ni à Passé(p), ni à Futur(p) sont concurrents avec p.
On a donc Concurrent(p) = {e, f, z, A, B}Dans un système réparti, la communication entre les noeuds du système est en général assurée par une couche de communication spécifique utilisée par des entités de la couche supérieure pour expédier ou recevoir des messages. Cette couche de communication peut être amenée à ne pas rendre accessible les informations reçues depuis d'autres sites aux applications de la couche supérieure. C'est le cas de la couche TCP qui ne rend accessible un caractère que lorsque tous les caractèress envoyés précédemment sur la connexion ont été effectivement reçus.
La délivrance d'un message est l'opération consistant à le rendre accessible aux applications clientes : nous noterons del(m) cette opération.Nous mentionnons maintenant les deux propriétés de l'ordre de délivrance des messages qui peuvent s'avérer souhaitables pour certains types d'application.
Afin de dater les événements, des
horloges logiques de différents types
peuvent être définies afin de rendre compte de la relation de causalité
entre les événements.
Les valeurs des horloges associées à des
événements (leurs estampilles logiques)
comparables doivent être elles-mêmes comparables et refléter l'ordre des
événements, c'est-à-dire que