بررسی معماری‌های دادهمعماری های اطلاعاتی

چرا monday.com دیتابیس‌های MySQL، Redis و Cassandra را کنار گذاشت و یک لایه سرویس‌دهی مبتنی بر DuckDB ساخت؟


زیرساخت داده در حال تجربه یک تغییر پارادایم است. برای دو دهه، به ما آموزش داده شده بود که روش درست معماری، ترکیب یک دیتابیس OLTP اثبات‌شده (مانند MySQL یا Postgres) با یک لایه کش (Redis) و شاید یک دیتابیس ستون‌گسترده (Cassandra) برای مقیاس‌پذیری است. این استک سال‌ها به خوبی به صنعت خدمت کرد. اما بارهای کاری (Workloads) مدرن — اسکیماهای داینامیک، خواندن‌های تحلیلی گسترده، الگوهای دسترسی مبتنی بر هوش مصنوعی و میلیون‌ها مستأجر (Tenant) که روزانه میلیاردها تغییر ایجاد می‌کنند — در حال درهم شکستن مدل قدیمی هستند.

تیم مهندسی monday.com اخیراً مقاله عمیقی با عنوان «mondayDB 3 – حل مشکل HTAP برای یک سیستم تریلیون جدولی» منتشر کرده است که جزئیات این تحول را شرح می‌دهد. بیایید نگاهی دقیق‌تر به آن بیندازیم؛ به‌ویژه برای کسانی که شاید هنوز به DuckDB ایمان نیاورده‌اند.

این تیم سیستمی را مدیریت می‌کند که می‌توان آن را به عنوان یک تریلیون جدول داینامیک در نظر گرفت؛ جایی که هر جدول اسکیمای خاص خود را دارد و کاربران آن را در لحظه تغییر می‌دهند. میلیون‌ها سازمان و ده‌ها میلیارد سطر که دائماً در حال تغییر هستند. دیتابیس MySQL، حتی با بهینه‌سازی‌های سنگین، هرگز برای چنین بار کاری طراحی نشده بود.

بنابراین آن‌ها دست به کار رادیکالی زدند: آن‌ها mondayDB 3 را ساختند، یک موتور ستونی (Columnar) سفارشی که قدرت خود را از DuckDB می‌گیرد و جایگزین استک اشتراکی قدیمی (MySQL + Redis + Cassandra) شد. این معماری جدید بر اساس مفهوم Sync-then-query (همگام‌سازی-سپس-کوئری) بنا شده است. نتیجه کار فقط یک بهبود تدریجی نبود. بارگذاری بردهای بزرگ ۲۰ برابر سریع‌تر شد. کوئری‌های تجمیعی (Aggregations) تا $۴۸\times$ سرعت گرفتند. هزینه‌های زیرساخت ۴۰-۶۰% کاهش یافت. و آن‌ها موفق شدند خواندن داده‌های همیشه تازه را با تأخیر (Latency) تک‌رقمی در مقیاس میلی‌ثانیه به دست آورند. فراتر از آن، این معماری جدید به‌طور تصادفی به فونداسیون بی‌نقصی برای هوش مصنوعی (AI) تبدیل شد: بازیابی معنایی (Semantic retrieval)، RAG و کوئری‌های عامل‌محور (Agentic) همگی اکنون روی همان زیرساخت و با همان ضمانت‌های تأخیر پایین اجرا می‌شوند.

در این پست، بررسی خواهیم کرد که چرا استک قبلی شکست خورد، معماری جدید در لایه‌های زیرین چگونه کار می‌کند، و چرا این معیارهای خیره‌کننده نتیجه مستقیم همین طراحی هستند. به همان اندازه مهم، بررسی خواهیم کرد که این الگو چه زمانی منطقی است و چه زمانی نیست؛ زیرا بزرگ‌ترین درس این مقاله «استفاده از DuckDB برای همه چیز» نیست، بلکه نحوه تفکر درباره لایه داده است، زمانی که الگوهای دسترسی شما هیچ شباهتی به مواردی ندارند که دیتابیس‌های سنتی برای آن‌ها ساخته شده‌اند.


نقطه فروپاشی: تقاطع دیتابیس‌های سطری و خواندن‌های تحلیلی گسترده

ساختار داده اصلی در monday.com یک بورد (Board) است. یک صفحه گسترده (Spreadsheet) را تصور کنید. حالا یک تریلیون از آن‌ها را تصور کنید که هر کدام ستون‌های خاص خود را دارند؛ متن، اعداد، تاریخ‌ها، وظایف افراد و لینک به بردهای دیگر. کاربران ستون‌ها را اضافه می‌کنند، نام آن‌ها را تغییر می‌دهند، نوع آن‌ها را عوض می‌کنند و در لحظه آن‌ها را حذف می‌کنند. هیچ اسکیمای ثابتی وجود ندارد؛ هر بورد در واقع جدول مجزایی با شکلِ در حال تکامل است.

آن‌ها سال‌ها تمام داده‌های بردها را با یک ترفند ساده در MySQL ذخیره می‌کردند: هر سطر یک آیتم بود و تمام مقادیر ستون‌های آن آیتم در یک ساختار یکپارچه JSON ذخیره می‌شد. این کار به آن‌ها انعطاف‌پذیری بی‌نهایتی در اسکیما می‌داد بدون اینکه نیازی به اجرای دستور ALTER TABLE با هر تغییر در بورد باشد. این روش به لطف قابلیت اطمینان MySQL و کمی شاردینگ (Sharding) هوشمندانه، برای مدت طولانی به خوبی کار کرد.

اما با عبور سیستم از مرز یک میلیون سازمان و رسیدن بردها به صدها هزار سطر، نادیده گرفتن نقاط ضعف غیرممکن شد:

  • بارگذاری بردهای بزرگ بیش از دو ثانیه طول می‌کشید. کاربران انتظار تعامل زیر یک ثانیه را دارند.
  • کوئری‌های تجمیعی (مرتب‌سازی، فیلتر کردن، گروه‌بندی) به شدت کند بودند. هر کوئری مجبور بود کل ساختار JSON را برای هر سطرِ منطبق از حالت سریال خارج کند (Deserialize)، حتی اگر فقط به یک ستون نیاز بود.
  • فرمت ذخیره‌سازی سطری (Row-oriented) در تضاد با الگوی دسترسی بود. وقتی کاربری یک بورد را باز می‌کند، حدود $۵۰۰$ سطر را می‌بیند اما در میان ستون‌های زیادی جستجو می‌کند. این یک خواندن تحلیلی و گسترده است. دیتابیس‌های سطری به صورت فیزیکی تمام ستون‌های یک سطر را در کنار هم ذخیره می‌کنند. این بدان معناست که برای خواندن فقط $۳$ ستون، دیتابیس همچنان باید کل سطر (شامل فایل حجیم JSON) را از دیسک فراخوانی کند که باعث هدررفت I/O و حافظه (Memory) می‌شود.
  • چندمستأجری (Multi-tenancy) اوضاع را بدتر کرد. میلیون‌ها سازمان جداول MySQL یکسانی را به اشتراک می‌گذاشتند. ایندکس‌ها به میلیاردها سطر متورم شدند. بارگذاری یک بورد نیازمند پیمایش در یک B-tree بود که حاوی داده‌های هزاران مستأجر نامرتبط بود؛ در نتیجه رکوردهای کشِ یکدیگر را بیرون می‌راندند و طوفان‌های I/O تصادفی ایجاد می‌کردند.

آن‌ها Read Replica اضافه کردند، جداول را پارتیشن‌بندی کردند و از ProxySQL برای مدیریت Pool اتصالات استفاده کردند. هر کدام از این کارها کمی زمان خرید اما مشکل اساسی را حل نکرد: آن‌ها در حال اجرای یک بار کاری تحلیلی روی یک دیتابیس سطری و تراکنشی (OLTP) بودند.

درس این اتفاق؟ وقتی عملیات اصلی شما “اسکن ستون‌های متعدد، فیلتر کردن، مرتب‌سازی، تجمیع و بازگرداندن یک صفحه از نتایج” روی یک اسکیمای داینامیک است، استک کلاسیک OLTP به دشمن شما تبدیل می‌شود. شما به یک موتور متفاوت نیاز دارید.


معماری جدید: تولد دوباره CQRS و معماری لامبدا

معماری mondayDB 3 بر اساس یک اصل تمیز CQRS (جداسازی مسئولیت‌های فرمان و کوئری) ساخته شده است: مسیر نوشتن و مسیر خواندن کاملاً از هم جدا هستند. این ایده جدیدی نیست، اما پیاده‌سازی آن با یک دیتابیس ستونی سبک (Embedded) و یک WAL خارجی، جایی است که جادو رخ می‌دهد.

علاوه بر CQRS، تیم یک الگوی معماری لامبدا را اتخاذ کرد که سیستم را به سه لایه تقسیم می‌کند:

۱. لایه بچ (Batch layer): اسنپ‌شات‌های پایدار از تمام داده‌ها به صورت فایل‌های DuckDB در فضای ذخیره‌سازی شیء (مانند S3). یک پایپ‌لاین دوره‌ای، تغییرات اخیر را در این فایل‌ها تجمیع (Flush) می‌کند.
۲. لایه سرعت (Speed layer): تغییرات (Mutations) لحظه‌ای را از طریق یک Write-Ahead Log (WAL) توزیع‌شده و خارجی ثبت می‌کند. تغییرات اخیر (از چند دقیقه تا چند ساعت گذشته) در این لاگِ سریع و مرتب‌شده قرار می‌گیرند.
۳. لایه سرویس‌دهی (Serving layer): ناوگانی از پردازش‌های زبان Go روی نودهای Kubernetes با درایوهای محلی NVMe SSD. هر نود به عنوان یک کشِ خواندنِ هوشمند (Read-through cache) عمل می‌کند. وقتی درخواست خواندنی می‌رسد، نود، فایل پایه DuckDB بورد را از لایه بچ (یا کشِ گرم خود) دریافت می‌کند، تغییرات معلق WAL را روی آن اعمال می‌کند تا فایل به‌روز شود و سپس کوئری را اجرا می‌کند.

از نظر مفهومی کل سیستم به این شکل است:

نکته کلیدی: دیتابیس DuckDB به صورت درون‌پردازشی (In-process) داخل نودهای سرویس‌دهی اجرا می‌شود. هیچ سرور دیتابیس مجزایی وجود ندارد. هر نود سرویس‌دهی، در زمان اجرای کوئری یک فایل DuckDB اختصاصی را به ازای هر بورد متصل (Attach) می‌کند، آن را همگام‌سازی (Sync) می‌کند، SQL را اجرا می‌کند و در صورت خروج از کش می‌تواند آن را جدا (Detach) کند. موتور ستونی DuckDB کوئری‌ها را به صورت برداری (Vectorized) روی RAM محلی و NVMe پردازش می‌کند؛ بدون نیاز به پرش‌های شبکه (Network hops) یا فرآیند Handshake برای اتصال.

چرا DuckDB؟ تیم متوجه شد که بار کاری آن‌ها اساساً تحلیلی است: اسکن‌های گسترده، فیلتر کردن، گروه‌بندی و مرتب‌سازی. DuckDB یک دیتابیس ستونی پیشرفته و Embedded است که می‌تواند به عنوان یک کتابخانه (Library) استفاده شود. این دیتابیس سریع است، از SQL پشتیبانی می‌کند و مهم‌تر از همه، اجازه متصل کردن و جدا کردن فایل‌های دیتابیس را در زمان اجرا (Runtime) می‌دهد. این ویژگی کاملاً با یک سیستم چندمستأجری تطابق دارد: اختصاص یک فایل DuckDB به ازای هر بورد، ایزوله‌سازی کامل مستأجرها را بدون سربار سیستم‌عامل فراهم می‌کند.

اما DuckDB یک محدودیت دارد: در هر زمان فقط یک نویسنده (Writer) برای هر فایل می‌تواند وجود داشته باشد. این محدودیت برای سیستمی با هزاران عملیاتِ نوشتنِ هم‌زمان، شبیه به یک نقص غیرقابل‌قبول به نظر می‌رسد. اما تیم، این محدودیت را به بهترین تصمیم طراحی خود تبدیل کرد.


فرمول جادویی: WAL خارجی و رویکرد Sync-Then-Query

به جای نوشتن مستقیم در فایل‌های DuckDB از مسیر نوشتن، mondayDB 3 تمام عملیات نوشتن را از طریق یک WAL توزیع‌شده خارجی مدیریت می‌کند. مسیر نوشتن به این شکل است:

۱. یک تغییر رخ می‌دهد (مثلاً کاربری سلولی را در یک بورد ویرایش می‌کند).
۲. این تغییر از طریق Kafka هدایت می‌شود و با شناسه (ID) بورد پارتیشن‌بندی می‌شود تا ترتیب آن تضمین شود.
۳. سرویس WAL writer، تغییر را با یک شماره توالی افزایشی (Sequence number) در WAL خارجی ذخیره می‌کند.
۴. مسیر نوشتن به پایان می‌رسد. این فرآیند هرگز DuckDB را لمس نمی‌کند.

حالا وقتی یک درخواست خواندن می‌رسد، نود سرویس‌دهی پروتکل Sync-then-query (همگام‌سازی-سپس-کوئری) را اجرا می‌کند:

۱. مسیریابی (Route): لود بالانسر (Load balancer) از یک الگوریتم مسیریابی چسبنده (Sticky routing) استفاده می‌کند تا درخواست را به یک نود مشخص ارسال کند (در ادامه این مورد را بررسی می‌کنیم).
۲. بررسی کش (Check cache): نود به دنبال فایل DuckDB بورد در کش LRU مبتنی بر NVMe خود می‌گردد. اگر فایل موجود باشد (که در بیش از $۹۵\%$ مواقع این‌طور است)، مستقیماً به مرحله ۴ می‌رویم.
۳. خطای کش (Cache miss): فایل از فضای ذخیره‌سازی شیء دانلود (یا از ابتدا ساخته) شده و در کش قرار می‌گیرد.
۴. تعیین موقعیت WAL: آخرین شماره توالی همگام‌سازی شده که در فایل محلی ذخیره شده است، خوانده می‌شود.
۵. همگام‌سازی (Sync): از WAL خارجی برای دریافت هر تغییری با شماره توالی بالاتر از آنچه داریم، کوئری گرفته می‌شود. این تغییرات روی فایل DuckDB محلی اعمال می‌شوند. اپلیکیشن از الگوی «حذف بر اساس کلید اصلی، سپس درج انبوه (Bulk insert)» برای هر تغییر استفاده می‌کند، که برای حالت معمول (داشتن چند صد تغییر معلق) سریع و Idempotent (مستقل از تکرار) است.
۶. اجرا (Execute): کوئری SQL کاربر روی فایل DuckDB که اکنون کاملاً به‌روز شده است، به صورت درون‌پردازشی اجرا می‌شود.
۷. بازگرداندن نتایج: نتایج به صورت سریالایز شده بازگردانده می‌شوند.

کل این چرخه معمولاً در کمتر از $۱۰$ میلی‌ثانیه تکمیل می‌شود.

این طراحی محدودیت تک‌نویسنده بودن DuckDB را به یک نقطه قوت تبدیل می‌کند. از آنجایی که فقط روتینِ Syncِ در نودِ سرویس‌دهی، روی فایل DuckDB می‌نویسد، هیچ تداخلی در نوشتن (Write contention) وجود ندارد. و به دلیل اینکه WAL خارجی است، مسیر خواندن کاملاً از خطاهای مسیر نوشتن ایزوله است. اگر بک‌اند WAL قطع شود، نودهای سرویس‌دهی همچنان به خواندن داده‌ها از آخرین وضعیت همگام‌سازی شده ادامه می‌دهند. اگر یک نود سرویس‌دهی از کار بیفتد، هیچ تأثیری بر پردازش نوشتن‌ها نخواهد داشت.


کارایی بر اساس طراحی: چرا این معماری سرعت را ۲۰ تا ۴۰ برابر افزایش می‌دهد؟

این معیارها جادو نیستند؛ بلکه نتیجه مستقیم سه تصمیم اساسی در معماری هستند.

۱. ذخیره‌سازی ستونی و اجرای برداری (Vectorized execution)
دیتابیس DuckDB داده‌ها را ستون به ستون ذخیره می‌کند، نه سطر به سطر. وقتی کاربری بوردی را باز می‌کند و فقط به $۵$ ستون از $۵۰$ ستون ممکن نیاز دارد، موتور دیتابیس دقیقاً همان $۵$ ستون را از دیسک می‌خواند. هرگز ستون‌های دیگر را لمس نمی‌کند. علاوه بر این، DuckDB داده‌ها را در دسته‌های $۲۰۴۸$ مقداری پردازش می‌کند و از دستورالعمل‌های SIMD و دسترسی حافظه هم‌تراز با کش بهره می‌برد. برای کوئری‌های مبتنی بر تجمیع — جمع‌ها، شمارش‌ها و میانگین‌ها روی هزاران سطر — این روش به مراتب سریع‌تر از دی‌سریالایز کردن سطریِ JSON در MySQL است.

۲. ایزوله‌سازی فایل به ازای هر مستأجر و حذف ایندکس‌های مشترک
در معماری قدیمی MySQL، یک ایندکس برای یک بورد، صفحات B-tree را با داده‌های صدها بورد دیگر به اشتراک می‌گذاشت. در mondayDB 3، هر بورد فایل DuckDB مختص خود را دارد. هیچ ساختار داده مشترکی وجود ندارد. یک کوئری روی یک بورد هرگز باعث درگیری I/O یا آلودگی کش از طرف بوردهای دیگر نمی‌شود. این کار مشکل همسایه پر سر و صدا (Noisy-neighbor) را که دیتابیس‌های چندمستأجری و اشتراکی را فلج کرده بود، از بین می‌برد. کش LRU مبتنی بر NVMe فایل‌های بوردهای پرکاربرد را در حافظه نگه می‌دارد، بنابراین بوردهای داغ اغلب نیازی به خواندن از دیسک ندارند.

۳. مسیریابی هوشمند با تمایل به کش (Weighted Rendezvous Hashing)
اگر درخواستی برای یک بورد به نودی برسد که فایل آن را در کش ندارد، عملکرد به شدت افت می‌کند. برای جلوگیری از این مشکل، mondayDB 3 از یک لایه مسیریابی سفارشی به نام Ranja استفاده می‌کند. این لایه از الگوریتم Weighted Rendezvous Hashing استفاده می‌کند: برای هر درخواست، هر نود به صورت مستقل فرمول Weighted Rendezvous Hashing را محاسبه می‌کند و درخواست به نودی با بالاترین امتیاز ارسال می‌شود. این وزن‌ها متناسب با ظرفیت هستند و به صورت پویا بر اساس بار پردازشی نود تنظیم می‌شوند. این مسیریابی چسبنده تضمین می‌کند که درخواست‌های مکرر برای یک بورد به همان نود قبلی ارسال شوند و در نتیجه نرخ Cache hit به حداکثر می‌رسد (همواره بیش از ۹۵٪).

علاوه بر این، تکنیکِ درخواست‌های پوششی (Hedged requests)، اسپایک‌های گاه‌به‌گاهِ تأخیر را پنهان می‌کنند: اگر نود اصلی در عرض۵۰۰ میلی‌ثانیه پاسخ ندهد، درخواست به یک نود ثانویه ارسال می‌شود. این معماری به طور رسمی با زبان مدلسازی TLA+ تأیید شده تا صحت عملکرد آن در زمان خرابیِ نودها و قطعی‌های شبکه تضمین شود.

نتیجه این کار، یک تأخیر قابل‌پیش‌بینیِ تک‌رقمی در مقیاس میلی‌ثانیه، حتی برای بردهای بزرگ، و سیستمی است که به صورت تقریباً خطی با افزایش تعداد نودهای سرویس‌دهی مقیاس‌پذیر می‌شود.


قهرمان گمنام: مهاجرت بدون قطعی (Zero-Downtime) برای بیش از ۱ میلیون سازمان

ساخت یک موتور جدید یک چیز است، اما انتقال میلیون‌ها مشتری بدون اینکه آن‌ها متوجه شوند، کاملاً چیز دیگری است.

این مهاجرت یک فرآیند ۱۸ ماهه، تدریجی و کاملاً قابل‌بازگشت بود. هر بخش از سیستم جدید، پشت یک Feature flag قرار داشت. در هر لحظه، تغییر یک Flag می‌توانست مسیر خواندنِ اطلاعات یک بورد را از سیستم جدید، دوباره به MySQL بازگرداند. تیم، اعتبارسنجی دوگانه (Dual-read validation) را ماه‌ها اجرا کرد: بارگذاری هر بورد هم روی MySQL و هم روی سیستم جدید اجرا می‌شد و نتایج به طور خودکار با هم مقایسه می‌شدند. آن‌ها باگ‌های ظریفی (مانند تفاوت‌های نرمال‌سازی در یونیکد، خطاهای دقت اعشاری و گره‌های مرتب‌سازی) را پیدا کردند که یافتن آن‌ها با تست‌های مصنوعی غیرممکن بود.

از آنجایی که آن‌ها در تمام این مدت، داده‌ها را به صورت دوگانه (Dual-writing) روی Kafka و WAL می‌نوشتند، داده‌ها در سیستم جدید هنگام انتقال نهایی کاملاً تازه (Fresh) بودند. خودِ انتقال نهایی صرفاً تغییر یک Feature flag بود: بدون نیاز به انتقال داده‌ها و بدون نیاز به راه‌اندازی مجدد (Restart). آن‌ها نوشتن دوگانه را تا $۳۰$ روزِ دیگر به عنوان یک شبکه ایمنی حفظ کردند، و سپس به آرامی مسیر قدیمی MySQL را برای همیشه خاموش کردند.

کاربران تنها چیزی که متوجه شدند این بود که بوردهایشان به طرز چشمگیری سریع‌تر شده است.


این معماری چه چیزی هست – و چه چیزی نیست

بیایید شفاف باشیم: شما نمی‌توانید دقیقاً همین معماری را روی یک نرم‌افزار SaaS تک‌مستأجری با عملیات ساده CRUD پیاده کنید و انتظار افزایش سرعت ۴۸ برابر را داشته باشید. mondayDB 3 عمیقاً برای مجموعه‌ای بسیار خاص از شرایط ساخته شده است:

  • سیستم چندمستأجری (Multi-tenancy) عظیم و داینامیک که در آن ایزوله‌سازی فایل به ازای هر مستأجر منطقی است.
  • بار کاری سنگین از نظر خواندن که مانند کارهای تحلیلی (اسکن گسترده، تجمیع‌ها، فیلترها) رفتار می‌کند، حتی اگر وظیفه سرویس‌دهی به رابط‌های کاربری (UI) عملیاتی را داشته باشد.
  • اسکیمایی که دائماً تغییر می‌کند و ایندکس‌گذاری‌های سنتی و مایگریشن اسکیما (Schema Migration) را غیرعملی می‌سازد.

اگر بار کاری شما شامل جستجوهای نقطه‌ای با توان عملیاتی بالا (High-throughput point lookups)، تداخل زیاد در نوشتن (Heavy write contention)، یا نیاز به Join بین مستأجرهای مختلف باشد، این معماری مناسب نخواهد بود. اما دقیقاً نکته همینجاست: تیمِ مهندسی با محدود کردنِ دامنهِ نیازمندی‌ها (Scope) موفق شد، نه با دنبال کردن یک راه‌حل همه‌منظوره.

درس بزرگ‌تر برای بیشتر مهندسین داده این نیست که «برای همه چیز از DuckDB استفاده کنید». بلکه این است: وقتی الگوهای دسترسی شما شبیه به کارهای تحلیلی است، دست از تنبیه کردنِ یک دیتابیس سطریِ تراکنشی بردارید. و اگر بتوانید یک لایه سرویس‌دهی سبک، پیرامون یک دیتابیس Embedded مبتنی بر فایل بسازید — و همگام‌سازی، کش کردن و مسیریابی را خودتان مدیریت کنید — ممکن است در نهایت به سیستمی دست یابید که ساده‌تر، سریع‌تر و ارزان‌تر از یک دیتابیس توزیع‌شدهِ تمام‌عیار باشد.

ستاره واقعی در اینجا فقط DuckDB نیست؛ بلکه الگوی معماریِ یک لایه داده‌ی نازک بر روی یک موتور فایل‌محور، با پشتیبانی از ذخیره‌سازی شیء و یک WAL خارجی است. این الگو قابل‌انتقال (Portable) است و این همان چیزی است که مهندسین داده باید با دقت بسیار بیشتری مطالعه کنند.


چرا این موضوع برای مهندسین داده مهم است؟

داستان mondayDB 3 درس‌هایی دارد که بسیار فراتر از یک شرکت صدق می‌کند، به خصوص اگر در اوایل مسیر شغلی خود هستید و می‌خواهید بفهمید سیستم‌های مقیاس‌پذیر بزرگ امروزه چگونه ساخته می‌شوند.

  • موتور دیتابیس خود را با الگوی دسترسی‌تان تطبیق دهید. وقتی خواندن‌های شما گسترده و تحلیلی هستند، یک دیتابیس ستونی همیشه یک دیتابیس سطری را شکست خواهد داد. ابزاری را مجبور به انجام کاری که برای آن طراحی نشده است، نکنید.
  • الگوهای CQRS و Event-driven فقط مختص میکروسرویس‌ها نیستند. جداسازی مسیر خواندن از نوشتن با یک لاگ (Log) خارجی می‌تواند مزایای چشمگیری در مقیاس‌پذیری و تاب‌آوری (Resilience) به شما بدهد، حتی درون خودِ لایه دیتابیس.
  • دیتابیس‌های Embedded در حال تغییر دادن قواعد بازی هستند. اجرای یک موتور تحلیلی کامل به صورت درون‌پردازشی، سربار شبکه را از بین می‌برد و عملیات را ساده می‌کند. وقتی این روش با فضای ذخیره‌سازی شیء و یک کش محلی سریع ترکیب شود، می‌توانید یک لایه سرویس‌دهی بسازید که در بارهای کاریِ مناسب، از یک دیتابیس توزیع‌شدهِ سنتی عملکرد بهتری داشته باشد.
  • ابزارهای هدف‌مند (Purpose-built) بر ابزارهای همه‌منظوره پیروز می‌شوند – زمانی که عدم تطابق واقعی باشد. این تیم یک دیتابیس جدید نساخت؛ آن‌ها یک سیستم داده ساختند که تنها برای یک چیز بهینه‌سازی شده بود: خواندن‌های گسترده روی اسکیماهای داینامیک. با محدود کردن دامنه، آن‌ها به ویژگی‌های عملکردی و هزینه‌ای دست یافتند که هیچ راه‌حلِ آماده‌ای (Off-the-shelf) نمی‌توانست با آن رقابت کند.
  • مفهوم انتزاع فایل (File-abstraction) قدرتمندتر از آن چیزی است که فکر می‌کنید. برخورد با داده‌های هر مستأجر به عنوان یک فایل واحد، و ساختن یک ارکستراسیون سبکِ اختصاصی پیرامون آن، می‌تواند ساده‌تر و مقیاس‌پذیرتر از مدیریت یک دیتابیس اشتراکیِ عظیم باشد. در این حالت پیچیدگی از بین نمی‌رود — بلکه به مدیریت کش، مسیریابی و همگام‌سازی منتقل می‌شود — اما در عوض شما می‌توانید آن را دقیقاً کنترل کنید.

امروزه، mondayDB 3 پاسخگوی ۱۰۰٪ از ترافیکِ خواندنِ بوردها برای بیش از۱ میلیون سازمان است. اما آنچه هیجان‌انگیزتر است، مسیر آینده آن است. از آنجا که سیستم در حال حاضر ایزوله‌سازی فایل به ازای هر بورد، دریافت داده‌های تازه از طریق روش Sync-then-query و مسیریابی چسبنده را فراهم می‌کند، این معماری یک فونداسیون عالی برای لایه هوش مصنوعی (AI) است. وقتی یک Agent هوش مصنوعی نیاز به بازیابی زمینه (Context) درباره یک بورد دارد، جدیدترین وضعیت را دریافت می‌کند، نه یک Embedding قدیمی و منقضی‌شده. جستجوی معنایی، RAG و کوئری‌های عامل‌محور، همگی روی همان پایپ‌لاین و با همان تأخیرِ تک‌رقمی در مقیاس میلی‌ثانیه اجرا می‌شوند. معماری‌ای که جایگزین MySQL شد، اکنون زیرساخت قدرتمند هوش مصنوعی در monday.com است.

هیچ‌کدام از این‌ها به این معنی نیست که MySQL، Postgres یا MongoDB قرار است از بین بروند. آن‌ها هنوز هم بخش اعظم اپلیکیشن‌های امروزی را (به دلایل درستی) تغذیه می‌کنند. اما وقتی بار کاری شما شبیه به کارهای تحلیلی است، وقتی اسکیماها دقیقه به دقیقه تغییر می‌کنند، و وقتی در حال سرویس‌دهی به میلیون‌ها مستأجر روی یک زیرساخت مشترک هستید، فرضیات قدیمی کارایی خود را از دست می‌دهند. تغییر پارادایم واقعی در مورد کنار گذاشتن دیتابیس‌های سنتی نیست — بلکه در مورد تشخیص زمانی است که آن‌ها ابزار نامناسبی هستند، و داشتن شجاعتِ ساختنِ چیزی است که دقیقاً برای آن هدف مناسب باشد. قمار monday.com روی یک دیتابیس Embedded تک‌فایلی که در یک لایه سرویس‌دهی هوشمند پوشانده شده بود، نشان می‌دهد وقتی دست از پذیرش الگوهای قدیمی به عنوان تنها راه چاره برمی‌دارید و آن‌ها را تنها به عنوان یکی از انتخاب‌ها در نظر می‌گیرید، تا چه حد کارهای بزرگی ممکن می‌شود.


اگر در حال ساخت سیستم‌های توزیع‌شده مقیاس‌پذیر، لایه‌های سرویس‌دهی تحلیلی یا زیرساخت‌های مبتنی بر هوش مصنوعی (AI-native) هستید، الگوهایی مانند این را زیر نظر داشته باشید. آن‌ها شاید همه‌جا کاربرد نداشته باشند، اما در جایی که مناسب هستند، تحولات شگرفی ایجاد می‌کنند.

 

مجتبی بنائی

دانشجوی دکترای نرم‌افزار دانشگاه تهران (yun.ir/smbanaie)، مدرس دانشگاه و فعال در حوزه توسعه نرم‌افزار و مهندسی داده که تمرکز کاری خود را در چند سال اخیر بر روی مطالعه و تحقیق در حوزه کلان‌داده و زیرساخت‌های پردازش داده و تولید محتوای تخصصی و کاربردی به زبان فارسی و انتشار آنها در سایت مهندسی داده گذاشته است. مدیریت پروژه‌های نرم‌افزاری و طراحی سامانه‌های مقیاس‌پذیر اطلاعاتی از دیگر فعالیتهای صورت گرفته ایشان در چند سال گذشته است.

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

این سایت از اکیسمت برای کاهش جفنگ استفاده می‌کند. درباره چگونگی پردازش داده‌های دیدگاه خود بیشتر بدانید.

دکمه بازگشت به بالا