ЁЯФБ рдзрдбрд╛ 10 тАФ Consistency: рд╕реВрдЪрдирд╛-рдиреЛрдВрджрд╡рд╣реАрдЪреНрдпрд╛ рддреАрди рдкреНрд░рддреА
ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 18 рдкреИрдХреА рдзрдбрд╛ 10 ┬╖ рдкреБрдвреАрд▓: lesson-11-distributed-transactions
ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ
рдзрдбреЗ 01тАУ09, рдЖрдгрд┐ рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░рдд рдЙрднрд╛ рдХрд░рдгрд╛рд░рд╛ рдкреНрд░рд╢реНрди: data рдПрдХрд╛рдкреЗрдХреНрд╖рд╛ рдЬрд╛рд╕реНрдд рдард┐рдХрд╛рдгреА рд░рд╛рд╣рддреЛ рддреЗрд╡реНрд╣рд╛ рдХреЛрдгрддреА рдкреНрд░рдд рдЦрд░реЗ рд╕рд╛рдВрдЧрддреЗ? рддреБрдореНрд╣реА рд╢рд┐рдХрддрд╛ strong рдЖрдгрд┐ eventual consistency, replicas рдЖрдгрд┐ replication lag, quorums (R + W > N), read-your-writes, monotonic reads, рд╕реЛрдкреНрдпрд╛ рд╢рдмреНрджрд╛рдВрдд CAP рдЖрдгрд┐ PACELC, рдЖрдгрд┐ data рдЪреНрдпрд╛ рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░рдХрд╛рд░рд╛рд╕рд╛рдареА рдирд┐рд╡рдб рдХрд╢реА рдХрд░рд╛рдпрдЪреА.
- design/blocks.py тАФ
quorum_ok(n, r, w)рдЖрдгрд┐quorum_read(copies, r) - design/demo.py тАФ
python3 design/demo.py consistency - design/test_design.py тАФ check L10
- demo-output.txt тАФ рдирд┐рд░реЛрдЧреА run рдХрд╛рдп рдЫрд╛рдкрддреЛ
ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ
рджреАрдкрд┐рдХрд╛рдЪреЗ рдирд┐рдпреЛрдЬрди рдХрд╛рд░реНрдпрд╛рд▓рдп рд╕реВрдЪрдирд╛-рдиреЛрдВрджрд╡рд╣реА рддреАрди рд╢рд┐рдХреНрд╖рдХ-рдЦреЛрд▓реНрдпрд╛рдВрдд рдареЗрд╡рддреЗ, рдореНрд╣рдгрдЬреЗ рдПрдХ рдЦреЛрд▓реА рдХреБрд▓реВрдкрдмрдВрдж рдЕрд╕рд▓реА рддрд░реА рд╕рдЧрд│реНрдпрд╛рдВрдЪреЗ рдХрд╛рдо рдерд╛рдВрдмрдд рдирд╛рд╣реА.
рдХрддрд░рд┐рдирд╛ рдПрдХ рд╕реВрдЪрдирд╛ рдмрджрд▓рддреЗ: "рдкрд░реАрдХреНрд╖рд╛ рдордВрдЧрд│рд╡рд╛рд░реА рд╣рд▓рд╡рд▓реА." рддреА рд╣реЗ рдЦреЛрд▓реА 1 рдордзреАрд▓ рдиреЛрдВрджрд╡рд╣реАрдд рд▓рд┐рд╣рд┐рддреЗ. рдордЧ рдПрдХ рдзрд╛рд╡рдкрдЯреВ рд╣рд╛ рдмрджрд▓ рдЦреЛрд▓реА 2 рдЖрдгрд┐ 3 рдордзреНрдпреЗ рдШреЗрдКрди рдЬрд╛рддреЛ. рдзрд╛рд╡рдкрдЯреВрд▓рд╛ рдереЛрдбрд╛ рд╡реЗрд│ рд▓рд╛рдЧрддреЛ.
рдРрд╢реНрд╡рд░реНрдпрд╛ рдЦреЛрд▓реА 3 рдордзреНрдпреЗ рдЖрд╣реЗ. рддреА рдзрд╛рд╡рдкрдЯреВ рдкреЛрд╣реЛрдЪрдгреНрдпрд╛рдЖрдзреА рдиреЛрдВрджрд╡рд╣реА рд╡рд╛рдЪрддреЗ. рддрд┐рд▓рд╛ "рд╕реЛрдорд╡рд╛рд░" рджрд┐рд╕рддреЛ. рдХрд╛рд╣реАрд╣реА рддреБрдЯрд▓реЗрд▓реЗ рдирд╛рд╣реА. рддрд┐рдЪреА рдкреНрд░рдд рдлрдХреНрдд рдЙрд╢рд┐рд░рд╛рдЪреА рдЖрд╣реЗ.
рджреАрдкрд┐рдХрд╛ рдПрдХ рдирд┐рдпрдо рдХрд░рддреЗ: "рдЭрд╛рд▓реЗ рдореНрд╣рдгрдгреНрдпрд╛рдЖрдзреА рдмрджрд▓ рджреЛрди рдиреЛрдВрджрд╡рд╣реНрдпрд╛рдВрдд рд▓рд┐рд╣рд╛. рджреЛрди рдиреЛрдВрджрд╡рд╣реНрдпрд╛ рд╡рд╛рдЪрд╛ рдЖрдгрд┐ рдЬрд╛рд╕реНрдд рдкрд╛рди-рдХреНрд░рдорд╛рдВрдХ рдЕрд╕рд▓реЗрд▓реЗ рдкрд╛рди рдареЗрд╡рд╛." рджреЛрди рд▓рд┐рд╣рд┐рд▓реЗрд▓реНрдпрд╛ рдЕрдзрд┐рдХ рджреЛрди рд╡рд╛рдЪрд▓реЗрд▓реНрдпрд╛ рдиреЛрдВрджрд╡рд╣реНрдпрд╛ рдореНрд╣рдгрдЬреЗ рдЪрд╛рд░ тАФ рддреАрди рдЦреЛрд▓реНрдпрд╛рдВрдкреЗрдХреНрд╖рд╛ рдЬрд╛рд╕реНрдд. рдореНрд╣рдгреВрди рджреЛрдиреНрд╣реА рдЧрдЯрд╛рдВрдд рдиреЗрд╣рдореА рдПрдХ рдЦреЛрд▓реА рд╕рд╛рдорд╛рдИрдХ рдЕрд╕рддреЗ, рдЖрдгрд┐ рд╡рд╛рдЪрдгрд╛рд░реАрд▓рд╛ рдиреЗрд╣рдореА рдирд╡реЗ рдкрд╛рди рд╕рд╛рдкрдбрддреЗ.
рдПрдХреЗ рджрд┐рд╡рд╢реА рдорд╛рд░реНрдЧрд┐рдХрд╛ рдЕрдбрддреЗ. рдЦреЛрд▓реА 3 рдмрд╛рдХреАрдЪреНрдпрд╛рдВрдкрд░реНрдпрдВрдд рдкреЛрд╣реЛрдЪреВ рд╢рдХрдд рдирд╛рд╣реА. рдПрдХ рдкрд╛рд▓рдХ рдЦреЛрд▓реА 3 рд▓рд╛ рд╡рд┐рдЪрд╛рд░рддреЛ. рдЦреЛрд▓реА 3 рдХрдбреЗ рджреЛрди рдкрд░реНрдпрд╛рдп рдЕрд╕рддрд╛рдд: рдЬреЗ рдЖрд╣реЗ рддреЗ рдЙрддреНрддрд░ рджреНрдпрд╛рдпрдЪреЗ (рдХрджрд╛рдЪрд┐рдд рдЬреБрдиреЗ), рдХрд┐рдВрд╡рд╛ "рдХреГрдкрдпрд╛ рдерд╛рдВрдмрд╛" рдореНрд╣рдгрд╛рдпрдЪреЗ (рдмрд░реЛрдмрд░ рд░рд╛рд╣рд╛рдпрдЪреЗ). рджреЛрдиреНрд╣реА рдПрдХрджрдо рдХрд░рддрд╛ рдпреЗрдд рдирд╛рд╣реА. рд╣реАрдЪ рдирд┐рд╡рдб рдореНрд╣рдгрдЬреЗ CAP.
ЁЯЧ║я╕П рдЖрдХреГрддреА
flowchart LR
w["тЬНя╕П Katrina writes v8<br/>exam moved to Tuesday"]
subgraph n3["ЁЯУЪ N = 3 copies"]
c1["room 1 ┬╖ v8"]
c2["room 2 ┬╖ v8"]
c3["room 3 ┬╖ v7 ┬╖ lag"]
end
w -->|"W = 2: wait for 2 copies"| c1
w -->|"W = 2"| c2
w -.->|"later"| c3
r["ЁЯСА Aishwarya reads<br/>R = 2, keep the newest"]
r --> c2
r --> c3
ok["2 + 2 > 3 тЖТ the groups overlap<br/>she sees v8"]
r --> ok
ЁЯЧ║я╕П рдХрд╛рдврд▓реЗрд▓реА рдЖрд╡реГрддреНрддреА + рдПрдХ lab: https://school-edh.pages.dev/system-design/lesson-diagrams.html#l10
тЭУ рдХрд╛рдп
- Replica тАФ рджреБрд╕рд▒реНрдпрд╛ server рд╡рд░рдЪреА data рдЪреА рдкреВрд░реНрдг рдкреНрд░рдд. Replicas рдореБрд│реЗ рдЬрд╛рд╕реНрдд рд╡рд╛рдЪрдХ рд╕рд╛рдВрднрд╛рд│рддрд╛ рдпреЗрддрд╛рдд, рдЖрдгрд┐ рдПрдХ server рдЧреЗрд▓рд╛ рддрд░реА system рдЯрд┐рдХрддреЗ.
- Replication lag тАФ рдПрдХрд╛ рдкреНрд░рддреАрд╡рд░ write рдЭрд╛рд▓реНрдпрд╛рдкрд╛рд╕реВрди рддреЛ рдмрд╛рдХреАрдЪреНрдпрд╛ рдкреНрд░рддреАрдВрд╡рд░ рдкреЛрд╣реЛрдЪреЗрдкрд░реНрдпрдВрддрдЪрд╛ рд╡реЗрд│. рд╕рд╣рд╕рд╛ milliseconds. Load рдЕрд╕рддрд╛рдирд╛, рдХрд┐рдВрд╡рд╛ regions рдУрд▓рд╛рдВрдбреВрди, рддреЛ seconds рдХрд┐рдВрд╡рд╛ рддреНрдпрд╛рд╣реВрди рдЬрд╛рд╕реНрдд рдЕрд╕реВ рд╢рдХрддреЛ.
- Strong consistency тАФ рдкреНрд░рддреНрдпреЗрдХ read рдирд╡реАрдирддрдо рдкреВрд░реНрдг рдЭрд╛рд▓реЗрд▓рд╛ write рдкрд╛рд╣рддреЛ. рдЬрдгреВ рдПрдХрдЪ рдкреНрд░рдд рдЖрд╣реЗ рдЕрд╕реЗ рд╡рд╛рдЯрддреЗ.
- Eventual consistency тАФ writes рдерд╛рдВрдмрд▓реЗ рддрд░ рд╕рдЧрд│реНрдпрд╛ рдкреНрд░рддреА рд╢реЗрд╡рдЯреА рд╕рд╛рд░рдЦреНрдпрд╛ рд╣реЛрддрд╛рдд. рддреЛрдкрд░реНрдпрдВрдд рдПрдЦрд╛рджрд╛ read рдЬреБрдиреА value рджреЗрдК рд╢рдХрддреЛ.
- Quorum тАФ N рдкреНрд░рддреА рдЕрд╕рддрд╛рдирд╛, write рддреНрдпрд╛рдВрдкреИрдХреА W рдЪреА рд╡рд╛рдЯ рдкрд╛рд╣рддреЛ, рдЖрдгрд┐ read R рдкреНрд░рддреАрдВрдирд╛ рд╡рд┐рдЪрд╛рд░рддреЛ рдЖрдгрд┐ рд╕рд░реНрд╡рд╛рдд рдирд╡реА version рдареЗрд╡рддреЛ. R + W > N рдЕрд╕реЗрд▓, рддрд░ рдкреНрд░рддреНрдпреЗрдХ read рдЧрдЯрд╛рдд рдкреНрд░рддреНрдпреЗрдХ write рдЧрдЯрд╛рд╢реА рдХрд┐рдорд╛рди рдПрдХ рдкреНрд░рдд рд╕рд╛рдорд╛рдИрдХ рдЕрд╕рддреЗ, рдореНрд╣рдгреВрди read рд▓рд╛ рдирд╡реАрдирддрдо write рджрд┐рд╕рддреЛ. N = 3 рд╕рд╣ R = 2 рдЖрдгрд┐ W = 2 рд╣реА рдиреЗрд╣рдореАрдЪреА рдирд┐рд╡рдб. рддреНрдпрд╛рдд рдПрдХ рдкреНрд░рдд рдЧреЗрд▓реА рддрд░реА system рдЯрд┐рдХрддреЗ.
- Read-your-writes тАФ рддреБрдореНрд╣реА рдХрд╛рд╣реА рдмрджрд▓рд▓реНрдпрд╛рд╡рд░ рддреБрдореНрд╣рд╛рд▓рд╛ рддреБрдордЪрд╛ рдмрджрд▓ рджрд┐рд╕рддреЛ. рдЗрддрд░ рд╡рд╛рдЪрдХрд╛рдВрдирд╛ рдХреНрд╖рдгрднрд░ рдЬреБрдиреА value рджрд┐рд╕реВ рд╢рдХрддреЗ. рд╣реЗ рдорд┐рд│рд╡рдгреНрдпрд╛рдЪреЗ рдорд╛рд░реНрдЧ: рд╕реНрд╡рддрдГрдЪреНрдпрд╛ write рдирдВрддрд░ рдХрд╛рд╣реА seconds primary рд╡рд░реВрди read рдХрд░рд╛, рдХрд┐рдВрд╡рд╛ рддреБрдореНрд╣реА рд▓рд┐рд╣рд┐рд▓реЗрд▓реА version рд▓рдХреНрд╖рд╛рдд рдареЗрд╡рд╛ рдЖрдгрд┐ рддреА рдЕрд╕рд▓реЗрд▓реНрдпрд╛ рдкреНрд░рддреАрд╡рд░реВрдирдЪ read рдХрд░рд╛.
- Monotonic reads тАФ рд╡рд╛рдЪрдгрд╛рд░реА рдХрдзреА рдХрд╛рд│рд╛рдд рдорд╛рдЧреЗ рдЬрд╛рдд рдирд╛рд╣реА: "рдордВрдЧрд│рд╡рд╛рд░" рдкрд╛рд╣рд┐рд▓реНрдпрд╛рд╡рд░ рддрд┐рд▓рд╛ рдкреБрдиреНрд╣рд╛ "рд╕реЛрдорд╡рд╛рд░" рджрд┐рд╕рддрд╛ рдХрд╛рдорд╛ рдирдпреЗ. рд╣реЗ рдорд┐рд│рд╡рдгреНрдпрд╛рдЪрд╛ рдорд╛рд░реНрдЧ: рдПрдХрд╛ рд╡рд╛рдЪрдХрд╛рд▓рд╛ рддреНрдпрд╛рдЪ replica рд╡рд░ рдареЗрд╡рд╛ (sticky), рдХрд┐рдВрд╡рд╛ рддрд┐рдиреЗ рд╢реЗрд╡рдЯрдЪреА рдкрд╛рд╣рд┐рд▓реЗрд▓реА version рд▓рдХреНрд╖рд╛рдд рдареЗрд╡рд╛.
- CAP тАФ network split (Partition) рдЪреНрдпрд╛ рд╡реЗрд│реА, рдмрд╛рдХреАрдЪреНрдпрд╛рдВрдкрд░реНрдпрдВрдд рдкреЛрд╣реЛрдЪреВ рди рд╢рдХрдгрд╛рд▒реНрдпрд╛ рдкреНрд░рддреАрд▓рд╛ рдирд┐рд╡рдб рдХрд░рд╛рд╡реА рд▓рд╛рдЧрддреЗ: Consistent рд░рд╛рд╣рд╛рдпрдЪреЗ (рдирдХрд╛рд░ рджреНрдпрд╛рдпрдЪрд╛ рдХрд┐рдВрд╡рд╛ рдерд╛рдВрдмрд╛рдпрдЪреЗ) рдХреА Available рд░рд╛рд╣рд╛рдпрдЪреЗ (рдЙрддреНрддрд░ рджреНрдпрд╛рдпрдЪреЗ, рдХрджрд╛рдЪрд┐рдд рдЬреБрдиреЗ). Splits рд╣реЛрддрд╛рддрдЪ, рдореНрд╣рдгреВрди рдЦрд░реА рдирд┐рд╡рдб split рдЪреНрдпрд╛ рд╡реЗрд│реА C рдЖрдгрд┐ A рдордзреНрдпреЗ рдЕрд╕рддреЗ.
- PACELC тАФ рдЙрд░рд▓реЗрд▓реА рдЧреЛрд╖реНрдЯ: Partition рдЕрд╕реЗрд▓ рддрд░ A рдХрд┐рдВрд╡рд╛ C рдирд┐рд╡рдбрд╛; Else (рд╕рд╛рдорд╛рдиреНрдп рджрд┐рд╡рд╢реА), Latency рдХрд┐рдВрд╡рд╛ Consistency рдирд┐рд╡рдбрд╛. рдЬрд╛рд╕реНрдд рдкреНрд░рддреАрдВрдЪреА рд╡рд╛рдЯ рдкрд╛рд╣рдгреЗ рд╣рд│реВ рдЕрд╕рддреЗ. рд╣реА рдирд┐рд╡рдб рддреБрдореНрд╣реА рджрд░рд░реЛрдЬ рдХрд░рддрд╛, рдлрдХреНрдд split рдЪреНрдпрд╛ рд╡реЗрд│реА рдирд╛рд╣реА.
ЁЯдФ рдХрд╛
рдХрд╛рд░рдг рдзрдбреЗ 05тАУ09 рдиреЗ рд╕рдЧрд│реАрдХрдбреЗ рдкреНрд░рддреА рддрдпрд╛рд░ рдХреЗрд▓реНрдпрд╛: caches, read replicas, рдЗрддрд░ services update рдХрд░рдгрд╛рд░реЗ events. рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░рдд рдЙрд╢рд┐рд░рд╛рдЪреА рдЕрд╕реВ рд╢рдХрддреЗ. рдирд┐рдпреЛрдЬрди рдХрд╛рд░реНрдпрд╛рд▓рдпрд╛рдиреЗ data рдЪреНрдпрд╛ рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░рдХрд╛рд░рд╛рд╕рд╛рдареА рдард░рд╡рд▓реЗ рдкрд╛рд╣рд┐рдЬреЗ рдХреА рдХрд┐рддреА рдЙрд╢реАрд░ рдЪрд╛рд▓рддреЛ. рдПрдХрд╛ рджрд┐рд╢реЗрдиреЗ рдЪреВрдХ рдЭрд╛рд▓реА, рддрд░ рдкрд╛рд▓рдХ fee рджреЛрдирджрд╛ рднрд░рддреЛ. рджреБрд╕рд▒реНрдпрд╛ рджрд┐рд╢реЗрдиреЗ рдЪреВрдХ рдЭрд╛рд▓реА, рддрд░ рдкреВрд░реНрдг app рдПрдХрд╛ view counter рд╕рд╛рдареА рдерд╛рдВрдмрддреЛ.
рд╕реВрдЪрдирд╛ рдлрд▓рдХ, рдкреНрд░рддреНрдпреЗрдХ data рдкреНрд░рдХрд╛рд░рд╛рд╕рд╛рдареА рдард░рд╡рд▓реЗрд▓реЗ:
| data | рдирд┐рд╡рдб | рдХрд╛ |
|---|---|---|
| fee payments | strong | рдкреИрд╕реЗ рдХрдзреАрд╣реА рджреЛрдирджрд╛ рдореЛрдЬрд▓реЗ рдЬрд╛рдК рдирдпреЗрдд рдХрд┐рдВрд╡рд╛ рд╣рд░рд╡реВ рдирдпреЗрдд |
| рдЧреБрдг | strong | рджреБрд░реБрд╕реНрддреАрдирдВрддрд░ рдкрд╛рд▓рдХрд╛рд▓рд╛ рдЬреБрдирд╛ рдЧреБрдг рджрд┐рд╕рддрд╛ рдХрд╛рдорд╛ рдирдпреЗ |
| рдХреЛрдг рдХреЛрдгрддреНрдпрд╛ рд╡рд░реНрдЧрд╛рдд рдЖрд╣реЗ (access) | strong | рдХрд╛рдврд▓реЗрд▓реНрдпрд╛ рдкрд╛рд▓рдХрд╛рдЪрд╛ access рд▓рдЧреЗрдЪ рдЧреЗрд▓рд╛ рдкрд╛рд╣рд┐рдЬреЗ |
| рд╕реВрдЪрдирд╛, рддрд┐рдЪреНрдпрд╛ рд▓реЗрдЦрд┐рдХреЗрд╕рд╛рдареА | read-your-writes | "posted" рдирдВрддрд░ рдХрддрд░рд┐рдирд╛рд▓рд╛ рддрд┐рдЪреА рд╕реНрд╡рддрдГрдЪреА post рджрд┐рд╕рд▓реА рдкрд╛рд╣рд┐рдЬреЗ |
| рд╕реВрдЪрдирд╛, рдЗрддрд░ рдкрд╛рд▓рдХрд╛рдВрд╕рд╛рдареА | eventual (seconds) | рдХрд╛рд╣реА seconds рдЙрд╢реАрд░ рдЪрд╛рд▓рддреЛ |
| "312 рдкрд╛рд▓рдХрд╛рдВрдиреА рд╡рд╛рдЪрд▓реА" counters, likes | eventual | 2 seconds рдЬреБрдиреНрдпрд╛ рдЖрдХрдбреНрдпрд╛рдиреЗ рдХреЛрдгрд╛рдЪреЗ рдиреБрдХрд╕рд╛рди рд╣реЛрдд рдирд╛рд╣реА |
ЁЯФз рдХрд╕реЗ (рдпрд╛ repo рдордзреНрдпреЗ)
design/blocks.py рдордзреАрд▓ quorum_ok(n, r, w) r + w > n рдкрд░рдд рдХрд░рддреЛ.
quorum_read(copies, r) (version, value) рдкреНрд░рддреАрдВрдЪреА рдпрд╛рджреА рдШреЗрддреЛ, рддреНрдпрд╛рдВрдкреИрдХреА рдкрд╣рд┐рд▓реНрдпрд╛ r рд╡рд╛рдЪрддреЛ
рдЖрдгрд┐ рд╕рд░реНрд╡рд╛рдд рдореЛрдареА version рдареЗрд╡рддреЛ. design/demo.py рдордзреАрд▓ consistency()
N = 3 рд╕рд╛рдареА рдЪрд╛рд░ R/W рдЬреЛрдбреНрдпрд╛ рд╡рд╛рдкрд░реВрди рдкрд╛рд╣рддреЛ, рдордЧ рдЕрд╢рд╛ рддреАрди рдкреНрд░рддреА рд╡рд╛рдЪрддреЛ рдЬреНрдпрд╛рдВрдкреИрдХреА рдлрдХреНрдд рдПрдХреАрдХрдбреЗ рдирд╡реА version 8 рдЖрд╣реЗ.
ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛
python3 design/demo.py consistency
python3 - <<'EOF'
import sys; sys.path.insert(0, "design"); from blocks import quorum_ok, quorum_read
for n in (3, 5):
strong = [f"R={r} W={w}" for r in range(1, n + 1) for w in range(1, n + 1) if quorum_ok(n, r, w)]
print(f"N={n}: {len(strong)} of {n * n} choices are strong ┬╖ smallest pair with R = W: R=W={n // 2 + 1}")
copies = [(8, "exam moved to Tuesday"), (7, "exam on Monday"), (7, "exam on Monday")]
print("W=1 (only copy 1 has v8):", "R=1 from copy 3 тЖТ", quorum_read(copies[2:], 1)[1], "┬╖ R=2 from copies 2,3 тЖТ", quorum_read(copies[1:], 2)[1])
copies = [(8, "exam moved to Tuesday"), (8, "exam moved to Tuesday"), (7, "exam on Monday")]
print("W=2 (copies 1,2 have v8):", "R=2 from copies 2,3 тЖТ", quorum_read(copies[1:], 2)[1], "┬╖ R=2 from copies 1,3 тЖТ", quorum_read(copies[::2], 2)[1])
EOF
python3 design/test_design.py
тЬЕ рддрдкрд╛рд╕рд╛ тАФ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рджрд┐рд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ
consistency рд╣реЗ рдЫрд╛рдкрддреЛ:
тФАтФА 3 copies (N=3): which read/write sizes are sure to see the latest write? (R + W > N)
R=1 W=1 тЖТ eventual: may read a stale copy
R=1 W=3 тЖТ strong: overlaps
R=2 W=2 тЖТ strong: overlaps
R=3 W=1 тЖТ strong: overlaps
copies [(7, 'exam on Monday'), (8, 'exam moved to Tuesday'), (7, 'exam on Monday')] ┬╖ read R=1 тЖТ 'exam on Monday' ┬╖ read R=2 тЖТ 'exam moved to Tuesday'
CAP: during a network split you choose тАФ answer (maybe stale) or refuse (stay correct)
most apps: strong for money and grades, eventual for likes and view counts
рддреБрдордЪрд╛ snippet рд╣реЗ рдЫрд╛рдкрддреЛ:
N=3: 6 of 9 choices are strong ┬╖ smallest pair with R = W: R=W=2
N=5: 15 of 25 choices are strong ┬╖ smallest pair with R = W: R=W=3
W=1 (only copy 1 has v8): R=1 from copy 3 тЖТ exam on Monday ┬╖ R=2 from copies 2,3 тЖТ exam on Monday
W=2 (copies 1,2 have v8): R=2 from copies 2,3 тЖТ exam moved to Tuesday ┬╖ R=2 from copies 1,3 тЖТ exam moved to Tuesday
Tests рдордзреНрдпреЗ тЬЕ L10 R + W > N overlaps; R=1 W=1 does not рдЕрд╕рддреЗ рдЖрдгрд┐ рд╢реЗрд╡рдЯреА 18/18 passed рдпреЗрддреЗ.
ЁЯПБ рддреБрдореНрд╣реА рдЖрддреНрддрд╛рдЪ рдХрд╛рдп рд╕рд┐рджреНрдз рдХреЗрд▓реЗ
3 рдкреНрд░рддреА рдЕрд╕рддрд╛рдирд╛ 9 рдкреИрдХреА 6 R/W рдЬреЛрдбреНрдпрд╛ strong рдЕрд╕рддрд╛рдд; 5 рдкреНрд░рддреА рдЕрд╕рддрд╛рдирд╛ рд╕рд░реНрд╡рд╛рдд рд▓рд╣рд╛рди рд╕рдорд╛рди рдЬреЛрдбреА R = W = 3 тАФ рдореНрд╣рдгрдЬреЗ рдмрд╣реБрдордд. Demo рдордзреАрд▓ R = 2 read рдиреАрдЯ рдкрд╛рд╣рд╛: рддреНрдпрд╛рд▓рд╛ "Tuesday" рд╕рд╛рдкрдбрд▓реЗ, рдкрдг рдлрдХреНрдд рдПрдХрд╛рдЪ рдкреНрд░рддреАрдХрдбреЗ version 8 рд╣реЛрддреА (W = 1), рдЖрдгрд┐ 2 + 1 рд╣реЗ 3 рдкреЗрдХреНрд╖рд╛ рдЬрд╛рд╕реНрдд рдирд╛рд╣реА. Demo рдиреЗ рдкреНрд░рддреА 1 рдЖрдгрд┐ 2 рд╡рд╛рдЪрд▓реНрдпрд╛ рдЖрдгрд┐ рддреЗ рдирд╢рд┐рдмрд╛рдиреЗ рдмрд░реЛрдмрд░ рдЖрд▓реЗ. рддреБрдордЪреНрдпрд╛ snippet рдиреЗ рдкреНрд░рддреА 2 рдЖрдгрд┐ 3 рд╡рд╛рдЪрд▓реНрдпрд╛ рдЖрдгрд┐ "Monday" рдорд┐рд│рд╛рд▓реЗ. W = 2 рдЕрд╕рддрд╛рдирд╛ рджреЛрди рдкреНрд░рддреАрдВрдЪреА рдкреНрд░рддреНрдпреЗрдХ рдЬреЛрдбреА "Tuesday" рд╢реЛрдзрддреЗ. Quorum рдореНрд╣рдгрдЬреЗ "рдЬрд╛рд╕реНрдд рдкреНрд░рддреА рд╡рд╛рдЪрд╛" рдирд╡реНрд╣реЗ. рддреЗ рдореНрд╣рдгрдЬреЗ "read рдЧрдЯ рдЖрдгрд┐ write рдЧрдЯ рдПрдХрдореЗрдХрд╛рдВрдирд╛ рдЫреЗрджрддреАрд▓ рдЕрд╕реЗ рдХрд░рд╛".
тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛
- write рдирдВрддрд░ рд▓рдЧреЗрдЪ replica рд╡рд░реВрди read рдХрд░рдгреЗ, рдЖрдгрд┐ рдордЧ рд▓реЗрдЦрдХрд╛рд▓рд╛ рдЬреБрдиреА value рджрд╛рдЦрд╡рдгреЗ ("рдореА post рдХреЗрд▓реЗ, рддреЗ рдХреБрдареЗ рдЖрд╣реЗ?") тАФ read-your-writes рд╡рд╛рдкрд░рд╛
- рдПрдХрд╛рдЪ рдкрд╛рд▓рдХрд╛рд▓рд╛ рдкреНрд░рддреНрдпреЗрдХ page рд╡рд░ рд╡реЗрдЧрд│реНрдпрд╛ replica рдХрдбреЗ рдкрд╛рдард╡рдгрд╛рд░рд╛ load balancer тАФ рд╕реВрдЪрдирд╛ рджрд┐рд╕рддреЗ, рдЧрд╛рдпрдм рд╣реЛрддреЗ рдЖрдгрд┐ рдкреБрдиреНрд╣рд╛ рджрд┐рд╕рддреЗ (monotonic reads рдирд╛рд╣реАрдд)
- рд╕рдЧрд│реНрдпрд╛рд╕рд╛рдареА strong consistency рдирд┐рд╡рдбрдгреЗ тАФ рдкреНрд░рддреНрдпреЗрдХ write рд╕рд░реНрд╡рд╛рдд рд╣рд│реВ рдкреНрд░рддреАрдЪреА рд╡рд╛рдЯ рдкрд╛рд╣рддреЛ
- рдкреИрд╕реЗ, рдЧреБрдг рдХрд┐рдВрд╡рд╛ access rights рд╕рд╛рдареА eventual consistency рдирд┐рд╡рдбрдгреЗ
- рдХрд╛рдЧрджрд╛рд╡рд░ R + W > N, рдкрдг "sloppy" quorums рдХрд┐рдВрд╡рд╛ hinted handoff рдЪрд╛рд▓реВ, рдЬреЗ рдЕрдкрдпрд╢рд╛рдЪреНрдпрд╛ рд╡реЗрд│реА рдЗрддрд░ nodes рд╡рд░ рд▓рд┐рд╣рд┐рддрд╛рдд тАФ database рдЪреНрдпрд╛ рдмрд╛рд░реАрдХ рдЕрдЯреА рд╡рд╛рдЪрд╛
- рд╕рд╛рдорд╛рдиреНрдп рджрд┐рд╡рд╢реА CAP рдореНрд╣рдгрдЬреЗ "рддреАрдирдкреИрдХреА рджреЛрди рдирд┐рд╡рдбрд╛" рдЕрд╕реЗ рд╕рдордЬрдгреЗ тАФ рдирд┐рд╡рдб рдлрдХреНрдд split рдЪреНрдпрд╛ рд╡реЗрд│реА рдЕрд╕рддреЗ; рд╕рд╛рдорд╛рдиреНрдп рджрд┐рд╡рд╢реА рджреЗрд╡рд╛рдгрдШреЗрд╡рд╛рдг latency рд╡рд┐рд░реБрджреНрдз consistency рдЕрд╢реА рдЕрд╕рддреЗ (PACELC)
ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд
рдЦрд▒реНрдпрд╛ account рд╡рд░ тАФ DynamoDB reads default рдиреЗ eventually consistent рдЕрд╕рддрд╛рдд. Strongly consistent read рдорд╛рдЧрд╛ (рддреНрдпрд╛рд▓рд╛ рджреБрдкреНрдкрдЯ read capacity рд▓рд╛рдЧрддреЗ, рдЖрдгрд┐ global tables рдЪреЗ рд╕реНрд╡рддрдГрдЪреЗ рдирд┐рдпрдо рдЕрд╕рддрд╛рдд):
aws dynamodb get-item --table-name notices \
--key '{"class_id":{"S":"3A"},"created_at":{"S":"2026-09-27T09:00:00Z"}}' \
--consistent-read
Cassandra: рдкреНрд░рддреНрдпреЗрдХ query рд╕рд╛рдареА level рдард░рд╡рд╛. Read рдЖрдгрд┐ write рджреЛрдиреНрд╣реАрд╕рд╛рдареА QUORUM рджрд┐рд▓реНрдпрд╛рд╕ R + W > N рдорд┐рд│рддреЗ:
CONSISTENCY QUORUM;
SELECT * FROM notices WHERE class_id = '3A' LIMIT 20;
Synchronous replicas рд╕рд╣ PostgreSQL: commit рддреЛрдкрд░реНрдпрдВрдд рдерд╛рдВрдмрддреЛ рдЬреЛрдкрд░реНрдпрдВрдд рджреЛрдирдкреИрдХреА рдПрдХрд╛ standby рдХрдбреЗ рддреЛ рдкреЛрд╣реЛрдЪрдд рдирд╛рд╣реА
(primary рд╡рд░реАрд▓ postgresql.conf):
synchronous_standby_names = 'ANY 1 (standby_a, standby_b)'
synchronous_commit = on
App рдордзреНрдпреЗ read-your-writes: рдкрд╛рд▓рдХ рдХрд┐рдВрд╡рд╛ рд╢рд┐рдХреНрд╖рд┐рдХреЗрдиреЗ рд▓рд┐рд╣рд┐рд▓реНрдпрд╛рд╡рд░, рдХрд╛рд╣реА seconds рддрд┐рдЪреЗ reads primary рдХрдбреЗ рдкрд╛рдард╡рд╛:
def db_for_read(session):
if time.time() - session.get("last_write_at", 0) < 5: # 5 s > the usual replica lag
return PRIMARY
return REPLICA
ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд рд╣реЗ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ: рдкреНрд░рддреНрдпреЗрдХ design рдЪреНрдпрд╛ data table рдордзреНрдпреЗ рдПрдХ "consistency" column рдареЗрд╡рд╛: strong, read-your-writes рдХрд┐рдВрд╡рд╛ eventual тАФ рдЖрдгрд┐ рдХрд╛ рдпрд╛рдЪреА рдПрдХ рдУрд│. рдордЧ replica lag рд╡рд░ alarm рд▓рд╛рд╡рд╛ (рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде RDS read replicas рд╕рд╛рдареА CloudWatch рдордзреАрд▓
ReplicaLag), рдХрд╛рд░рдг "eventual" рддреЛрдкрд░реНрдпрдВрддрдЪ рдЪрд╛рд▓рддреЗ рдЬреЛрдкрд░реНрдпрдВрдд "eventual" рдХрдореА рд╡реЗрд│рд╛рдЪреЗ рдЖрд╣реЗ.
тПня╕П рдкреБрдвреЗ
рдкреНрд░рддреА рдЕрд╕рд▓реЗрд▓реА рдПрдХ service рдЖрддрд╛ рд╕реНрдкрд╖реНрдЯ рдЭрд╛рд▓реА. рдкрдг рд╢рд╛рд│реЗрдЪреНрдпрд╛ рд╕рд╣рд▓реАрдЪреЗ booking рддреАрди services рдирд╛ рд╕реНрдкрд░реНрд╢ рдХрд░рддреЗ: seats, payment рдЖрдгрд┐ bus. рддрд┐рд╕рд░реА рдирд╛рд╣реА рдореНрд╣рдгрд╛рд▓реА рддрд░? Services рдУрд▓рд╛рдВрдбреВрди transactions.
git checkout lesson-11-distributed-transactions