پردازش سفارش تحمل گسل با PAXOS در یک فروشگاه تجارت الکترونیکی توزیع شده

در یک سیستم تجارت الکترونیکی توزیع شده ، اطمینان از پردازش هر سفارش دقیقاً یک بار– حتی وقتی سرورها خراب می شوند یا پیام ها از بین می روند – بسیار مهم است. در این پست ، من شما را از طریق نحوه الگوریتم اجماع Paxos برای هماهنگی ایجاد سفارش در چندین سرور و تضمین تحمل گسل در پس زمینه من بهار استفاده می شود.
چرا paxos؟
- قوام تحت شکست: حتی اگر برخی از گره ها خراب شوند یا شبکه غیرقابل اعتماد باشد ، Paxos تضمین می کند که یک مقدار واحد و توافق شده (در اینجا ، عمل “ایجاد سفارش”) دقیقاً یک بار انتخاب شود.
- هیچ نقطه ای از شکست: هر گره می تواند یک سفارش را پیشنهاد کند ، و الگوریتم تا زمانی که اکثر گره ها به پایان برسند ، همچنان به اجماع می رسد.
- بدون همزمان و بدون رهبر: هیچ رهبر ثابت وجود ندارد. هر گره می تواند روند اجماع را آغاز کند.
جریان سطح بالا
-
پیشنهاد: مشتری درخواست سفارش را ارسال می کند (پیچیده شده
Proposal
) به مجموعه ای از سرورهای Paxos. -
وعده: هر سرور با a پاسخ می دهد
Promise
اگر قول داده ای با شماره بالاتر را نداشته باشد. -
قبول کردن: هنگامی که پیشنهاد دهنده اکثر وعده ها را جمع می کند ، آن را ارسال می کند
accept
درخواست - یاد گرفتن: پس از پذیرش اکثر سرورها ، آنها عملیات انتخاب شده را “یاد می گیرند” و آن را اجرا می کنند (سفارش را ایجاد کنید).
رابط کلیدی
همه سرورهای Paxos یک رابط کاربری ساده را پیاده سازی می کنند (از com.arm.coordinator.common.PaxosServer
):
public interface PaxosServer<T> {
Promise promise(Proposal proposal);
Boolean accept(Proposal proposal);
Result learn(Proposal proposal, Integer userId);
}
مرحله وعده
در promise(...)
روش تضمین می کند که هیچ سرور پیشنهادهای قدیمی تر از آنچه قبلاً قول داده است را نمی پذیرد. در شما PaxosOrderService
:
@Override
public synchronized Promise promise(Proposal proposal) {
serverLogger.info("Receive a promise message");
if (proposal.getId() <= this.maxId) {
return new Promise(Status.REJECTED, null);
}
this.maxId = proposal.getId();
if (this.accepted != null) {
// If we’ve already accepted something, let the proposer know
return new Promise(Status.ACCEPTED,
new Proposal(accepted.getId(), accepted.getOperation()));
} else {
// Otherwise, promise not to accept lower proposals
return new Promise(Status.PROMISED, proposal);
}
}
.
در اینجا maxId
بالاترین پیشنهاد پیشنهادی را که تاکنون دیده می شود ، ردیابی می کند. اگر پیشنهاد ورودی جدیدتر باشد ، ما آن را ضبط می کنیم و یا پیشنهاد از قبل پذیرفته شده را گزارش می دهیم یا قول می دهیم بعداً آن را بپذیریم.
مرحله پذیرش
هنگامی که یک پیشنهاد دهنده اکثریت دارد PROMISED
پاسخ ها ، آن را صادر می کند accept
درخواست:
@Override
public synchronized Boolean accept(Proposal proposal) {
serverLogger.info("Received an accept message");
if (proposal.getId() != this.maxId) {
// Only accept if this is the latest promised proposal
return false;
}
// Record that we’ve accepted this proposal
accepted = new Proposal(proposal.getId(), proposal.getOperation());
serverLogger.info("Proposal successfully accepted");
return true;
}
.
با بررسی proposal.getId() == maxId
، ما از قوام اطمینان می دهیم: سرورها فقط پیشنهادی را که اخیراً وعده داده اند ، می پذیرند.
مرحله یادگیری
پس از پذیرش اکثر سرورها ، این عملیات “آموخته شده” و دقیقاً یک بار اجرا می شود:
@Override
public synchronized Result learn(Proposal proposal, Integer userId) {
serverLogger.info("Received a learn message");
OrderForm form = proposal.getOperation().getOrderForm();
// Validate products, create Order and OrderProducts atomically
Order order = orderService.create(new Order(...));
// ... attach products, set status, etc.
Result result = new Result(true, ResultCodeEnum.ALL_OKAY, "Order created successful");
return result;
}
.
این مرحله آخر فقط یک بار سفارش به پایگاه داده می نویسد ، حتی اگر برخی از سرورها پس از پذیرش خراب شوند.
چرا این تحمل گسل را حل می کند
- تعداد معیارهای: تا زمانی که اکثر سرورها پاسخ دهند ، این پیشنهاد به جلو پیش می رود. گره های تصادف شده یا آهسته می توانند بعداً به دست بیاورند.
- معناشناسی دقیقاً یکسان: با جدا کردن وعده ، پذیرش و یادگیری مراحل ، حتی اگر پیام ها دوباره انجام شود ، از ایجاد دو برابر جلوگیری می کنید.
- بهبودی: سرورهای جدید یا بازیابی می توانند آخرین پیشنهاد پذیرفته شده را بیاموزند و آن را برای رسیدن به همان حالت اعمال کنند.
مراحل بعدی و پسوند
-
حالت مداوم: فروشگاه
maxId
وتaccepted
در ذخیره سازی بادوام ، بنابراین سرورها می توانند پس از یک راه اندازی مجدد کامل بهبود یابند. - انتخابات رهبر: برای کاهش تأخیر در سفر ، یک پیشنهاد برجسته بسازید.
- دسته بندی: عملیات چندگانه گروه در هر اجماع برای توان بالاتر.
با بافتن paxos به سرویس سفارش خود ، شما یک برنامه بوت بهار وانیلی را به یک سیستم توزیع شده با گسل سنگی و دارای گسل تبدیل می کنید. احساس راحتی کنید که کد کامل را کشف کرده و آن را در اینجا چنگال کنید:
👉 github.com/anizmo/distributed-ecommerce-store
برنامه نویسی مبارک! ✨