CAP ও PACELC — theorem যেটা সবাই ভুল বোঝে
CAP Theorem and PACELC
Partition হলে Consistency না Availability — বাধ্যত-বাছাই; partition না থাকলে Latency না Consistency — PACELC-ই CAP-এর আসল operational অনুবাদ।
আগে এটা বুঝি
প্রতিটা architecture-meeting-এ একবার হলেও ওঠে: “আমরা তিনটার দুইটা বাছব — CAP তো বলেই।” আর ঠিক সেই বাক্যটাই প্রায়ই ভুল। কারণ CAP theorem যেটা বলে, তার সাথে popular সংস্করণের মিল শব্দের স্তরে, অর্থের স্তরে নয়।
আসল theorem (Brewer-এর conjecture 2000, Gilbert–Lynch-এর proof 2002) তিনটা খুব নির্দিষ্ট claim-এর উপর দাঁড়িয়ে:
- Consistency — clients যা দেখে তা single-copy-র মতো: completed write-এর ঠিক পরেই সব read নতুন মান দেখে
- Availability — যেকোনো চলমান node-এর কাছে যাওয়া প্রতিটা request উত্তর পায় (error ছাড়া)
- Partition tolerance — network ভেঙে গেলেও সিস্টেম চলে
আর proof-এর মর্ম: P-কে ছাড়তে পারবেন না — কারণ network ভাঙা physics-এর সত্য, feature নয়। তাই আসল সিদ্ধান্ত ঘটে ঠিক একটা মুহূর্তে: partition চলাকালীন C না A। বাকি সময়? সেখানে theorem নীরব — আর সেই নীরবতায়ই ঢুকে পড়ে আসল প্রতিদিনের trade-off: latency। এই সম্পূরক ফ্রেমের নাম PACELC।
মূল ধারণা
তিন অক্ষরের আনুষ্ঠানিক মানে
| অক্ষর | Formal মানে | যা নয় |
|---|---|---|
| C | Linearizability — single-object: write-complete-এর পরের প্রতিটা read নতুন মান দেখে | transaction-level serializability নয়, multi-object guarantee নয় |
| A | জীবিত node-এর প্রতিটা non-failing request যুক্তিসঙ্গত সময়ে উত্তর পায় | “কোনো downtime হবে না”-ধরনের marketing-A নয় |
| P | Network partition (node-গুলো alive, কিন্তু পরস্পর-অদৃশ্য) সহ্য করা | “network ভাঙবে না” — এমন আশা নয় |
C-র সংজ্ঞায় single-object শব্দটা খেয়াল করুন — CAP-এর C অনেক সস্তা জিনিস যা মানুষ ভাবে। Bank-account-এর একটা key-র recency guarantee; পুরো database-এর transactional সততা নয়।
Partition-মুহূর্ত — বাইনারি মুহূর্ত
Proof-এর core argument একটা ছোট দৃশ্য:
- Replica A আর B আছে; মাঝের network ভাঙল
- Client W, A-কে
x=1লিখতে বলল — A জীবিত, উত্তর দিতে পারে - Client R, B-কে
xপড়তে বলল — B-ও জীবিত, কিন্তু নতুন মানটা তার কাছে আসেনি
এখন B-র সামনে দুইটা মাত্র পথ:
- Serve করো পুরনো
x=0→ R উত্তর পেল (A ✓), কিন্তু linearizability ভাঙল (C ✗) - Reject করো → C রক্ষা (unavailable node-ই মিথ্যা বলতে পারে না — এটা CP-দর্শন), কিন্তু R-এর request-এর উত্তরই নেই (A ✗)
তৃতীয় কোনো পথ proof-এ নেই — এটাই “choose C or A during partition”। আর partition শেষ হলে? সিদ্ধান্ত-মুহূর্তও শেষ — reconciliation-এর নতুন অধ্যায় শুরু (conflict merge — AP- জগতের দৈনিক কাজ)।
PACELC — Else-এর জগৎ
Abadi-র সম্পূরক ফ্রেম: partition-এর বাইরের সময়টুকুও তো আছে —
if Partition -> A (serve stale) অথবা C (block)
else (স্বাভাবিক) -> L (দ্রুত, async) অথবা C (sync-replicate)Else Latency vs Consistency: স্বাভাবিক অবস্থায় প্রতিটা write-
ack অপেক্ষা করবে replica-র fsync/apply-র জন্য (C, কিন্তু ধীর),
না সঙ্গে সঙ্গে ফেরবে (L, কিন্তু replica পিছিয়ে)? Replication
লেসনের synchronous_commit ladder আসলে এই axis-ই ছিল।
CP-দের কর-ফর্ম: sync-replication মানে প্রতিটা write-এ network round-trip — দূরের replica হলে tens-of-ms। AP-দের লাভ: async ack, sub-ms — দাম partition-time stale-read আর heal-পরব convergence-ঝামেলা।
ভেতরে কী ঘটছে
Eventual consistency — সংজ্ঞা আর শর্ত
AP-জগতের promise-টা সাবধানে পড়ুন: eventual মানে —
- নতুন write না-হওয়া পর্যন্ত অপেক্ষা করলে (quiescence), সব replica একই final value-তে পৌঁছাবে (convergence)
- সেই পৌঁছানোর সময়সীমা সংজ্ঞায়িত নয় — milliseconds থেকে minutes
Convergence automatic নয় — এর জন্য লাগে conflict-resolution rule: last-write-wins (clock-এর উপর বিশ্বাস!), version-vector, CRDT-গণিত। Partition-চলাকালীন দুই পাশে একই key-তে দুই ভিন্ন write গেলে, heal-এর পরে একটা হেরে যাবে — LWW হলে clock-skew মানেই নতুন write পুরনোর কাছে হার মানতে পারে। “Eventually consistent” শব্দযুগল কোনো সমস্যা-মুক্তি-চিঠি নয়; এটা একটা contract যার ছোট-ছোট হরফে লেখা শর্ত আছে।
Consistency-র সিঁড়ি — Level 9-এর preview
শক্তিশালী ◄──────────────────────────────────────► দুর্বল
linearizable > sequential > causal > eventual
linearizable: single-object real-time recency (CAP-এর C)
sequential: প্রতিটা process নিজের ক্রম দেখে, cross-process
real-time ordering নেই
causal: cause-effect সম্পর্কিত operation-দের ক্রম সবাই
এক দেখে; unrelated-দের ব্যাপারে মতভেদ ok
eventual: quiescence-এ মিল — পথে কোনো ক্রমের নিশ্চয়তা নেইপ্রতিটা ধাপ-নাম্বার নামানো মানে replication-এর উপর কম তালা — আরও latency-লাভ, আরও reasoning-ভার application-code-এর কাঁধে। এই সিঁড়ির পূর্ণ গাণিতিক বিবরণ distributed-systems module-এর মূল খাদ্য — এখানে map-টুকু মুখস্থ করুন।
PostgreSQL-এর আসল position
“PostgreSQL CP না AP?” — প্রশ্নটাই খারাপভাবে গঠিত। Single-primary PG: সব write এক node-এ → ওই node-এর reads linearizable; primary মরলে fencing-ছাড়া promote করা হয় না (replication লেসনের rule!) — অর্থাৎ availability ত্যাগ করে C ধরে রাখা হয়: failover-boundary- তে CP-আচরণ। কিন্তু standby-তে hot-standby read = async snapshot — eventual! একই সিস্টেমে দুই মোড, endpoint-ভেদে। CAP label মানুষের জন্য, মেশিনের জন্য নয় — আর বাস্তব সিস্টেম label ছাড়াই প্রতিটা operation-এ সিদ্ধান্ত নেয়।
উদাহরণ
একটা partition, তিনটা design, তিনটা ভিন্ন দিন
দৃশ্য: দুই datacenter (A: Dublin, B: Mumbai), inter-link ভাঙল
৪৫ মিনিটের জন্য। Application: shopping-cart (key=user)।
Design ১ — CP (etcd-style consensus, sync commit):
Mumbai-র users: cart-write প্রতিটা timeout/error
-> availability শূন্য, কিন্তু কোনো user-এর cart কখনো
পুরনো দেখায়নি; link ফিরল সব স্বাভাবিক
RPO/RTO মানসিকতা: data-loss অসম্ভব, revenue-loss ৪৫ মিনিটDesign ২ — AP (Dynamo-style, LWW):
Mumbai চলছে পূর্ণ speed — cart read/write সব local
Dublin-এ একই user একসাথে edit করল (traveler scenario)
-> দুই শাখায় ভিন্ন cart-content; heal-এ LWW merge —
Dublin-এর শেষ write জিতল, Mumbai-এর item-drop হারাল
(user-এর চোখে: ঝুড়ি থেকে জিনিস নিখোঁশ!)
Availability ১০০%, correctness-এর বিল ব্যবহারকারীই দিলDesign ৩ — hybrid (PG primary + async standby, app-aware):
Writes: Mumbai traffic Mumbai-local cache-এ, queue-এ async
replay Dublin-এ (eventual, window ≈ seconds)
Reads: cart-view Mumbai-cache থেকে (stale-ok UI);
checkout-moment-এ force-sync validation primary-তে
Partition-এ: browsing চলল, checkout ব্লকড (queue + retry)
-> ক্ষতি সীমাবদ্ধ, সুদৃঢ় point শুধু টাকা-তোলার মুহূর্তেকোনটা সঠিক? প্রশ্নটা ভুল। সঠিক প্রশ্ন: কোন operation-এ কোন guarantee লাগে — আর Design ৩-ই সেই প্রশ্নের আধুনিক উত্তর। Per-operation consistency-choice-ই আজকের production-দর্শন।
ছবিতে
সিদ্ধান্ত-মানচিত্র
request এলো
│
┌─── network partition? ───┐
│ YES │ NO
▼ ▼
┌─── বাছাই ───┐ ┌─── বাছাই ───┐
│ │ │ │
▼ ▼ ▼ ▼
SERVE REJECT ASYNC ack SYNC ack
(stale) (block) = Latency = Consistency
│ │ সস্তা,replica প্রতি write-এ
▼ ▼ পিছিয়ে থাকতে replica-apply
A রক্ষা C রক্ষা পারে round-trip
C হানি A হানি │ │
▼ ▼
AP-systems CP-systems
(Dynamo, (ZooKeeper,
Cassandra) etcd, Spanner*)
(*TrueTime-nuance)
heal-এর পরে AP-দের বাড়তি কাজ: convergence — conflict-resolution
(LWW/version-vector/CRDT) ছাড়া দুই শাখা মেলে নাguarantee ▲
strong │ linearizable <- CAP-এর C; single-object recency
│ │ (bank balance, lock, config-flag)
│ sequential <- per-process order ঠিক; total
│ │ real-time order নেই
│ causal <- কারণ-প্রভাব chain সবাই এক দেখে
│ │ (reply-before-post অসম্ভব হবে)
weak │ eventual <- শুধু quiescent-convergence
│ (like-count, view-count)
└────────────────────────────────► latency-costনিজে চালিয়ে দেখুন
নিজের laptop-এ partition বানান — stale বনাম block চোখে
ছোট script — cap_probe.py; দুই replica, এক shared-wire,
দুই mode:
import time
PARTITION = False # এই switch-টাই network-cable
SYNC = False # False=AP-ish async, True=CP-ish sync
class Node:
def __init__(self, name):
self.name = name
self.kv = {}
a, b = Node("A"), Node("B")
wire = [] # (deliver_after_tick, key, val)
tick = 0
def pump(tick):
global wire
due = [w for w in wire if w[0] <= tick]
wire = [w for w in wire if w[0] > tick]
for _, k, v in due:
b.kv[k] = v # standby-তে apply
# --- write path ---
t0 = time.perf_counter()
a.kv["balance"] = 500 # local accept
if not PARTITION:
wire.append((tick + 2, "balance", 500)) # propagation delay
elif SYNC:
print(f"[tick {tick}] WRITE BLOCKED — replica unreachable, "
f"C-রক্ষা: ack অস্বীকার")
else:
print(f"[tick {tick}] WRITE ACKED locally — replica "
f"এখনো অন্ধ (AP)")
for tick in range(1, 6):
pump(tick)
if "balance" in b.kv:
break
print(f"[tick {tick}] B-এর চোখে balance = "
f"{b.kv.get('balance', '(আগের মান!)')}")
stale_ticks = tick # B কত-tick অন্ধ ছিল
print(f"\nobserved: stale-window={stale_ticks} ticks, "
f"wall-clock={(time.perf_counter()-t0)*1000:.1f}ms")খেলা ১ — AP-mode (default): চালান — write সঙ্গে-সঙ্গে acked, B কয়েক tick পুরনো মান দেখে, তারপর converge।
খেলা ২ — CP-mode: SYNC = True, PARTITION = True করুন —
write blocked; B কখনো নতুন মান পায় না; কিন্তু ভুল মানও কেউ
দেখেনি।
খেলা ৩ — heal: PARTITION = True রেখে ২০ iteration চালান,
তারপর False — held writes propagate, convergence burst দেখুন
(build-section-এর LogShipper-এর আত্মীয়!)।
প্রতিটা খেলার পরে নিজেকে জিজ্ঞেস করুন: এই মুহূর্তে এক bank, এক like-counter, এক shopping-cart — কোনটার জন্য কোন মোড গ্রহণযোগ্য?
Partition-মুহূর্তের দ্বন্দ্বটা theory নয় — দুই in-process replica-এর মাঝের wire বন্ধ করলেই CP-mode write আটকায়, AP-mode read পুরনো মান দেয়; আর sync/async-এর latency-gap সংখ্যায় বসে।
নিজে বানান
MiniCAPLab — PACELC-দাবির quantitative matrix
- Two-node store — configurable W (কত replica-apply লেগে ack)
- Partition switch — propagation বন্ধ
- Client-probe — availability, staleness, latency গুনুন
- ৪টা মোডে (sync/async × partition on/off) workload চালান
- Matrix ছাপুন — CAP/PACELC দাবিগুলো সংখ্যায় মিলুন
লক্ষ্য: “CP partition-এ unavailable”, “AP stale দেয়”, “sync ধীর” — তিনটা textbook-বাক্যই এক matrix-row-এ সংখ্যা হয়ে ফুটবে।
import statistics
class Lab:
"""Two-node KV; W=1 local-ack-only, W=2 replica-apply-পরে-ack"""
def __init__(self, sync_w2=False, net_delay=2):
self.w2 = sync_w2
self.delay = net_delay
self.down = False
self.inflight = [] # (arrive_tick, seq) — wire
self.retained = [] # partition-চলাকালীন জমা WAL
self.seq = 0 # primary-র write-counter
self.acked = 0 # client-confirm'd সর্বশেষ seq
self.applied = 0 # B-তে apply'd সর্বশেষ seq
self.m = {"ok": 0, "blocked": 0}
self.lat = []
self.max_stale = 0
self.probes = 0
def write(self, tick):
if self.down:
if self.w2: # CP: replica-ছাড়া confirm নয়
self.m["blocked"] += 1
self.lat.append(20) # timeout-abort cost
return
self.seq += 1 # AP: local-ই যথেষ্ট; log জমা থাকে
self.retained.append((tick + self.delay, self.seq))
self.acked = self.seq # local ack — এটাই A-র দাম
self.m["ok"] += 1
self.lat.append(1)
return
self.seq += 1
self.inflight.append((tick + self.delay, self.seq))
if self.w2: # CP: apply-পর্যন্ত ack ঝুলিয়ে
self.lat.append(1 + self.delay)
else: # AP: সঙ্গে-সঙ্গে ack (Else-L)
self.acked = self.seq
self.lat.append(1)
self.m["ok"] += 1
def advance(self, tick):
if self.down:
return # partition: delivery বন্ধ
due = [w for w in self.inflight if w[0] <= tick]
self.inflight = [w for w in self.inflight if w[0] > tick]
for _, s in sorted(due):
self.applied = s
if self.w2:
self.acked = s # sync-ack এখানেই ফিরে
def probe(self):
"""standby-B-র চোখে staleness — version-gap-এ"""
self.probes += 1
gap = self.acked - min(self.applied, self.acked)
self.max_stale = max(self.max_stale, gap)
def run(sync_w2, partitioned, n_writes=200):
lab = Lab(sync_w2)
heal_at = None
for t in range(1, n_writes + 1):
if partitioned and t == 121:
lab.down = False # cable ফিরল — retained flush
lab.inflight.extend(lab.retained)
lab.retained.clear()
lab.down = lab.down or (partitioned and t <= 120)
lab.write(t)
lab.advance(t)
if t % 5 == 0:
lab.probe()
return lab
print(f"{'mode':<24}{'avail%':>8}{'avg-lat':>9}"
f"{'max-stale':>10}")
for name, s, p in [("AP (W=1) normal", False, False),
("AP (W=1) partition", False, True),
("CP (W=2) normal", True, False),
("CP (W=2) partition", True, True)]:
lab = run(s, p)
total = lab.m["ok"] + lab.m["blocked"]
avail = 100 * lab.m["ok"] / total
avg = statistics.mean(lab.lat)
print(f"{name:<24}{avail:>7.0f}%{avg:>9.1f}"
f"{lab.max_stale:>10.0f}")প্রত্যাশিত output:
mode avail% avg-lat max-stale
AP (W=1) normal 100% 1.0 2
AP (W=1) partition 100% 1.0 ~115
CP (W=2) normal 100% 3.0 0
CP (W=2) partition 0% 20.0 0Matrix পড়ুন — চার row-ই একটা করে theorem:
- AP-partition: available ১০০%, কিন্তু staleness partition- জুড়ে জমে ~১১৫ version — এই gap-টাই async replication-এর RPO-জানালা; heal-এর পরে retained-log burst-apply-তে convergence
- AP-normal: max-stale = net_delay — partition না থাকলেও async-এর ছোট, স্থির lag (PACELC-র Else-L-লাভের উৎস)
- CP-normal: staleness শূন্য, কিন্তু avg-latency ৩× — PACELC-র Else-C-র কর!
- CP-partition: availability শূন্য — “during partition, choose” — এই row-ই CAP-এর হৃদয়বাক্য
নিজে বাড়ান:
- Read-your-writes session-affinity mode — client সবসময় leader থেকে পড়লে stale% কোথায় যায়?
- Quorum-W=1,R=2 বনাম W=2,R=2 — partition-এর কোন পাশ serve করবে হিসাব করুন (Level 9-এর quorum-গণিতের আভাস)
- LWW-conflict inject — partition-চলাকালীন দুই পাশে ভিন্ন key- value, heal-এ কে জেতে দেখুন (clock-ভিত্তিক LWW-র বিপদ)
বাস্তব সিস্টেমে
বাস্তব জগতে CAP-এর ছায়া
Theorem-টার জন্মকথা। Eric Brewer 2000-এ keynote-conjecture দিলেন, Gilbert ও Lynch 2002-এ formal proof দিলেন, আর 2012-তে Brewer নিজেই IEEE Computer-এ লিখলেন theorem-টা কীভাবে সবাই ভুল quote করছে — creator-এর নিজের correction পড়া বিরল সৌভাগ্য।
CP-shrine। ZooKeeper, etcd, Consul — consensus-core (Raft/ ZAB); configuration, locking, service-discovery — যেখানে ভুল মানে বিপদ, সেখানেই এদের ঠিকানা। Partition-এ minority-side unavailable — সচেতনভাবে।
AP-shrine। Cassandra, DynamoDB, Riak — shopping-cart, session, telemetry, feed; write-availability business-critical যেখানে, conflict-rule সাথে কিনে নিয়ে। Dynamo-paper (2007)-এর LWW + vector-clock আলোচনা এখনো পড়ার মতো।
Nuance-শিকারিরা। Google Spanner: technically CP, তবু low- latency — GPS+atomic-clock (TrueTime) দিয়ে sync-এর wait ছোট bound-এ বাঁধে; প্রমাণ করে “CP মানে ধীর” formula ভাঙা যায় hardware দিয়ে। আর CRDT-based systems (Redis Enterprise CRDB, Automerge) AP হয়েও conflict-free convergence গ্যারান্টি দেয় — math দিয়ে।
আপনার প্রতিদিন। DNS (eventual, TTL-cache), Git (offline-commit, later-merge — AP-darshan), airline-reservation (overbooking = availability-র দাম আগে-ই-গোনা) — partition-thinking শুধু server-room- এর নয়।
যে ভুলগুলো সবাই করে
“CA system বানানো যায় — 'three pick two'-তে CA একটা option।”
Distributed context-এ নয়। P-optional-ভাবা-ই ভুল: network partition আপনার সিদ্ধান্তে আসে না। “CA”-label পাওয়া প্রতিটা system আসলে single-node (বা data-plane-network-হীন)। Brewer নিজেই 2012-তে এই reading-কে invalid বলেছেন — partition-tolerance বাছাইযোগ্য feature নয়, environment-এর শর্ত।
“NoSQL মানে AP, SQL মানে CP — database-শ্রেণি-ই consistency ঠিক করে।”
Category-ভিত্তিক mapping বাজার-সাহিত্য, theorem নয়। MongoDB (default config) CP-leaning, tunable; Cassandra per-keyspace consistency-level-এ CP-to-AP dial করা যায়; PostgreSQL single- primary linearizable-per-object, কিন্তু standby-read eventual। আসল unit-of-analysis: operation, শ্রেণি নয় — প্রতিটা read/ write কোন guarantee-তে চলবে সেটা config/session/code-এ ঠিক হয়।
“Eventual consistency মানে শেষমেশ সব ঠিক হয়ে যাবে — চিন্তা নেই।”
Convergence-এর জন্য লাগে (১) quiescence — নতুন write বন্ধ, (২) একটা sound merge-rule। Partition-চলাকালীন conflicting writes-এ LWW নীরবে data ফেলে দিতে পারে — “শেষ” মানে শেষ-লেখা নয়, শেষ- জেতা। Cart-item হারানো, duplicate-charge, resurrected-delete — production-এর ক্লাসিক AP-ঘাত। Eventual মানে contract-এর নাম, amnesty নয়।
“CAP-এর C আর ACID-এর C একই — আর "linearizable = serializable"।”
ACID-এর C = constraint-consistency (invariant ভাঙে না); CAP-এর C = linearizability — ভিন্ন universe। আর linearizable (single-object real-time recency) ≠ serializable (multi-object transaction-equivalence) — একটা object-scoped, অন্যটা transaction-scoped; কোনোটা অন্যটাকে imply করে না। Interview-classic confusion — সংজ্ঞা আলাদা করে মুখস্থ।
বুঝেছেন কি না দেখুন
1CAP-এর C-র formal নাম আর এক-বাক্য সংজ্ঞা; এটা কোন scope-এ কাজ করে?
স্মরণ
Linearizability: কোনো write complete হওয়ার পরে শুরু হওয়া প্রতিটা read সেই নতুন মান (বা তার পরের কোনো মান) দেখবে — single-object, real-time recency। Scope: এক object; transaction- level নয়।
2“P tolerance-টা তো ভালো জিনিস — সবাই বেছে নেবে, তাহলে দ্বন্দ্ব কোথায়?”
— এই প্রশ্নের ভুলটা ধরুন।
যুক্তি
P-কে feature ভাবা-ই ভুল। P মানে “network ভাঙলেও সিস্টেম দাঁড়িয়ে থাকুক” — আর ভাঙা network-কে বাছাইয়ের টেবিলে বসানোর সুযোগ নেই; switch/fiber/shark যখন-তখন ঠিক করে দেবে। তাই P হলো premise, choice নয়; choice ঘটে ভাঙা-মুহূর্তে C-vs-A — এখানেই দ্বন্দ্ব।
3Build-এর matrix-এ CP-normal-এর avg-latency 3, AP-র 1। এই 2-tick
ব্যবধান ঠিক কী খরচের হিসাব? Real-world এই ব্যবধান কখন নগণ্য, কখন
অসহ্য?
প্রয়োগ
ব্যবধান = replica-apply-পর্যন্ত অপেক্ষার net-delay (delay=2) — sync-replication-এর round-trip। নগণ্য: co-located replicas (sub-ms) — write-rate-এর তুলনায় নীরব। অসহ্য: geo-distributed replica (50-150ms প্রতি write) — interactive-path-এ user-চোখে lag, throughput-ceiling। তাই geo-sync systems হয় region-local leader (Spanner-model), নয় async + reconciliation।
4Heal-এর পরে AP-cluster-এ convergence automatic-ভাবে “ঠিক” হয় না
— ঠিক কোন দুই component-এর অনুপস্থিতিতে ভুল merge হতে পারে?
যুক্তি
(১) Sound conflict-rule — LWW clock-skew-এ পুরনো write জিততে পারে; version-vector/CRDT ছাড়া causality-র হিসাবই থাকে না। (২) Quiescence — merge চলাকালীন নতুন conflicting write এলে rule-টা আবার খেলে। Rule-হীন convergence মানে silent data-loss — “eventual” শব্দটা merge-semantics লুকিয়ে রাখে।
5Product-requirement: (a) username-registration — duplicate অসম্ভব
হতে হবে; (b) profile-view-count — ±৫% ভুল ok; (c) password-change —
পুরনো password পরের ৬০ সেকেন্ড কাজ করলে security-incident। তিনটার
জন্য consistency-target আর mechanism propose করুন।
ডিজাইন
(a) Strong/linearizable — unique-index সহ single-authority store (consensus-backed); partition-এ registration-block acceptable। (b) Eventual — async counter, batch-flush, sampling-ও চলে; stale window seconds-scale harmless। (c) Causal-at-minimum, practically read-your-writes + short-TTL-invalidation — পরিবর্তনের পরে সব auth-path 60s-এর মধ্যে new-hash দেখতে বাধ্য (session-token revocation push)। মূল সূত্র: requirement-ভেদে per-operation target — এক system-এ তিন মোডই স্বাভাবিক।
এরপর কী
এরপর কী
CAP/PACELC lens এখন হাতে — এবার সেই lens দিয়ে দেখা যাক যে movement-টা “SQL-বিরোধী বিপ্লব” বলে market হয়েছিল: NoSQL — document, key-value, wide-column, graph চার পরিবার; কে কী দেয়, কোথায় ভাঙে, আর JSONB-যুগের PostgreSQL কীভাবে সীমানাগুলো ঝাপসা করে তুলল। এটাই databases module-এর শেষ লেসন — শেষে পুরো module wrap-up আর Level 9 distributed-systems-এর দরজা।
আরও পড়ুন
- Brewer's Conjecture and the Feasibility of Consistent, Available, Partition-Tolerant Web Services — Seth Gilbert, Nancy Lynch — ACM SIGACT News 33(2), 2002 · CAP-এর formal proof — theorem-টার আসল গাণিতিক উৎস
- CAP Twelve Years Later: How the Rules Have Changed — Eric Brewer — IEEE Computer, 2012 · Theorem-টার স্রষ্টার নিজের hindsight — misinterpretation-গুলোর সরাসরি জবাব
- DBMS Musings — Problems with CAP, and Yahoo's little known NoSQL system (PACELC) — Daniel J. Abadi · PACELC-র মূল formulation — Else-Latency শাখার জন্মদাতা
- Designing Data-Intensive Applications, Chapter 9 — Consistency, Consensus — Martin Kleppmann · Linearizability আর CAP-এর সূক্ষ্ম সম্পর্কের সেরা practitioner আলোচনা