ЁЯХ░я╕П рдзрдбрд╛ 02 тАФ Clocks: рдкреНрд░рддреНрдпреЗрдХ рд╢рд╛рдЦреЗрдЪреЗ рдШрдбреНрдпрд╛рд│ рдереЛрдбреЗрд╕реЗ рдЪреБрдХреАрдЪреЗ рдЕрд╕рддреЗ
ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 12 рдкреИрдХреА рдзрдбрд╛ 02 ┬╖ рдорд╛рдЧреЗ: lesson-01-partial-failure ┬╖ рдкреБрдвреЗ: lesson-03-ordering
ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ
рдзрдбрд╛ 01, рдЕрдзрд┐рдХ рд╡реЗрд│. рдкреНрд░рддреНрдпреЗрдХ рд╢рд╛рдЦреЗрдЪреЗ рд╕реНрд╡рддрдГрдЪреЗ wall clock рдЕрд╕рддреЗ, рдЖрдгрд┐ рддреА рд╣рд│реВрд╣рд│реВ рд╡реЗрдЧрд│реА рд╣реЛрдд рдЬрд╛рддрд╛рдд.
рд╡реЗрдЧрд╡реЗрдЧрд│реНрдпрд╛ machines рд╡рд░рдЪреНрдпрд╛ рдШрдЯрдирд╛рдВрдЪрд╛ рдХреНрд░рдо wall time рд╕реБрд░рдХреНрд╖рд┐рддрдкрдгреЗ рдХрд╛ рдард░рд╡реВ рд╢рдХрдд рдирд╛рд╣реА, NTP рдХрд╛рдп
рджреБрд░реБрд╕реНрдд рдХрд░реВ рд╢рдХрддреЛ рдЖрдгрд┐ рдХрд╛рдп рдирд╛рд╣реА, monotonic рд╡рд┐рд░реБрджреНрдз wall clocks, рдЖрдгрд┐ Lamport clocks тАФ рдХреЛрдгрддреНрдпрд╛рд╣реА
рдЦрд▒реНрдпрд╛ рдШрдбреНрдпрд╛рд│рд╛рд╢рд┐рд╡рд╛рдп рдХрд╛рд░рдгрд╛рд▓рд╛ рдкрд░рд┐рдгрд╛рдорд╛рдЪреНрдпрд╛ рдЖрдзреА рдареЗрд╡рдгрд╛рд░рд╛ рдПрдХ counter. dist/demo.py рдордзрд▓реЗ clocks()
рдЖрдгрд┐ dist/sim.py рдордзрд▓реЗ LamportClock.
ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ
рдкреНрд░рддреНрдпреЗрдХ рд╢рд╛рдЦреЗрдЪреНрдпрд╛ рднрд┐рдВрддреАрд╡рд░ рдПрдХ рдШрдбреНрдпрд╛рд│ рдЖрд╣реЗ. ЁЯХ░я╕П рд╕рдЧрд│реА рдПрдХрд╛рдЪ рджрд┐рд╡рд╢реА рд▓рд╛рд╡рд▓реА рд╣реЛрддреА. рдкрдг рдШрдбреНрдпрд╛рд│реЗ рдкрд░рд┐рдкреВрд░реНрдг рдирд╕рддрд╛рдд. рдкреБрдгреНрдпрд╛рдЪреЗ рдШрдбреНрдпрд╛рд│ рдереЛрдбреЗ рдкреБрдвреЗ рдкрд│рддреЗ. рдирд╛рд╢рд┐рдХрдЪреЗ рдереЛрдбреЗ рдорд╛рдЧреЗ рд░рд╛рд╣рддреЗ.
рдПрдХрд╛рдЪ рдХреНрд╖рдгреА, рдкреБрдгреНрдпрд╛рдЪреЗ рдШрдбреНрдпрд╛рд│ 10:00:00.120 рджрд╛рдЦрд╡рддреЗ рдЖрдгрд┐ рдирд╛рд╢рд┐рдХрдЪреЗ 09:59:59.980.
рдкреБрдгреНрдпрд╛рддрд▓реА рдХрддрд░рд┐рдирд╛ "exam at 10" рд▓рд┐рд╣рд┐рддреЗ рдЖрдгрд┐ рддрд┐рдЪреНрдпрд╛ рдШрдбреНрдпрд╛рд│рд╛рдиреБрд╕рд╛рд░ рддреНрдпрд╛рд╡рд░ 10:00:00.100 рдЕрд╢реА рд╡реЗрд│ рдЯрд╛рдХрддреЗ. рдПрдХрд╛ рдХреНрд╖рдгрд╛рдиреЗ рдирдВрддрд░, рдирд╛рд╢рд┐рдХрдордзрд▓реА рдРрд╢реНрд╡рд░реНрдпрд╛ рддреЗ рдмрджрд▓реВрди "exam at 11" рдХрд░рддреЗ рдЖрдгрд┐ рддрд┐рдЪреНрдпрд╛ рдШрдбреНрдпрд╛рд│рд╛рдиреБрд╕рд╛рд░ рддреНрдпрд╛рд╡рд░ 10:00:00.050 рдЕрд╢реА рд╡реЗрд│ рдЯрд╛рдХрддреЗ.
рдЖрддрд╛ рдХреЛрдгреАрддрд░реА рдЪрд┐рдареНрдареНрдпрд╛ рд╡реЗрд│реЗрдиреБрд╕рд╛рд░ рд▓рд╛рд╡рддреЗ. рдкреБрдгреНрдпрд╛рдЪреНрдпрд╛ рдЪрд┐рдареНрдареАрд╡рд░рдЪреА рд╡реЗрд│ рдореЛрдареА рдЖрд╣реЗ. рдореНрд╣рдгреВрди рдкреБрдгреНрдпрд╛рдЪреА рдЪрд┐рдареНрдареА рдЬрд┐рдВрдХрддреЗ. рдкрдг рдРрд╢реНрд╡рд░реНрдпрд╛рдЪрд╛ рдмрджрд▓ рдирдВрддрд░ рдЖрд▓рд╛ рд╣реЛрддрд╛! рддрд┐рдЪрд╛ рдмрджрд▓ рдлреЗрдХреВрди рджрд┐рд▓рд╛ рдЬрд╛рддреЛ, рдЖрдгрд┐ рдХреЛрдгрд╛рдЪреНрдпрд╛ рд▓рдХреНрд╖рд╛рддрд╣реА рдпреЗрдд рдирд╛рд╣реА.
рдореНрд╣рдгреВрди рд╢рд╛рдЦрд╛ рд╡реЗрдЧрд│реА рдХрд▓реНрдкрдирд╛ рд╡рд╛рдкрд░реВрди рдкрд╛рд╣рддрд╛рдд. рдкреНрд░рддреНрдпреЗрдХ рд╢рд╛рдЦрд╛ рдПрдХ counter рдареЗрд╡рддреЗ. ЁЯФв рдкреНрд░рддреНрдпреЗрдХ рд╡реЗрд│реА рддреБрдореНрд╣реА рд▓рд┐рд╣рд┐рддрд╛, 1 рдорд┐рд│рд╡рд╛. рдкреНрд░рддреНрдпреЗрдХ рдЪрд┐рдареНрдареАрд╡рд░ рддреБрдордЪрд╛ counter рдЕрд╕рддреЛ. рддреБрдореНрд╣рд╛рд▓рд╛ рдЪрд┐рдареНрдареА рдорд┐рд│рд╛рд▓реА рдХреА рддреБрдордЪрд╛ counter "рдорд╛рдЭрд╛ рдЖрдгрд┐ рдЪрд┐рдареНрдареАрдЪрд╛ рдпрд╛рдВрдкреИрдХреА рдореЛрдард╛, рдЕрдзрд┐рдХ 1" рдЕрд╕рд╛ рдХрд░рд╛. рдЖрддрд╛ рдЙрддреНрддрд░рд╛рд▓рд╛ рдиреЗрд╣рдореА рддреЗ рдЬреНрдпрд╛ рдкреНрд░рд╢реНрдирд╛рдЪреЗ рдЙрддреНрддрд░ рдЖрд╣реЗ рддреНрдпрд╛рдЪреНрдпрд╛рдкреЗрдХреНрд╖рд╛ рдореЛрдард╛ рдХреНрд░рдорд╛рдВрдХ рдЕрд╕рддреЛ. Wall clock рдЪреА рдЧрд░рдЬрдЪ рдирд╛рд╣реА. рддреНрдпрд╛ counter рд▓рд╛ Lamport clock рдореНрд╣рдгрддрд╛рдд.
ЁЯЧ║я╕П рдЖрдХреГрддреА
flowchart LR
subgraph wall["ЁЯХ░я╕П wall clocks: Pune is 140 ms ahead"]
p1["Pune writes 'exam at 10'<br/>stamp 10:00:00.100"] --> n1["Nashik writes 'exam at 11' LATER<br/>stamp 10:00:00.050"]
n1 --> lww["sort by stamp: Pune's note wins<br/>the later change is lost"]
end
subgraph lam["ЁЯФв Lamport clocks"]
a["Pune writes<br/>L = 1"] -->|"note carries 1"| b["Nashik receives<br/>L = max(0, 1) + 1 = 2"]
b --> c["Nashik writes<br/>L = 3"]
end
ЁЯЧ║я╕П рдХрд╛рдврд▓реЗрд▓реА рдЖрд╡реГрддреНрддреА + рдПрдХ lab: https://school-edh.pages.dev/distributed-systems/lesson-diagrams.html#l02
тЭУ рдХрд╛рдп
- Wall clock (рджрд┐рд╡рд╕рд╛рддреАрд▓ рд╡реЗрд│) тАФ "10:00:00" рд╕рд╛рдВрдЧрдгрд╛рд░реЗ рдШрдбреНрдпрд╛рд│. Computer рдЪрд╛ crystal oscillator рдереЛрдбрд╛ рдЬрд▓рдж рдХрд┐рдВрд╡рд╛ рд╣рд│реВ рдЪрд╛рд▓рддреЛ, рддреНрдпрд╛рдореБрд│реЗ рдШрдбреНрдпрд╛рд│ рдкреБрдвреЗ-рдорд╛рдЧреЗ рд╣реЛрддреЗ (drift) (рд╕рд╛рдорд╛рдиреНрдп рдЖрдХрдбрд╛ рдореНрд╣рдгрдЬреЗ рд╕реБрдорд╛рд░реЗ 200 parts per million рдкрд░реНрдпрдВрдд тАФ рдХреЛрдгреА рджреБрд░реБрд╕реНрдд рдХреЗрд▓реЗ рдирд╛рд╣реА рддрд░ рджрд┐рд╡рд╕рд╛рд▓рд╛ рд╕реБрдорд╛рд░реЗ 17 рд╕реЗрдХрдВрджрд╛рдВрдкрд░реНрдпрдВрдд).
- Clock skew тАФ рдПрдХрд╛рдЪ рдХреНрд╖рдгреА рджреЛрди рдШрдбреНрдпрд╛рд│рд╛рдВрдордзрд▓рд╛ рдлрд░рдХ. Demo рдордзреНрдпреЗ: 10:00:00.120 тИТ 09:59:59.980 = 140 ms.
- NTP (Network Time Protocol) тАФ machine time servers рдирд╛ рд╡рд┐рдЪрд╛рд░рддреЗ рдЖрдгрд┐ рдЖрдкрд▓реЗ рдШрдбреНрдпрд╛рд│ рджреБрд░реБрд╕реНрдд рдХрд░рддреЗ. рдпрд╛рдЪреА рдЦреВрдк рдорджрдд рд╣реЛрддреЗ, рдкрдг рдорд░реНрдпрд╛рджрд╛ рдЖрд╣реЗрдд: internet рд╡рд░реВрди рджрд╣рд╛-рджрд╣рд╛ milliseconds рдЪреНрдпрд╛ рдЪреБрдХрд╛ рд╕рд╛рдорд╛рдиреНрдп рдЖрд╣реЗрдд, рдЖрдгрд┐ network delay рджреЛрдиреНрд╣реА рджрд┐рд╢рд╛рдВрдирд╛ рд╕рд╛рд░рдЦрд╛рдЪ рдЕрд╕реЗрд▓ рдпрд╛рд╡рд░ рддреЗ рдЕрд╡рд▓рдВрдмреВрди рдЕрд╕рддреЗ. рдПрдЦрд╛рджреА рджреБрд░реБрд╕реНрддреА wall clock рд▓рд╛ рдорд╛рдЧреЗрд╣реА рдЙрдбреА рдорд╛рд░рд╛рдпрд▓рд╛ рд▓рд╛рд╡реВ рд╢рдХрддреЗ.
- Monotonic clock тАФ рдлрдХреНрдд рдкреБрдвреЗрдЪ рдЬрд╛рдгрд╛рд░реЗ рдШрдбреНрдпрд╛рд│, рдПрдХрд╛рдЪ machine рд╡рд░ рдХрд╛рд▓рд╛рд╡рдзреА рдореЛрдЬрдгреНрдпрд╛рд╕рд╛рдареА
(Python
time.monotonic(), LinuxCLOCK_MONOTONIC). рддреНрдпрд╛рдЪреНрдпрд╛ рдЖрдХрдбреНрдпрд╛рд▓рд╛ рджреБрд╕рд▒реНрдпрд╛ machine рд╡рд░ рдХрд╛рд╣реАрдЪ рдЕрд░реНрде рдирд╕рддреЛ. рддреЗ timeouts рдЖрдгрд┐ "рдпрд╛рд▓рд╛ рдХрд┐рддреА рд╡реЗрд│ рд▓рд╛рдЧрд▓рд╛" рд╕рд╛рдареА рд╡рд╛рдкрд░рд╛; wall clock рдлрдХреНрдд рдорд╛рдгрд╕рд╛рд▓рд╛ рд╡реЗрд│ рджрд╛рдЦрд╡рдгреНрдпрд╛рд╕рд╛рдареА рд╡рд╛рдкрд░рд╛. - Wall time рдиреБрд╕рд╛рд░ last-writer-wins (LWW) тАФ рд╕рд░реНрд╡рд╛рдд рдореЛрдареА рд╡реЗрд│ рдЕрд╕рд▓реЗрд▓рд╛ write рдареЗрд╡рд╛. Skew рджреЛрди writes рдордзрд▓реНрдпрд╛ рдЕрдВрддрд░рд╛рдкреЗрдХреНрд╖рд╛ рдореЛрдард╛ рдЕрд╕реЗрд▓ рддрд░ рдЖрдзреАрдЪрд╛ write рдЬрд┐рдВрдХрддреЛ рдЖрдгрд┐ рдирдВрддрд░рдЪрд╛ рдЧреБрдкрдЪреВрдк рд╣рд░рд╡рддреЛ.
- Happened-before (тЖТ) тАФ Leslie Lamport рдЪреА 1978 рдЪреА рдХрд▓реНрдкрдирд╛: a тЖТ b рдЬрд░ рдПрдХрд╛рдЪ node рд╡рд░ a рд╣реЗ b рдЪреНрдпрд╛ рдЖрдзреА рдЖрд▓реЗ, рдХрд┐рдВрд╡рд╛ a message рдкрд╛рдард╡рдд рдЖрд╣реЗ рдЖрдгрд┐ b рддреЛ рдШреЗрдд рдЖрд╣реЗ, рдХрд┐рдВрд╡рд╛ рдЕрд╢рд╛рдВрдЪреА рдПрдХ рд╕рд╛рдЦрд│реА рдЖрд╣реЗ. a тЖТ b рд╣реА рдирд╛рд╣реА рдЖрдгрд┐ b тЖТ a рд╣реА рдирд╛рд╣реА, рддрд░ рддреНрдпрд╛ рдШрдЯрдирд╛ concurrent рдЖрд╣реЗрдд.
- Lamport clock тАФ рдкреНрд░рддреНрдпреЗрдХ node рд╡рд░ рдПрдХ counter.
tick()рдкреНрд░рддреНрдпреЗрдХ рдШрдЯрдиреЗрд╕рд╛рдареА 1 рдорд┐рд│рд╡рддреЗ.recv(t)counter рд▓рд╛max(mine, t) + 1рдХрд░рддреЗ. рддреЛ рд╣рдореА рджреЗрддреЛ рддреЛ рдирд┐рдпрдо: a тЖТ b рдЕрд╕реЗрд▓ рддрд░ L(a) < L(b). рдЙрд▓рдЯ рдЦрд░реЗ рдирд╛рд╣реА: L(a) < L(b) рдореНрд╣рдгрдЬреЗ a рдореБрд│реЗ b рдЭрд╛рд▓реЗ рдЕрд╕реЗ рдирд╛рд╣реА. рдмрд░реЛрдмрд░реА рд╕реЛрдбрд╡рд╛рдпрд▓рд╛ node рдЪреЗ рдирд╛рд╡ рдЬреЛрдбрд╛, рдЖрдгрд┐ рддреБрдореНрд╣рд╛рд▓рд╛ рдкреНрд░рддреНрдпреЗрдХ node рдорд╛рдиреНрдп рдХрд░рддреЛ рдЕрд╕рд╛ total order рдорд┐рд│рддреЛ.
ЁЯдФ рдХрд╛
рдХрд╛рд░рдг "рд╕рд░реНрд╡рд╛рдд рдирд╡рд╛ write рдареЗрд╡рд╛" рд╣рд╛ distributed data рдордзрд▓рд╛ рд╕рд░реНрд╡рд╛рдд рд╕рд╛рдорд╛рдиреНрдп рдирд┐рдпрдо рдЖрд╣реЗ, рдЖрдгрд┐ "рд╕рд░реНрд╡рд╛рдд рдирд╡рд╛" рдореНрд╣рдгрдЬреЗ рд╕рд╣рд╕рд╛ "рд╕рд░реНрд╡рд╛рдд рдореЛрдареА time stamp". Skew рдЕрд╕реЗрд▓ рддрд░ рд╕рд░реНрд╡рд╛рдд рдореЛрдареА stamp рдореНрд╣рдгрдЬреЗ рд╕рд░реНрд╡рд╛рдд рдирд╡рд╛ write рдирд╕рддреЛ. Data рдЪреЗ рдиреБрдХрд╕рд╛рди рдЧреБрдкрдЪреВрдк рд╣реЛрддреЗ: error рдирд╛рд╣реА, log line рдирд╛рд╣реА, рдлрдХреНрдд рдПрдХ рдмрджрд▓ рдирд╛рд╣реАрд╕рд╛ рд╣реЛрддреЛ. Lamport clocks рдЕрд╕рд╛ рдХреНрд░рдо рджреЗрддрд╛рдд рдЬреЛ рдиреЗрд╣рдореА рдХрд╛рд░рдг рдЖрдгрд┐ рдкрд░рд┐рдгрд╛рдо рдкрд╛рд│рддреЛ, рдЖрдгрд┐ рддреНрдпрд╛рдЪреА рдХрд┐рдВрдордд рдореНрд╣рдгрдЬреЗ рдкреНрд░рддреНрдпреЗрдХ message рд╡рд░ рдПрдХ рдЫреЛрдЯрд╛ рдЖрдХрдбрд╛.
ЁЯФз рдХрд╕реЗ (рдпрд╛ repo рдордзреНрдпреЗ)
dist/sim.py рдордзрд▓реНрдпрд╛ LamportClock рдордзреНрдпреЗ t, tick() (+1) рдЖрдгрд┐
recv(other) (max(t, other) + 1) рдЖрд╣реЗрдд. dist/demo.py рдордзрд▓реЗ clocks()
skew рдЪреА рдЧреЛрд╖реНрдЯ рдЖрдгрд┐ рдПрдХ рдкреБрдгреЗ тЖТ рдирд╛рд╢рд┐рдХ рджреЗрд╡рд╛рдгрдШреЗрд╡рд╛рдг print рдХрд░рддреЗ. рдЦрд╛рд▓рдЪреНрдпрд╛ snippet рдордзрд▓рд╛ wall-clock рднрд╛рдЧ
рд╕рд╛рдзреЗ рдЧрдгрд┐рдд рдЖрд╣реЗ: рдкреНрд░рддреНрдпреЗрдХ рд╢рд╛рдЦреЗрдЪреА time stamp рдореНрд╣рдгрдЬреЗ рдЦрд░реА рд╡реЗрд│ рдЕрдзрд┐рдХ рддреНрдпрд╛ рд╢рд╛рдЦреЗрдЪрд╛
offset, рдЖрдгрд┐ рдзрдбрд╛ 08 рдордзрд▓реЗ resolve(..., "lww") рд╕рд░реНрд╡рд╛рдд рдореЛрдареА stamp рдареЗрд╡рддреЗ.
ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛
python3 dist/demo.py clocks
python3 - <<'EOF'
import sys; sys.path.insert(0, "dist"); from sim import LamportClock, resolve
p, n, g = LamportClock(), LamportClock(), LamportClock()
a = p.tick(); b = p.tick() # Pune writes twice
c = g.tick() # Nagpur writes once, sees nobody
d = n.recv(b) # Nashik reads Pune's second note
e = n.tick() # Nashik writes
print(f"Pune a={a} b={b} ┬╖ Nagpur c={c} ┬╖ Nashik receives b тЖТ {d}, writes e={e}")
print("b caused e, so b < e:", b < e)
print("c and b never met, yet c < b:", c < b, "тАФ a smaller number does NOT mean 'caused'")
# true time in ms after 10:00:00.000; each branch's clock is off by an offset
for pune_off, nashik_off in ((120, -20), (100, 0), (60, 0), (0, 0)):
pune_stamp = -20 + pune_off # Pune writes FIRST, at true time -20 ms
nashik_stamp = 70 + nashik_off # Nashik writes 90 ms LATER, at true time +70 ms
kept = resolve((pune_stamp, "exam at 10"), (nashik_stamp, "exam at 11"), "lww")
print(f"Pune ahead by {pune_off - nashik_off:>3} ms тЖТ stamps pune {pune_stamp:>3}, nashik {nashik_stamp:>3} тЖТ last-writer-wins keeps {kept!r}")
EOF
тЬЕ рддрдкрд╛рд╕рд╛ тАФ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рджрд┐рд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ
clocks рд╣реЗ print рдХрд░рддреЗ:
тФАтФА wall clocks drift: Pune's clock reads 10:00:00.120, Nashik's reads 09:59:59.980 at the same instant
Pune writes 'exam at 10' at 10:00:00.100 by its clock; Nashik then writes 'exam at 11' at 10:00:00.050 by its clock
sorting by wall time says Pune's note was LAST тАФ the later change is silently thrown away
тФАтФА Lamport: Pune writes (L=1) тЖТ Nashik receives (L=2) тЖТ Nashik writes (L=3) тАФ cause always has a smaller number
рддреБрдордЪрд╛ snippet рд╣реЗ print рдХрд░рддреЛ:
Pune a=1 b=2 ┬╖ Nagpur c=1 ┬╖ Nashik receives b тЖТ 3, writes e=4
b caused e, so b < e: True
c and b never met, yet c < b: True тАФ a smaller number does NOT mean 'caused'
Pune ahead by 140 ms тЖТ stamps pune 100, nashik 50 тЖТ last-writer-wins keeps 'exam at 10'
Pune ahead by 100 ms тЖТ stamps pune 80, nashik 70 тЖТ last-writer-wins keeps 'exam at 10'
Pune ahead by 60 ms тЖТ stamps pune 40, nashik 70 тЖТ last-writer-wins keeps 'exam at 11'
Pune ahead by 0 ms тЖТ stamps pune -20, nashik 70 тЖТ last-writer-wins keeps 'exam at 11'
ЁЯПБ рддреБрдореНрд╣реА рдЖрддреНрддрд╛рдЪ рдХрд╛рдп рд╕рд┐рджреНрдз рдХреЗрд▓реЗ
рджреЛрди writes рдордзреНрдпреЗ 90 ms рдЪреЗ рдЕрдВрддрд░ рд╣реЛрддреЗ. 100 рдХрд┐рдВрд╡рд╛ 140 ms рдЪреНрдпрд╛ skew рдиреЗ last-writer-wins рдиреЗ
рдЬреБрдирд╛ write рдареЗрд╡рд▓рд╛. 60 ms рдХрд┐рдВрд╡рд╛ рддреНрдпрд╛рд╣реВрди рдХрдореА skew рдиреЗ рддреНрдпрд╛рдиреЗ рдмрд░реЛрдмрд░ write рдареЗрд╡рд▓рд╛. рдореНрд╣рдгрдЬреЗ wall-clock рдХреНрд░рдо
рдлрдХреНрдд рддреЗрд╡реНрд╣рд╛рдЪ рд╕реБрд░рдХреНрд╖рд┐рдд рдЖрд╣реЗ рдЬреЗрд╡реНрд╣рд╛ skew writes рдордзрд▓реНрдпрд╛ рдЕрдВрддрд░рд╛рдкреЗрдХреНрд╖рд╛ рд▓рд╣рд╛рди рдЕрд╕рддреЛ тАФ рдЖрдгрд┐ рддреБрдореНрд╣рд╛рд▓рд╛ рдпрд╛рдкреИрдХреА
рдХреЛрдгрддрд╛рдЪ рдЖрдХрдбрд╛ рдХреНрд╡рдЪрд┐рддрдЪ рдорд╛рд╣реАрдд рдЕрд╕рддреЛ. Lamport рдХреНрд░рдорд╛рдВрдХ рдиреЗрд╣рдореА рдХрд╛рд░рдгрд╛рд▓рд╛ рдкрд░рд┐рдгрд╛рдорд╛рдЪреНрдпрд╛ рдЖрдзреА рдареЗрд╡рддрд╛рдд (b=2 < e=4), рдкрдг c=1 < b=2
рджрд╛рдЦрд╡рддреЗ рдХреА рд▓рд╣рд╛рди рдХреНрд░рдорд╛рдВрдХ рдЕрд╢рд╛ рдШрдЯрдиреЗрдЪрд╛рд╣реА рдЕрд╕реВ рд╢рдХрддреЛ рдЬрд┐рдЪрд╛ рджреБрд╕рд░реАрд╢реА рдХрд╛рд╣реАрдЪ рд╕рдВрдмрдВрдз рдирд╡реНрд╣рддрд╛.
рд╣реЗ рджреЛрди рдкреНрд░рдХрд╛рд░ рд╡реЗрдЧрд│реЗ рдУрд│рдЦрдгреЗ рд╣рд╛ рдкреБрдврдЪрд╛ рдзрдбрд╛ рдЖрд╣реЗ.
тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛
- wall clock рдиреЗ timeout рдореЛрдЬрдгреЗ тАФ NTP рджреБрд░реБрд╕реНрддреАрдореБрд│реЗ рддреЛ negative рдХрд┐рдВрд╡рд╛ рдкреНрд░рдЪрдВрдб рд╣реЛрдК рд╢рдХрддреЛ
- рд╡реЗрдЧрд╡реЗрдЧрд│реНрдпрд╛ machines рд╡рд░рдЪреЗ writes рддреНрдпрд╛рдВрдЪреНрдпрд╛ wall-clock time stamps рдиреБрд╕рд╛рд░ рдХреНрд░рдорд╛рдиреЗ рд▓рд╛рд╡рдгреЗ
- "NTP рдЪрд╛рд▓реВ рдЖрд╣реЗ" рдореНрд╣рдгрдЬреЗ рдШрдбреНрдпрд╛рд│реЗ millisecond рдкрд░реНрдпрдВрдд рдЬреБрд│рддрд╛рдд рдЕрд╕реЗ рдорд╛рдирдгреЗ
- L(a) < L(b) рдЪрд╛ рдЕрд░реНрде "a рдореБрд│реЗ b рдЭрд╛рд▓реЗ" рдЕрд╕рд╛ рдШреЗрдгреЗ
- receive рд╡рд░
max(...) + 1рд╡рд┐рд╕рд░рдгреЗ тАФ рдордЧ рдЙрддреНрддрд░рд╛рд▓рд╛ рддреНрдпрд╛рдЪреНрдпрд╛ рдкреНрд░рд╢реНрдирд╛рдкреЗрдХреНрд╖рд╛ рд▓рд╣рд╛рди рдХреНрд░рдорд╛рдВрдХ рдорд┐рд│реВ рд╢рдХрддреЛ
ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд
On a real server тАФ рдпрд╛ machine рдЪреЗ рдШрдбреНрдпрд╛рд│ рддреНрдпрд╛рдЪреНрдпрд╛ time servers рдкрд╛рд╕реВрди рдХрд┐рддреА рджреВрд░ рдЖрд╣реЗ рддреЗ рддрдкрд╛рд╕рд╛. chrony рд╕рд╣ (рдЕрдиреЗрдХ Linux distributions рд╡рд░рдЪрд╛ default NTP client):
chronyc tracking # "System time : 0.000012 seconds fast of NTP time", plus the estimated error
chronyc sources -v # which servers it uses and how far each one is
timedatectl # "System clock synchronized: yes"
AWS рд╡рд░, Amazon Time Sync Service рдкреНрд░рддреНрдпреЗрдХ VPC рдЪреНрдпрд╛ рдЖрдд 169.254.169.123 рд╡рд░ рдЕрд╕рддреЗ; chrony
/etc/chrony.conf рдордзрд▓реНрдпрд╛ рдПрдХрд╛ рдУрд│реАрдиреЗ рддреА рд╡рд╛рдкрд░рддреЗ:
server 169.254.169.123 prefer iburst minpoll 4 maxpoll 4
рдХрд╛рд▓рд╛рд╡рдзреА monotonic clock рдиреЗ рдореЛрдЬрд╛:
import time
start = time.monotonic()
do_work()
elapsed = time.monotonic() - start # safe even if NTP moves the wall clock meanwhile
рдЬреНрдпрд╛ systems рдирд╛ machines рдкрд▓реАрдХрдбреЗ рд╡реЗрд│ рд▓рд╛рдЧрддреЗ рддреНрдпрд╛ error bar рдЕрд╕рд▓реЗрд▓реЗ рдШрдбреНрдпрд╛рд│ рд╡рд╛рдкрд░рддрд╛рдд, рд╢рдмреНрджрд╛рдВрдд:
- Google TrueTime (Spanner рдЪреНрдпрд╛ рдЖрдд) тАФ рдкреНрд░рддреНрдпреЗрдХ data center рдордзреНрдпреЗ GPS receivers рдЖрдгрд┐ atomic clocks.
TT.now()рдПрдХ рд╡реЗрд│ рдирд╡реНрд╣реЗ рддрд░ рдПрдХ interval [earliest, latest] рдкрд░рдд рджреЗрддреЗ. рдордЧ Spanner commit report рдХрд░рдгреНрдпрд╛рдЖрдзреА рддреЛ interval рд╕рдВрдкреЗрдкрд░реНрдпрдВрдд рдерд╛рдВрдмрддреЛ ("commit wait"), рддреНрдпрд╛рдореБрд│реЗ commit рд╡реЗрд│рд╛ рдЦрд▒реНрдпрд╛ рдХреНрд░рдорд╛рд╢реА рдЬреБрд│рддрд╛рдд. рд╣рд╛ interval рд╕рд╣рд╕рд╛ рдХрд╛рд╣реА milliseconds рдЪрд╛ рдЕрд╕рддреЛ. - Hybrid logical clocks (HLC) тАФ CockroachDB рдЖрдгрд┐ YugabyteDB рд╡рд╛рдкрд░рддрд╛рдд. Time stamp рдореНрд╣рдгрдЬреЗ wall time рдЕрдзрд┐рдХ рдПрдХ рдЫреЛрдЯрд╛ Lamport-рд╕рд╛рд░рдЦрд╛ counter. рддреЛ рдЦрд▒реНрдпрд╛ рд╡реЗрд│реЗрдЪреНрдпрд╛ рдЬрд╡рд│ рд░рд╛рд╣рддреЛ, рдЖрдгрд┐ рдШрдбреНрдпрд╛рд│реЗ рдереЛрдбреА рдЪреБрдХрд▓реА рддрд░реА рдХрд╛рд░рдгрд╛рд▓рд╛ рдкрд░рд┐рдгрд╛рдорд╛рдЪреНрдпрд╛ рдЖрдзреА рдареЗрд╡рддреЛ. рд╣реЗ databases рдЬрд╛рд╕реНрддреАрдд рдЬрд╛рд╕реНрдд рдкрд░рд╡рд╛рдирдЧреА рдЕрд╕рд▓реЗрд▓рд╛ clock offset рд╣реА рдард░рд╡рддрд╛рдд (CockroachDB рдЪрд╛ default 500 ms рдЖрд╣реЗ) рдЖрдгрд┐ рдЬреНрдпрд╛ node рдЪреЗ рдШрдбреНрдпрд╛рд│ рдЦреВрдк рджреВрд░ рдЧреЗрд▓реЗ рдЖрд╣реЗ рддреНрдпрд╛рд▓рд╛ рдерд╛рдВрдмрд╡рддрд╛рдд.
ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд рд╣реЗ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ: рддреБрдордЪреНрдпрд╛ code рдордзреНрдпреЗ machines рдкрд▓реАрдХрдбреЗ "sort by created_at" рдЖрдгрд┐
time.time()рдкрд╛рд╕реВрди рдмрдирд╡рд▓реЗрд▓реЗ timeouts рд╢реЛрдзрд╛. рдХрд╛рд▓рд╛рд╡рдзреАрд╕рд╛рдареА monotonic clock рд╡рд╛рдкрд░рд╛, рдЖрдгрд┐ рдХреНрд░рдорд╛рд╕рд╛рдареА database sequence, version number рдХрд┐рдВрд╡рд╛ Lamport/HLC time stamp рд╡рд╛рдкрд░рд╛.
тПня╕П рдкреБрдвреЗ
Lamport рдХреНрд░рдорд╛рдВрдХ "рдХрджрд╛рдЪрд┐рдд рдЖрдзреА" рд╕рд╛рдВрдЧрддрд╛рдд. "рдпрд╛ рджреЛрдШрд╛рдВрдирд╛ рдПрдХрдореЗрдХрд╛рдВрдмрджреНрджрд▓ рдорд╛рд╣реАрдд рдирд╡реНрд╣рддреЗ" рд╣реЗ рддреЗ рд╕рд╛рдВрдЧреВ рд╢рдХрдд рдирд╛рд╣реАрдд. Vector clocks рд╕рд╛рдВрдЧреВ рд╢рдХрддрд╛рдд.
git checkout lesson-03-ordering