حالت تاریک
فصل ۶ — جداسازی دادهٔ عملیاتی
خلاصهٔ تحلیلی — این متن برداشت و سازماندهی مفاهیم فصل به زبان فارسی است، نه ترجمهٔ واژهبهواژه.
مسئله و زمینه
تفکیک سرویسها بدون بازاندیشی در داده، اغلب فقط یک «مونولیت توزیعشده» میسازد: سرویسها جدا deploy میشوند، اما همگی به یک مدل و یک پایگاهدادهٔ مشترک گره خوردهاند. داده حساسترین دارایی کسبوکار است و بریدن آن از کد دشوارتر است؛ زیرا جدولها علاوه بر وابستگی منطقی، با کلید خارجی، view، trigger، procedure و تراکنش به هم متصلاند.
هدف فصل این نیست که «database-per-service» را قانون همگانی اعلام کند. پرسش درست این است که کدام فشارها جداسازی را توجیه میکنند و کدام فشارها نگهداشتن داده در کنار هم را. معماری خوب، مرز bounded context را با مسئولیت نوشتن و نیازهای عملیاتی سازگار میکند.
مفاهیم و الگوهای محوری
نیروهای جداساز و یکپارچهساز
دلایل اصلی جداسازی داده عبارتاند از:
- کنترل تغییر: تغییر ناسازگار در schema مشترک همهٔ مصرفکنندگان را همزمان درگیر میکند. سرویس مالک، با قرارداد API جدا از schema داخلی، اثر این تغییر را محصور میسازد.
- مدیریت اتصال و مقیاس: هر instance سرویس pool خودش را دارد؛ رشد instanceها میتواند اتصالهای یک پایگاه مشترک را اشباع کند. quota اتصال، راه مهار موقت است، نه جایگزین تفکیک درست.
- تابآوری و quantum معماری: پایگاه مشترک نقطهٔ شکست مشترک و بخشی از coupling ایستا است؛ جداسازی میتواند خرابی را به یک دامنه محدود کند.
- تناسب نوع پایگاهداده: همهٔ دادهها رفتار یکسان ندارند؛ حفظ اجباری همه در RDBMS ممکن است برای دادهٔ کلید-مقدار، سندی، گراف یا سری زمانی نامناسب باشد.
در برابر این نیروها، رابطهٔ دادهها و تراکنش واحد ACID دلیل مهمی برای نزدیک نگهداشتن جدولها هستند. اگر جداسازی، foreign key و invariants حیاتی را میشکند یا یک فرایند کسبوکاری واقعاً به commit/rollback واحد نیاز دارد، هزینهٔ تفکیک میتواند از سود آن بیشتر شود.
فرایند تکاملی پنجمرحلهای
- database و وابستگیهای آن را تحلیل و data domainها را پیدا کنید: مجموعهای از جدولها و artifactهای وابسته که در یک حوزهٔ محدود با هم استفاده میشوند.
- جدولها و artifactهای هر domain را به schema منطقی خودش منتقل کنید. synonym فقط پلی موقت برای دیدن وابستگیهاست، نه مرز نهایی.
- اتصال هر سرویس را به domain خودش محدود کنید؛ نیاز به دادهٔ بیرونی باید از سرویس مالک عبور کند، نه با query مستقیم بین schemaها.
- schemaهای تثبیتشده را به سرورهای مستقل ببرید: backup/restore سادهتر ولی مستلزم downtime است؛ replication downtime را کم میکند اما هماهنگی بیشتری میخواهد.
- اتصال قدیمی و schemaهای باقیمانده را حذف کنید تا واحدهای deploy و عملیات واقعاً مستقل شوند.
خروجی مطلوب، حاکمیت داده بهازای سرویس است: سرویس میتواند schema و فناوری ذخیرهسازی خود را تغییر دهد، اما بهای آن دسترسی دشوارتر به حجم زیاد دادهٔ بیرونی، از دسترفتن referential integrity میان دامنهها، و انتقال منطق stored procedureهای بیندامنهای به لایهٔ سرویس است.
انتخاب فناوری ذخیرهسازی
انتخاب محصول از نام فناوری آغاز نمیشود؛ از workload و مدل دسترسی آغاز میشود: منحنی یادگیری، مدلسازی، read/write throughput، availability/partition tolerance، consistency، بلوغ ابزار و مهارت تیم را کنار هم بسنجید.
- رابطهای: SQL و ACID، مدلسازی آشنا و workload متعادل؛ در مقیاس افقی و partition tolerance معمولاً پرهزینهتر است.
- Key-value و document: aggregate-oriented، مناسب بازیابی با کلید یا سندهای انعطافپذیر؛ طراحی مرز aggregate و الگوی query پیش از انتخاب حیاتی است.
- Column family: برای حجم بالای read/write و دادهٔ sparse مناسب، اما طراحی row key و مدل ذهنی آن تخصص میخواهد.
- Graph: برای پیمایش رابطهها ارزشمند است، ولی مدلسازی و shard کردن graph دشوارتر است.
- NewSQL: تلاش برای جمعکردن SQL/ACID با scale افقی؛ پیچیدگی را حذف نمیکند، بلکه بخشی از آن را به پلتفرم میسپارد.
- Cloud-native و time-series: اولی بار عملیاتی را با هزینه و وابستگی سرویسدهنده مبادله میکند؛ دومی برای رویدادهای timestampدار و append-oriented است، نه ذخیرهسازی عمومی.
موازنهها
- استقلال schema و استقرار در برابر حفظ رابطهها و تراکنش محلی.
- availability و scale مستقل در برابر هزینهٔ انتقال، همگامسازی و احتمال ناسازگاری داده.
- polyglot persistence در برابر هزینهٔ مهارت، عملیات، governance و ابزارهای متعدد.
- aggregate یکپارچه در document store، خواندن و render سادهتری میدهد؛ aggregateهای شکسته reuse را بالا میبرند، اما جمعکردن و تغییر آنها را پیچیدهتر میکنند.
راهنمای عملی
- پیش از migration، dependency map واقعی بسازید: چه کسی میخواند، چه کسی مینویسد، و کدام artifactهای database مرزها را میشکنند.
- محرکها را با معیارهای قابل مشاهده اثبات کنید: connection wait، blast radius خرابی، نرخ تغییر schema و الگوی بار؛ صرف «میکروسرویس بودن» توجیه نیست.
- ابتدا schemaهای منطقی را جدا کنید، سپس اتصالها را محدود کنید، و فقط پس از تثبیت مرزها سراغ سرورهای مستقل بروید.
- قرارداد سرویس را از طرح جدول جدا نگه دارید تا تغییر نام ستون یا نوع داده به مصرفکننده نشت نکند.
- برای هر domain، نوع داده، الگوی query، حجم، نرخ تغییر، SLA consistency و توان تیم را مستند کنید؛ سپس انتخاب فناوری را در ADR ثبت کنید.
نکات کلیدی فصل
- پایگاهدادهٔ مشترک میتواند استقلال deploy سرویسها را خنثی کند.
- جداسازی داده یک migration مرحلهای و مشترک میان تیم نرمافزار و DBA است، نه صرفاً انتقال جدول.
- مرز داده باید همزمان با مرز مسئولیت نوشتن و نیازهای تراکنشی طراحی شود.
- «بهترین database» وجود ندارد؛ تطبیق مدل داده و trade-off با مسئله مهم است.
یادداشتهای مترجم
- اصطلاحهای
bounded context،schema،aggregate،ACIDوpolyglot persistenceبرای حفظ دقت مفهومی لاتین نگه داشته شدهاند. - «حاکمیت داده» در این متن معادل data sovereignty است، نه مالکیت حقوقی داده.