در دنیای معماری نرمافزار مدرن، قابلیت اطمینان اهمیت حیاتی دارد. با حرکت از برنامههای تکنودی به سمت سیستمهای توزیعشده، مسئله اطمینان از توافق همه گرهها بر روی وضعیت دادهها به موضوعی حیاتی تبدیل میشود. اینجا الگوریتمهای اجماع وارد عمل میشوند. آنها پایه و اساس پایگاههای داده توزیعشده، صفهای پیام و قفلهای توزیعشده هستند. امروز، ما دو مورد از تأثیرگذارترین الگوریتمها در این حوزه را بررسی خواهیم کرد: Paxos و Raft.
مشکل اجماع
یک خوشه از سه سرور را تصور کنید که همان دادهها را ذخیره میکنند. اگر سرور A از کار بیفتد، سرورهای باقیمانده باید تصمیم بگیرند که کدام قطعه از داده صحیح است. سناریوهای پیچیدهتری زمانی پیش میآیند که شبکه پارتیشنبندی شود، پیامها با تأخیر ارسال شوند یا چندین گره همزمان بهروزرسانیهای متفاوتی را پیشنهاد دهند. یک الگوریتم اجماع به گروهی از گرهها اجازه میدهد بر روی یک مقدار واحد توافق کنند، حتی اگر برخی از گرهها شکست بخورند یا رفتار مخرب داشته باشند.
چالش اصلی، دستیابی به سازگاری، دسترسیپذیری و تحمل پارتیشن (قضیه CAP) در یک محیط ناهمگام است که در آن شکستها اجتنابناپذیر هستند.
Paxos: پایه نظری
Paxos که در سال ۱۹۸۹ توسط لسلی لامپورت ابداع شد، به احتمال زیاد مشهورترین الگوریتم اجماع است. این الگوریتم برای بقا در برابر پارتیشنهای شبکه و شکست گرهها طراحی شده است. اگرچه از نظر نظری زیباست، اما به دلیل پیچیدگی و فازهای غیرشهودی آن (پیشنهاد، پذیرش، یادگیری)، پیادهسازی و اشکالزدایی آن به شدت دشوار است.
Paxos با انتخاب یک رهبر عمل میکند. رهبر تنها گرهای است که اجازه دارد تغییرات را بر روی وضعیت پیشنهاد دهد. سایر گرهها (پیروان) این پیشنهادها را میپذیرند، مشروط بر اینکه پیش از این پیشنهاد با شماره بالاتری را نپذیرفته باشند. پروتکل تضمین میکند که پس از انتخاب یک مقدار، نمیتوان آن را لغو کرد.
اگرچه ما به ندرت کد خام Paxos مینویسیم، اما درک منطق دو مرحلهای آن برای درک نحوه عملکرد تراکنشهای توزیعشده حیاتی است. در اینجا یک نمایش مفهومی سادهشده از جریان پیشنهاد آورده شده است:
function propose(node, proposal_id, value):
if node.role == LEADER:
prepare(proposal_id) // Phase 1: Ask followers for promises
// Phase 2: If majority promised, accept the value
accept(proposal_id, value)
else:
handle_proposal(proposal_id, value)
Raft: اجماع به شکلی قابل فهم
Raft به طور خاص برای رفع مشکلات پیادهسازی Paxos طراحی شده است. این الگوریتم توسط دیگو اونگارو و جان اوسترهوت در دانشگاه استنفورد توسعه یافته و اجماع را به سه زیرمسئله تجزیه میکند: انتخاب رهبر، تکرار لاگ و ایمنی.
Raft به دلیل تکیه بر مدیریت صریح رهبر، بسیار قابل درکتر است. در Raft، گرهها میتوانند در یکی از سه حالت باشند: رهبر، پیرو یا نامزد. سیستم تضمین میکند که در هر زمان فقط یک رهبر وجود دارد.
هنگامی که رهبر شکست میخورد، انتخابات آغاز میشود. پیروان تایمرها را شروع میکنند؛ اولین گرهای که زمان آن تمام شود، به نامزد تبدیل شده و درخواست رأی میدهد. اگر یک نامزد اکثریت آرا را دریافت کند، به رهبر جدید تبدیل شده و شروع به افزودن ورودیها به لاگ خود میکند که سپس آنها را به پیروان تکرار میکند.
بینشهای پیادهسازی عملی
برای توسعهدهندگان، احتمالاً شما Raft را از صفر پیادهسازی نخواهید کرد، مگر اینکه در حال ساخت یک پایگاه داده توزیعشده هسته باشید. در عوض، شما از کتابخانههایی مانند etcd، consul یا ZooKeeper استفاده خواهید کرد که این پروتکلها را در لایههای زیرین پیادهسازی میکنند. با این حال، درک جریان کار به رفع اشکال مشکلاتی مانند سناریوهای «تقسیم مغز» (split-brain) یا افزایش تأخیر در طول انتخابات رهبر کمک میکند.
این کد شبه (pseudo-code) را برای بررسی ضربان قلب به سبک Raft در نظر بگیرید که از انتخابات غیرضروری جلوگیری میکند:
function checkHeartbeat(node):
last_heartbeat_time = get_last_message_time(node)
current_time = now()
if (current_time - last_heartbeat_time) > ELECTION_TIMEOUT:
transition_to_candidate(node)
start_election(node)
else:
stay_as_follower(node)
نتیجهگیری
انتخاب بین Paxos و Raft اغلب به تخصص تیم شما و الزامات خاص سیستم شما بستگی دارد. Paxos همچنان استاندارد طلایی برای درستی نظری است و در سیستمهایی مانند Chubby و Bigtable استفاده میشود. با این حال، Raft به دلیل وضوح و سهولت پیادهسازی، در اکوسیستمهای ابری مدرن (مانند etcd و TiDB) محبوبیت زیادی کسب کرده است.
همانطور که سیستمهای توزیعشده به تکامل خود ادامه میدهند، تسلط بر این مکانیسمهای اجماع نه تنها یک تمرین آکادمیک است، بلکه یک ضرورت عملی برای ساخت نرمافزارهای مقاوم، مقیاسپذیر و تحملکننده خطا میباشد. با درک نحوه توافق گرهها، شما خود را قادر میسازید تا سیستمهایی را طراحی کنید که حتی زمانی که شبکه دچار مشکل میشود، نیز مستحکم باقی بمانند.