نوشتن چندمنطقهای: تغییر در واقع کجا تثبیت میشود؟
مسیریابی درخواست را به یک منطقه میرساند؛ تنها مرز تراکنش است که نوشتن را اتمی میکند. ناوردا را نام ببرید، مالک را انتخاب کنید و سپس تلاش مجدد را پیرامون آن طراحی کنید.
دو سرور برنامه در دو منطقه، یک کلاینت که از طریق VPN مینویسد، و پرسشی که هیچکس ننوشت: کدام مؤلفه تصمیم میگیرد که نوشتن رخ داده است؟ مسیریابی درخواست را به یک فرایند میرساند. مرز تراکنش تعیین میکند که تغییر کِی پایدار و قابل مشاهده میشود. اینها کارهای متفاوتی هستند که سیستمهای متفاوت انجام میدهند، و شکاف میان آنها همان جایی است که بیشتر باگهای نوشتن چندمنطقهای زندگی میکنند.
از قاعده کسبوکار شروع کنید، نه از نقشه
با جملهای درباره قاعده کسبوکار شروع کنید نه درباره جغرافیا: کدام خواندنها و نوشتنها باید با هم موفق شوند و کدام تغییرات همزمان باید در این میان ناممکن باشند. برای رزرو موجودی این یعنی بررسی موجودی و رزرو یا هر دو اثر میکنند یا هیچکدام، و هیچ سفارش دومی نباید در این فاصله همان واحد را مصرف کند.
| Requirement | What satisfies it | What does not |
|---|---|---|
| All-or-nothing application | A transaction inside one owning system | A VPN path between regions |
| No double spend | Isolation strong enough to exclude the conflict | Atomicity alone |
| Survive a region loss | Replication the database itself documents | Two independent databases behind one client |
دقیقاً همان سطر میانی است که تیمها از آن میگذرند. اتمیک بودن بدون جداسازی کافی به دو تراکنش اجازه میدهد هر یک درست تثبیت شوند و باز هم وضعیتی بسازند که کسبوکار آن را ناممکن میداند، و هیچ مقدار منطق تلاش مجدد آن را بعداً درست نمیکند.
یک مرز معتبر بر دو سرور منطقهای پیروز میشود
سرورهای برنامه منطقهای میتوانند همانجا بمانند، تا زمانی که عملیات را به سرویسی بسپارند که آن را درون یک مرز تراکنش پشتیبانیشده انجام دهد. لایه برنامه به مسیریاب قصد تبدیل میشود؛ لایه داده حقیقت را در اختیار دارد.
آن مرز را کوتاه و نزدیک به دادهای که لمس میکند نگه دارید. تراکنشی که باز نگه داشته میشود تا انسانی به یک پرسش پاسخ دهد، یا تا یک فراخوان دو منطقه را بپیماید، وقتش را صرف نگهداشتن قفلها میکند و احتمال اینکه چیز دیگری پشت آن از مهلت بگذرد را بالا میبرد. آن شکست شبیه مشکل پایگاه داده به نظر میرسد و در واقع مشکلی در طراحی است که چنین لباسی پوشیده. انتقال تصمیم به لایه داده معمولاً آن را کاملاً حذف میکند.
BEGIN;
UPDATE inventory SET reserved = reserved + 1
WHERE sku = 'A-100' AND available >= 1;
INSERT INTO reservation (sku, order_id) VALUES ('A-100', 'ord-9f');
COMMIT;
آن طرح را به عنوان یک مرز بخوانید، نه یک توصیه کارایی. نکته این است که بررسی و درج یک تثبیت را شریکاند، پس یک سفارش همزمان یا موجودی را مصرفشده میبیند یا اصلاً آن را نمیبیند.
پایگاه داده تکثیرشده چه میدهد و چه نمیدهد
پایگاه داده تکثیرشده میتواند وقتی مدل تراکنش خودش پشتیبانی کند، مرز گستردهتری فراهم کند. Spanner تراکنشهای اتمی خواندن-نوشتن را در یک پایگاه داده واحد و بر روی جدولها مستند میکند، با جداسازی و رفتار تلاش مجدد تعریفشده. این تضمینی است که آن را میخوانید، آزمایش میکنید و آگاهانه به آن تکیه میکنید.
همچنین تضمینی است که از محصول میآید، نه از مسیر. یک VPN میان دو منطقه تغییر میدهد که بستهها چگونه سفر میکنند و خطاها چگونه خود را نشان میدهند. این مرز تراکنش را حتی یک سطر هم گسترش نمیدهد، هرقدر هم تونل سالم به نظر برسد. اشتباه گرفتن این دو، معماریهایی میسازد که در آنها هر مؤلفه بررسی خودش را میگذراند و دادهها باز هم با هم نمیخوانند.
دو پایگاه داده به یک سیستم تبدیل نمیشوند
دو پایگاه داده که مستقل اداره میشوند، فقط به این دلیل که کلاینتها به هر دو دسترسی دارند، مدیر تراکنش مشترک پیدا نمیکنند. اگر کسبوکار واقعاً به تعهد اتمی در سراسر این جفت نیاز دارد، سازوکار هماهنگی، مشارکتکنندگان و فرایند بازیابی همه باید انتخاب و ارزیابی شوند، نه اینکه فرض شوند.
به لحظهای فکر کنید که یک مشارکتکننده یا یک پیوند پس از آماده شدن کار ناپدید میشود. یک تثبیت توزیعشده پشتیبانیشده میتواند وضعیت نامعلومی برجا بگذارد که به رویه بازیابی و تصمیم انسانی نیاز دارد، و هیچ قولی نمیدهد که هر منطقه در هر تقسیمی قابل نوشتن بماند.
اگر در عوض هماهنگی ناهمگام پذیرفتنی است، آن را صریح بگویید و حالتهای میانی کسبوکار به همراه قواعد آشتی را بنویسید. زنجیرهای از گامهای تثبیتشده محلی با جبران، طراحی مشروعی است؛ فقط یک تراکنش اتمی با نام دیگر نیست.
تلاش مجدد را پیش از نخستین قطعی طراحی کنید
کلاینت ممکن است پاسخ را پس از تثبیت عملیات از دست بدهد، بنابراین فراخواننده نمیتواند مهلت را شکست بداند. هویت درخواست پایدار را حفظ کنید و پیش از تلاش مجدد برای یک تغییر، از نتیجه سرویس یا سازوکار عدمتکرار استفاده کنید، وگرنه تلاش مجدد به یک نوشتن دوم تبدیل میشود.
فراخوانهای خودکار تراکنش هم میتوانند پس از یک لغو قابل تکرار بیش از یک بار اجرا شوند، که آنها را محل بدی برای اثرات بیرونی برگشتناپذیر میکند. آنها را بیرون از فراخوان نگه دارید مگر اینکه گردش کار پروتکل ایمن صریحی برایشان تعریف کند. همین احتیاط برای هر چیزی که پول هزینه میکند یا پیامی میفرستد صدق میکند. برداشت مضاعف گفتوگویی بسیار سختتر از یک خط گزارش تکراری است.
پذیرش باید چهار سناریو را دوباره اجرا کند: دو کلاینت که برای یک سطر مسابقه میدهند، لغوی که سرویس میگوید قابل تکرار است، تثبیتی که پاسخش هرگز نمیرسد، و از دست رفتن یک منطقه یا پیوند میان آنها. نتیجه کسبوکار تثبیتشده و وضعیتهای حلنشده را در کنار طراحی مسیریابی ثبت کنید تا کسی شبکه را با مؤلفهای که تضمین را میدهد اشتباه نگیرد.