✂️ धडा 08 — CAP & PACELC: जेव्हा रस्ता तुटतो
📍 तुम्ही इथे आहात: 12 पैकी धडा 08 · मागे: lesson-07-consistency-models · पुढे: lesson-09-raft
📦 या ब्रँचमध्ये काय आहे
धडे 01–07, आणि network partition भाग पाडते ती निवड: consistent राहा
(उत्तर देण्यास नकार द्या) किंवा available राहा (उत्तर द्या, कदाचित जुन्या data सह) — हा CAP
theorem — आणि PACELC, जो सामान्य दिवसांतली निवड जोडतो: latency की
consistency. शिवाय: फुटीच्या दोन्ही बाजूंनी केलेले दोन बदल कसे मिटवायचे.
dist/demo.py मधील cap() आणि dist/sim.py मधील
partition_choice() + resolve().
🧒 5 वर्षांच्या मुलाला समजावल्यासारखे
वादळामुळे रस्ता तुटतो. ⛈️ पुणे आणि नाशिक एकमेकांशी बोलू शकतात. नागपूर आणि कोल्हापूर एकमेकांशी बोलू शकतात. पण हे दोन गट एकमेकांपर्यंत अजिबात पोहोचू शकत नाहीत.
पुण्याने नुकताच परीक्षेचा दिवस बदलला आहे (version 2). नागपूरकडे अजून version 1 आहे.
नागपूरमधील एक पालक विचारतात: "परीक्षेचा दिवस कोणता?" नागपूरकडे दोन पर्याय आहेत:
- 🔒 नकार द्या: "माफ करा, मी पुण्याशी तपासू शकत नाही, म्हणून मी उत्तर देणार नाही." पालक नाराज होतात, पण त्यांना चुकीचा दिवस कधीच सांगितला जात नाही. (CP — consistent)
- 📣 उत्तर द्या: "सोमवार" — जुना दिवस, नागपूरकडे असलेला एकमेव. पालकांना उत्तर मिळते, पण कदाचित चुकीचे. (AP — available)
रस्ता तुटलेला असेपर्यंत तिसरा पर्याय नाही. Version 2 अस्तित्वात आहे हे नागपूरला कळूच शकत नाही.
त्याहून वाईट: वादळाच्या काळात दोन्ही बाजू वर्ग 3A च्या सहलीतील एक बदल स्वीकारतात. पुण्याची बाजू शुक्रवार म्हणते. नागपूरची बाजू शनिवार म्हणते. रस्ता पुन्हा उघडल्यावर कोण जिंकणार? मोठा क्रमांक ठेवायचा आणि दुसरा फेकून द्यायचा? की दोन्ही ठेवून एखाद्या व्यक्तीला विचारायचे?
🗺️ आकृती
flowchart LR
subgraph left["Pune + Nashik"]
p["🏫 Pune<br/>latest: v2"]
n["🏫 Nashik"]
end
subgraph right["Nagpur + Kolhapur"]
g["🏫 Nagpur<br/>holds v1"]
k["🏫 Kolhapur"]
end
p -.-x|"✂️ road cut"| g
g --> cp["CP: refused<br/>no answer rather than a wrong one"]
g --> ap["AP: answered v1 (stale!)"]
🗺️ रेखाटलेली आवृत्ती + एक lab: https://school-edh.pages.dev/distributed-systems/lesson-diagrams.html#l08
❓ काय
- CAP theorem (Eric Brewer यांचे 2000 मधील अनुमान; Seth Gilbert आणि Nancy
Lynch यांनी 2002 मध्ये सिद्ध केले) — प्रती असलेली system या तिन्ही गोष्टींची एकाच वेळी हमी देऊ शकत नाही:
- C, Consistency — इथे याचा अर्थ linearizability (धडा 07), ACID मधला "C" नव्हे
- A, Availability — बंद न पडलेल्या node ला आलेल्या प्रत्येक request ला (error नसलेले) उत्तर मिळते
- P, Partition tolerance — network ने nodes मधले messages टाकून दिले तरी system काम करत राहते
- खरा अर्थ — partitions होणारच (धडा 01), म्हणून P ऐच्छिक नाही. CAP म्हणते: partition च्या काळात, C निवडा (काही requests ना errors मिळतात किंवा थांबावे लागते) किंवा A निवडा (प्रत्येक request ला उत्तर मिळते, कदाचित जुने, आणि दोन्ही बाजूंचे मत वेगळे असू शकते). Partition नसताना तुम्हाला दोन्ही मिळू शकतात. Network वर पसरलेल्या system साठी "CA" हा खरा पर्यायच नाही.
- CP systems — अल्पसंख्य बाजूला नकार देतात: etcd, ZooKeeper, consensus-आधारित databases (धडा 09). Locks, leader election, bookings, balances साठी योग्य.
- AP systems — दोन्ही बाजूंना उत्तर देतात आणि नंतर मेळ घालतात: Cassandra आणि DynamoDB त्यांच्या default modes मध्ये, DNS, caches. Carts, likes, presence, feeds साठी योग्य.
- PACELC (Daniel Abadi, 2010) — Partition असेल तर A किंवा C निवडा; Else (सामान्य कामकाज) Latency किंवा Consistency निवडा. Partition नसतानाही consistent read किंवा write ला इतर प्रतींसाठी थांबावे लागते; वेगवान read/write थांबत नाही. या रोजच्या किंमतीबद्दल CAP काहीच सांगत नाही; PACELC सांगतो.
- फुटीनंतर मेळ घालणे — दोन्ही बाजूंनी writes स्वीकारले असतील (AP), तर रस्ता
पुन्हा जुळल्यावर:
- last-writer-wins (LWW) — मोठा time stamp किंवा version असलेला write ठेवा; दुसरा गुपचूप टाकून दिला जातो
- merge — दोन्ही ठेवा (siblings), CRDT ने merge करा, किंवा एखाद्या व्यक्तीला ठरवू द्या (धडा 03)
🤔 का
कारण प्रती असलेल्या प्रत्येक system समोर तुटलेला रस्ता येणारच, आणि ही निवड एकतर जाणूनबुजून (design मध्ये) केली जाते किंवा अपघाताने (code च्या defaults मध्ये, जी outage च्या वेळी उघडकीस येते). "आमचा database highly available आणि strongly consistent आहे" हे network फुटेपर्यंतच खरे असते. ही निवड माहीत असली की तुम्ही data च्या प्रत्येक तुकड्यासाठी वेगळी निवडू शकता: seat booking साठी CP, like counter साठी AP.
🔧 कसे (या repo मध्ये)
dist/sim.py मधील partition_choice(mode, local_version, latest_version)
'CP' साठी नकार परत करते, किंवा 'AP' साठी "answered v…" परत करते, आणि local
version मागे असेल तर सोबत (stale!). resolve(a, b, rule) दोन (version, value) writes मिटवते: 'lww'
मोठी version असलेला ठेवतो; बाकी काहीही ('merge') दोन्ही values परत करते, क्रमाने लावून
आणि duplicates शिवाय.
🧪 करून पाहा
python3 dist/demo.py cap
python3 - <<'EOF'
import sys; sys.path.insert(0, "dist"); from sim import partition_choice, resolve
for mode in ("CP", "AP"):
for local in (1, 2):
print(f"{mode} · Nagpur holds v{local}, latest v2 → {partition_choice(mode, local, 2)}")
print("lww, versions 7 vs 6 →", resolve((7, "trip on Friday"), (6, "trip on Saturday"), "lww"))
print("lww, a tie 6 vs 6 →", resolve((6, "trip on Friday"), (6, "trip on Saturday"), "lww"))
print("merge, same text →", resolve((5, "trip on Friday"), (6, "trip on Friday"), "merge"))
EOF
✅ तपासा — तुम्हाला काय दिसायला हवे
cap हे print करते:
── the road between Pune+Nashik and Nagpur+Kolhapur is cut (a partition); Nagpur holds v1, the latest is v2
CP: Nagpur is asked the exam day → refused — cannot reach a majority, so no answer rather than a wrong one
AP: Nagpur is asked the exam day → answered v1 (stale!)
── both sides accepted a change during the split: (5, '3A trip on Friday') and (6, '3A trip on Saturday')
last-writer-wins → '3A trip on Saturday' (the other write is silently dropped) · merge → ['3A trip on Friday', '3A trip on Saturday'] (a person decides)
PACELC: during a Partition choose A or C; Else (normal days) choose Latency or Consistency
तुमचा snippet हे print करतो:
CP · Nagpur holds v1, latest v2 → refused — cannot reach a majority, so no answer rather than a wrong one
CP · Nagpur holds v2, latest v2 → refused — cannot reach a majority, so no answer rather than a wrong one
AP · Nagpur holds v1, latest v2 → answered v1 (stale!)
AP · Nagpur holds v2, latest v2 → answered v2
नंतर:
lww, versions 7 vs 6 → trip on Friday
lww, a tie 6 vs 6 → trip on Friday
merge, same text → ['trip on Friday']
🏁 तुम्ही आत्ताच काय सिद्ध केले
CP node त्याची प्रत योगायोगाने अद्ययावत असली तरीही नकार देतो — दुसऱ्या बाजूशिवाय त्याला हे कळू शकत नाही. AP node नेहमी उत्तर देतो, आणि तो बरोबर असतो तो फक्त नशिबाने. Tie झाल्यास last-writer-wins तरीही एक निवडतो (इथे, फक्त पहिला argument) आणि दुसरा टाकून देतो, कोणत्याही error शिवाय. Merge दोन्ही ठेवतो — आणि दोन सारखे writes एक होतात.
⚠️ नेहमीच्या चुका
- system ला "CA" म्हणणे — network वरील कोणत्याही system ला partitions हाताळावेच लागतात
- data च्या प्रत्येक तुकड्यासाठी निवड करण्याऐवजी संपूर्ण product साठी एकच अक्षर निवडणे
- CAP मधला C म्हणजे ACID मधला C असे समजणे (त्या वेगळ्या कल्पना आहेत)
- वेगवेगळ्या machines वरील wall-clock time stamps सह last-writer-wins वापरणे (धडा 02)
- PACELC विसरणे: बहुतेक वेळा partition नसतो, आणि खरी किंमत latency असते
🏭 प्रत्यक्ष वापरात
नेहमीच्या systems कुठे बसतात (defaults; अनेक बदलता येतात):
| System | Partition च्या काळात (PAC) | सामान्य दिवशी (ELC) |
|---|---|---|
| etcd, ZooKeeper | C — अल्पसंख्य बाजू writes नाकारते | C — writes बहुमतासाठी थांबतात |
| Cassandra, DynamoDB (default reads) | A — दोन्ही बाजू उत्तर देतात | L — वेगवान reads, कदाचित जुने |
QUORUM सह Cassandra |
ज्या keys च्या replicas बहुमतापासून तुटल्या आहेत त्यांच्यासाठी C | latency ची किंमत देऊन C |
On a real account — etcd मध्ये CP वर्तन पाहा: 3 members असताना 2 बंद करा, मग उरलेल्या एकावर write करून पाहा:
etcdctl --endpoints=http://nagpur:2379 put exam-day Tuesday
# Error: context deadline exceeded (no leader: the minority cannot commit)
DynamoDB global tables (अनेक AWS Regions मध्ये replicate केलेली एक table) — default नुसार प्रत्येक Region writes स्वीकारतो आणि asynchronously replicate करतो; एकाच item वरील एकाच वेळचे updates last writer wins ने मिटवले जातात. ही AP / EL निवड आहे. नवा multi-Region strong consistency mode दुसरी निवड करतो: writes दुसऱ्या Region साठी थांबतात.
🏭 प्रत्यक्ष वापरात हे का महत्त्वाचे: प्रत्येक data item साठी दोन रिकाम्या जागा भरा: "partition च्या काळात आम्ही ___ (नकार देतो / जुने उत्तर देतो)" आणि "सामान्य दिवशी आम्ही ___ (प्रतींसाठी थांबतो / लगेच उत्तर देतो)". मग store च्या settings त्याच्याशी जुळतात का ते तपासा.
⏭️ पुढे
भाग 2 पूर्ण झाला. CP systems ना शाखांनी एका leader वर आणि बदलांच्या एका क्रमावर एकमत करायला हवे, काही बंद असल्या तरीही. भाग 3 याची सुरुवात करतो: consensus आणि Raft.
git checkout lesson-09-raft