پست

مفاهیم اصلی مصاحبه‌های طراحی سیستم

مهم‌ترین مفاهیم لازم برای مصاحبه‌های طراحی سیستم شامل مقیاس‌پذیری، قضیه CAP، قفل‌گذاری، ایندکس‌گذاری، پروتکل‌های ارتباطی، امنیت و مانیتورینگ

مفاهیم اصلی مصاحبه‌های طراحی سیستم

مفاهیم اصلی

در این فصل مهم‌ترین مفاهیمی را مرور می‌کنیم که برای مصاحبه‌های طراحی سیستم لازم است. این مفاهیم را مدیران و مهندسان ارشد شرکت‌های FAANG گردآوری کرده‌اند.

آشنایی با ساختار کلی مصاحبه، همان‌طور که در بخش تحویل آمده، به شما کمک می‌کند مصاحبه را بهتر پیش ببرید. اما برای حل مسائلی که در مصاحبه با آن‌ها روبه‌رو می‌شوید کافی نیست. برای این کار باید چند مفهوم پایه‌ای طراحی سیستم را هم خوب بشناسید.

مفاهیم رایج

در ادامه، متداول‌ترین مفاهیمی را که در مصاحبه‌های طراحی سیستم با آن‌ها برخورد می‌کنید مرور می‌کنیم.

مقیاس‌پذیری

یکی از مهم‌ترین موضوعات در بسیاری از سوال‌های طراحی سیستم، نحوه مواجهه با مقیاس است. راه‌های زیادی برای این کار وجود دارد، اما مصاحبه‌گر حتماً می‌خواهد بداند چطور یک سیستم را به‌صورت افقی (horizontal) مقیاس می‌دهید. مقیاس افقی یعنی برای افزایش ظرفیت، ماشین‌های بیشتری به سیستم اضافه کنیم. در مقابل، مقیاس عمودی (vertical) یعنی منابع بیشتری به همان یک ماشین اضافه کنیم.

مصاحبه‌گران باتجربه‌تر معمولاً به این نکته توجه می‌کنند که مقیاس عمودی پیچیدگی اضافی بسیار کمتری ایجاد می‌کند. اگر بتوانید حجم کار را تخمین بزنید و به این نتیجه برسید که در آینده قابل‌پیش‌بینی با مقیاس عمودی هم جواب می‌گیرید، این راه اغلب از مقیاس افقی بهتر است. بسیاری از سیستم‌ها می‌توانند به‌صورت عمودی تا حد شگفت‌انگیزی رشد کنند.

اضافه کردن ماشین هزینه پنهان دارد (No free lunch). با مقیاس‌دهی، اغلب باید با توزیع کار، داده و state در کل سیستم درگیر شوید. این یکی از دلایل رایج «پرچم زرد» گرفتن در مصاحبه‌های طراحی سیستم است، پس کمی بیشتر درباره‌اش حرف می‌زنیم.

کاندیداهای کم‌تجربه معمولاً دو اشتباه می‌کنند. اول این‌که برای حل هر مشکل عملکردی سراغ مقیاس افقی می‌روند، حتی وقتی لازم نیست. دوم این‌که تبعات مقیاس افقی روی بقیه سیستم را در نظر نمی‌گیرند. وقتی به یک گلوگاه (bottleneck) برمی‌خورید، مراقب باشید به‌جای اصلاح طراحی ضعیف، فقط ماشین به آن اضافه نکنید.

اگر مقیاس افقی انتخاب درستی است، باید به نحوه توزیع کار بین ماشین‌ها فکر کنید. اغلب سیستم‌های مدرن برای این کار از تکنیکی به نام Consistent Hashing استفاده می‌کنند. در این روش، هم داده‌ها و هم ماشین‌ها روی یک فضای دایره‌ای به نام «حلقه هش» (hash ring) قرار می‌گیرند. به این ترتیب می‌توانید ماشین اضافه یا حذف کنید و کمترین جابه‌جایی داده را داشته باشید.

توزیع کار

نخستین چالش مقیاس افقی این است که کار به ماشین مناسب برسد. معمولاً این کار را یک load balancer انجام می‌دهد و تعیین می‌کند هر درخواست ورودی به کدام گره از گروه برود. load balancerها استراتژی‌های مختلفی دارند، مثل کمترین تعداد اتصال یا انتخاب بر اساس میزان مصرف. با این حال، روش ساده Round Robin اغلب کافی است. برای کارهای ناهمزمان (asynchronous) معمولاً از یک سیستم صف استفاده می‌شود.

توزیع کار باید تا حد ممکن بار سیستم را یکنواخت نگه دارد. برای مثال، اگر از یک hash map برای توزیع کار بین گره‌ها استفاده کنید، ممکن است الگوی درخواست‌های ورودی باعث شود یک گره بار نامتناسبی بگیرد. مقیاس‌پذیری سیستم شما در نهایت به این بستگی دارد که این مشکل را چقدر خوب حل کنید. اگر یک گره ۹۰٪ و بقیه ۱۰٪ مشغول باشند، از مقیاس افقی سود چندانی نمی‌برید.

توزیع داده

باید به نحوه توزیع داده در سیستم هم فکر کنید. در بعضی سیستم‌ها، یعنی داده را در حافظه گرهٔ پردازش‌کننده نگه می‌دارید. در بیشتر موارد، یعنی داده در پایگاه داده‌ای است که بین همه گره‌ها مشترک است. سعی کنید داده را طوری پارتیشن‌بندی کنید که هر گره بدون ارتباط با گره‌های دیگر به داده موردنیازش دسترسی داشته باشد. اگر ناچار به ارتباط با گره‌های دیگر هستید (مفهومی به نام fan-out)، تعداد آن‌ها را کم نگه دارید.

یک ضدالگوی رایج این است که درخواست‌ها را به گره‌های مختلف بفرستید و بعد نتیجه همه را جمع کنید. این الگو، یعنی scatter-gather، مشکل‌ساز است. ترافیک شبکه‌ای زیادی ایجاد می‌کند، به خرابی هر اتصال حساس است و اگر نتیجه نهایی به همه پاسخ‌ها وابسته باشد، از مشکل تأخیر دم (tail latency) هم رنج می‌برد.

اگر مسئله طراحی شما جغرافیایی است، به احتمال زیاد می‌توانید بر اساس چیزی شبیه REGION_ID پارتیشن‌بندی کنید. برای سیستم‌هایی که با مکان‌های فیزیکی سروکار دارند، این روش مقیاس‌دهی بسیار خوبی است. چون در بسیاری از مسائل، کاربر فقط به داده‌های همان مکان یا اطراف آن نیاز دارد. مثلاً کاربری در آمریکا به داده‌های اروپا نیازی ندارد.

مقیاس افقی روی داده ذاتاً چالش هماهنگ‌سازی (synchronization) می‌آورد. یا داده را در یک پایگاه داده مشترک می‌خوانید و می‌نویسید که از طریق شبکه در دسترس است (در حالت ایده‌آل با تأخیر حدود ۱ تا ۱۰ میلی‌ثانیه)، یا چند نسخه از آن را روی هر سرور نگه می‌دارید. این یعنی race condition و چالش‌های سازگاری! بیشتر پایگاه‌های داده برای حل مستقیم بخشی از این مشکلات ساخته شده‌اند، مثلاً با تراکنش‌ها. در بعضی موارد هم ممکن است لازم باشد از قفل توزیع‌شده استفاده کنید. در هر صورت باید آماده باشید درباره نحوه حفظ سازگاری داده‌ها صحبت کنید.

قضیه CAP

قضیه CAP مفهومی بنیادی در سیستم‌های توزیع‌شده است. طبق این قضیه، از میان سه ویژگی سازگاری (Consistency)، دسترس‌پذیری (Availability) و تحمل پارتیشن (Partition Tolerance) فقط دو مورد را می‌توان داشت. در عمل، چون پارتیشن شبکه اجتناب‌ناپذیر است، باید بین سازگاری و دسترس‌پذیری یکی را انتخاب کنید.

انتخاب سازگاری یعنی همه گره‌ها در هر لحظه داده یکسانی را می‌بینند. پس از انجام یک نوشتن، همه خواندن‌های بعدی، از هر گرهای که باشند، همان مقدار را برمی‌گردانند. اما هنگام پارتیشن شبکه، برای حفظ این تضمین ممکن است بعضی گره‌ها در دسترس نباشند.

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

در مصاحبه طراحی سیستم، دسترس‌پذیری باید انتخاب پیش‌فرض شما باشد. فقط وقتی به سازگاری قوی (Strong Consistency) نیاز دارید که خواندن داده کهنه قابل‌قبول نباشد.

نمونه سیستم‌هایی که به سازگاری قوی نیاز دارند:

  • سیستم‌های مدیریت موجودی، چون سطح موجودی باید دقیق ردیابی شود تا محصول بیش از موجودی فروخته نشود.
  • سیستم‌های رزرو منابع محدود (صندلی هواپیما، بلیت رویداد، اتاق هتل)، چون باید جلوی رزرو دوباره یک مورد را بگیرید.
  • سیستم‌های بانکی، چون موجودی حساب باید در همه گره‌ها یکسان باشد تا از تقلب جلوگیری شود.

ویژگی مشترک این سیستم‌ها این است که هر ناهماهنگی، حتی موقتی، می‌تواند مشکل تجاری یا فنی جدی ایجاد کند.

لازم نیست برای کل سیستم یک مدل سازگاری انتخاب کنید. بخش‌های مختلف سیستم اغلب نیازهای متفاوتی دارند. مثلاً در یک سیستم تجارت الکترونیک، توضیحات محصول می‌تواند در نهایت سازگار (eventually consistent) باشد، اما شمارش موجودی و پردازش سفارش به سازگاری قوی نیاز دارند تا فروش بیش از موجودی رخ ندهد.

قفل‌گذاری

در سیستم ممکن است منابع مشترکی داشته باشیم که در هر زمان فقط یک کلاینت باید به آن‌ها دسترسی داشته باشد. نمونه‌اش یک شمارنده مشترک (مثل تعداد موجودی) یا رابط یک دستگاه فیزیکی (مثلاً یک پل متحرک!) است. قفل‌گذاری (locking) یعنی اطمینان از این‌که در هر لحظه فقط یک کلاینت به منبع مشترک دسترسی دارد.

قفل در تمام سطوح سیستم‌های کامپیوتری وجود دارد: در هسته سیستم‌عامل، در برنامه‌های شما، در پایگاه داده و حتی به شکل قفل توزیع‌شده. به همین دلیل موضوع پرتکراری در مصاحبه‌های طراحی سیستم است. قفل‌ها برای درستی اجرای سیستم مهم‌اند، اما می‌توانند به عملکرد آسیب بزنند.

در بیشتر مصاحبه‌ها، وقتی به race condition فکر می‌کنید، باید سراغ قفل هم بروید. race condition یعنی چند کلاینت هم‌زمان سعی کنند به یک منبع دسترسی پیدا کنند. نتیجه‌اش می‌تواند خراب شدن داده، از دست رفتن به‌روزرسانی‌ها و مشکلات دیگر باشد.

هنگام استفاده از قفل باید به سه چیز توجه کنید.

granularity قفل

قفل‌ها را تا حد ممکن ریزدانه (fine-grained) می‌خواهیم، یعنی فقط همان بخشی را قفل کنیم که لازم است تا کلاینت‌های دیگر بی‌دلیل مسدود نشوند. مثلاً هنگام به‌روزرسانی پروفایل یک کاربر، فقط همان پروفایل را قفل می‌کنیم، نه کل جدول کاربران را.

مدت قفل

قفل‌ها باید کوتاه‌ترین زمان ممکن نگه داشته شوند، یعنی فقط به اندازه بخش بحرانی (critical section). مثلاً در به‌روزرسانی پروفایل، قفل را فقط برای مدت خود به‌روزرسانی نگه می‌داریم، نه برای کل درخواست.

آیا می‌توان قفل را دور زد؟

در بسیاری از موارد می‌توانیم با کنترل هم‌زمانی خوش‌بینانه (optimistic concurrency control) از قفل پرهیز کنیم. این روش به‌خصوص وقتی مناسب است که کار فقط خواندنی باشد یا بتوان آن را دوباره تلاش کرد. در این روش فرض می‌کنیم کار را بدون قفل می‌توان انجام داد و بعد بررسی می‌کنیم که فرضمان درست بوده یا نه. در بیشتر سیستم‌ها برای این کار می‌توان از عملیات compare-and-swap استفاده کرد.

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

ایندکس‌گذاری

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

ابتدایی‌ترین روش این است که داده را در یک hash map بر اساس یک کلید خاص نگه داریم. هر وقت بخواهیم داده را با آن کلید بگیریم، این کار در زمان O(1) انجام می‌شود و دیگر لازم نیست برای پیدا کردن داده، کل مجموعه را اسکن کنیم.

روش دیگر این است که داده‌ها را در یک لیست مرتب نگه داریم. این کار اجازه می‌دهد با جستجوی دودویی (binary search) داده را در زمان O(log n) پیدا کنیم. این روش در پایگاه‌های داده رایج است.

ایندکس‌ها انواع مختلفی دارند، اما اصل آن‌ها یکی است: کمترین کار لازم را از قبل انجام بدهید تا خواندن سریع‌تر شود.

بیشتر سوال‌های ایندکس‌گذاری به پایگاه داده شما مربوط می‌شوند و گزینه‌ها به انتخاب پایگاه داده بستگی دارد. برای مثال، بیشتر پایگاه‌های داده رابطه‌ای اجازه می‌دهند روی هر ستون یا گروهی از ستون‌ها ایندکس بسازید. اما این امکان نامحدود نیست. پایگاه‌هایی مثل DynamoDB اجازه می‌دهند ایندکس‌های ثانویه زیادی بسازید، ولی در پایگاه‌هایی مثل Redis باید استراتژی ایندکس‌گذاری را خودتان طراحی و پیاده‌سازی کنید.

اگر می‌توانید ایندکس‌گذاری را در همان پایگاه داده اصلی انجام دهید، همین کار را بکنید. پایگاه‌های داده دهه‌ها برای همین مسئله ساخته و بهینه شده‌اند، پس تا وقتی مجبور نیستید چرخ را از نو اختراع نکنید.

ایندکس‌های تخصصی

علاوه بر روش‌های پایه، ایندکس‌های تخصصی زیادی برای حل مسائل خاص وجود دارد.

  • ایندکس‌های جغرافیایی برای داده‌های مکانی به کار می‌روند. مثلاً برای پیدا کردن نزدیک‌ترین رستوران یا پمپ‌بنزین.
  • پایگاه‌های داده برداری (vector) برای داده‌های با ابعاد بالا کاربرد دارند. مثلاً برای پیدا کردن تصاویر یا اسناد مشابه.
  • ایندکس‌های متن کامل (full-text) برای داده‌های متنی استفاده می‌شوند. مثلاً برای جستجوی اسناد یا توییت‌ها.

بسیاری از پایگاه‌های داده بالغ مثل Postgres از افزونه‌ها پشتیبانی می‌کنند که امکان ساخت ایندکس‌های تخصصی را می‌دهند. برای مثال، Postgres افزونه PostGIS را دارد که ساخت ایندکس مکانی را ممکن می‌کند. اگر پایگاه داده شما چنین امکانی ندارد، باید ایندکس‌ها را در یک سیستم خارجی نگه دارید.

راهکار پیشنهادی ما برای این ایندکس‌های ثانویه، در صورت امکان، ElasticSearch است. ElasticSearch از طریق Lucene از ایندکس متن کامل (جستجو بر اساس متن)، ایندکس مکانی و حتی ایندکس برداری پشتیبانی می‌کند. می‌توانید با Change Data Capture (CDC) آن را برای ایندکس‌گذاری بیشتر پایگاه‌های داده راه بیندازید. در این حالت، خوشه ES تغییرات پایگاه داده را دریافت می‌کند و ایندکس‌های خودش را بر اساس آن‌ها به‌روز می‌کند.

این راهکار بی‌نقص نیست. با CDC یک نقطه شکست جدید و یک منبع تازه تأخیر (latency) اضافه می‌کنید و داده‌ای که از ایندکس جستجو می‌خوانید ممکن است کهنه باشد، هرچند اغلب این مشکل مهمی نیست.

برای کاندیداها خیلی رایج است که ElasticSearch را بدون شناخت محدودیت‌هایش یا بدون توضیح نحوه استفاده، به‌عنوان راه‌حل پیشنهاد بدهند. مطمئن شوید اصول آن را مرور کرده‌اید تا در روز مصاحبه آماده باشید.

پروتکل‌های ارتباطی

پروتکل‌ها بخش مهمی از مهندسی نرم‌افزارند، اما بیشتر مصاحبه‌های طراحی سیستم مدل کامل OSI را پوشش نمی‌دهند. در عوض از شما می‌خواهند درباره پروتکل‌های ارتباطی که در سیستم‌تان به کار می‌برید استدلال کنید. باید دو دسته پروتکل را در نظر بگیرید، داخلی و خارجی.

در داخل سیستم، برای یک برنامه میکروسرویسی معمولی که بیش از ۹۰٪ مسائل طراحی سیستم را تشکیل می‌دهد، HTTP(S) یا gRPC کافی است. موضوع را پیچیده نکنید.

از نظر خارجی، باید به نحوه ارتباط کلاینت‌ها با سیستم فکر کنید. چه کسی ارتباط را شروع می‌کند، ملاحظات تأخیر چیست و چه حجمی از داده باید ارسال شود.

بیشتر سیستم‌ها را می‌توان با ترکیبی از HTTP(S)، SSE یا Long Polling و WebSocket ساخت. مرورگرها و اپلیکیشن‌ها برای کار با این پروتکل‌ها ساخته شده‌اند و استفاده از آن‌ها ساده است. معمولاً هم در مصاحبه‌های طراحی سیستم با کلاینت‌هایی که پروتکل سفارشی و پرکارایی لازم دارند سروکار نداریم.

HTTP(S)

برای APIهای ساده با الگوی درخواست و پاسخ از HTTP(S) استفاده کنید. چون هر درخواست بدون حالت (stateless) است، با قرار دادن API پشت یک load balancer می‌توانید آن را افقی مقیاس دهید. فقط مطمئن شوید سرویس‌هایتان به state کلاینت (مثل session) وابسته نیستند.

Long Polling

اگر می‌خواهید به‌روزرسانی‌های تقریباً بلادرنگ به کلاینت بدهید، به راهی برای دریافت به‌روزرسانی از سرور نیاز دارید. Long Polling برای این کار انتخاب خوبی است و سادگی و مقیاس‌پذیری HTTP را با به‌روزرسانی بلادرنگ WebSocket ترکیب می‌کند.

در Long Polling کلاینت درخواستی به سرور می‌فرستد و سرور آن را باز نگه می‌دارد تا داده جدیدی برای ارسال داشته باشد. بعد از ارسال داده، کلاینت درخواست دیگری می‌فرستد و این چرخه تکرار می‌شود. نکته مهم این است که می‌توانید از load balancer و فایروال معمولی هم استفاده کنید و به زیرساخت خاصی نیاز ندارید.

WebSocket

اگر به ارتباط بلادرنگ و دوطرفه بین کلاینت و سرور نیاز دارید، WebSocket ضروری است. از نظر طراحی سیستم، WebSocket می‌تواند چالش‌برانگیز باشد، چون باید اتصال بین کلاینت و سرور را حفظ کنید. این موضوع برای load balancerها و فایروال‌ها مشکل‌ساز است و نگه داشتن تعداد زیادی اتصال باز هم برای سرور سنگین است.

الگوی رایج در این حالت این است که یک message broker ارتباط بین کلاینت و سرور را مدیریت کند و سرویس‌های بک‌اند هم با همان broker ارتباط بگیرند. به این ترتیب لازم نیست هر سرویس بک‌اند اتصال‌های طولانی با کلاینت‌ها نگه دارد.

SSE

رویدادهای ارسالی از سرور (Server-Sent Events یا SSE) راه خوبی برای ارسال به‌روزرسانی از سرور به کلاینت هستند. SSE شبیه Long Polling است، اما برای ارتباط یک‌طرفه از سرور به کلاینت کارآمدتر است. سرور هر زمان داده جدیدی داشته باشد آن را می‌فرستد و کلاینت لازم نیست مثل Long Polling مدام درخواست جدید بدهد.

این کار با یک اتصال HTTP طولانی‌مدت انجام می‌شود، پس برای حالتی که سرور مرتب داده‌ای برای ارسال دارد مناسب‌تر است. برخلاف WebSocket، SSE فقط برای ارتباط سرور به کلاینت طراحی شده و ارسال پیام از کلاینت به سرور را پشتیبانی نمی‌کند. در عوض، پیاده‌سازی و ادغام آن با زیرساخت HTTP موجود، مثل load balancer و فایروال، ساده‌تر است و مدیریت خاصی نمی‌خواهد.

وضعیت‌داری (statefulness) منبع اصلی پیچیدگی در سیستم‌هاست. هر جا ممکن است، state را به یک message broker یا پایگاه داده بسپارید تا سیستم ساده‌تر شود. به این ترتیب سرویس‌های شما بدون حالت و افقی مقیاس‌پذیر می‌مانند، در حالی که ارتباط stateful با کلاینت‌ها حفظ می‌شود.

امنیت

هنگام طراحی سیستم‌های production، امنیت باید در اولویت باشد. مصاحبه‌های طراحی سیستم کمتر از شما می‌خواهند طراحی را به‌طور دقیق از نظر امنیتی بررسی کنید. اما انتظار دارند در جاهای لازم به امنیت اشاره کنید. یعنی باید آماده باشید درباره ایمن‌سازی سیستم در هر لایه صحبت کنید. رایج‌ترین دغدغه‌های امنیتی این‌ها هستند.

احراز هویت و مجوزدهی

در بسیاری از سیستم‌ها، یک API در اختیار کاربران بیرونی قرار می‌دهید که فقط باید برای کاربران مشخصی قابل‌دسترس باشد. سپردن این کار به API Gateway یا سرویس اختصاصی مثل Auth0 راه خوبی است تا چرخ را از نو اختراع نکنید. ممکن است مصاحبه‌گر جزئیات بیشتری بخواهد، مثلاً نحوه ایمن‌سازی موجودیت‌های خاص. اما اغلب کافی است بگویید «API Gateway احراز هویت و مجوزدهی را انجام می‌دهد».

رمزگذاری

هنگام کار با داده‌های حساس، باید مطمئن شوید از دید دیگران محافظت می‌شوند. هم داده‌های در حال انتقال (in transit) را باید پوشش بدهید، مثلاً با رمزگذاری در سطح پروتکل، و هم داده‌های ذخیره‌شده (at rest)، مثلاً با رمزگذاری ذخیره‌سازی.

HTTPS همان HTTP روی SSL/TLS است که داده را هنگام انتقال رمزگذاری می‌کند و استاندارد ترافیک وب است. gRPC هم به‌صورت پیش‌فرض از SSL/TLS پشتیبانی می‌کند. برای داده‌های ذخیره‌شده، یا از پایگاه داده‌ای استفاده کنید که رمزگذاری را پشتیبانی می‌کند، یا قبل از ذخیره، خودتان داده را رمزگذاری کنید.

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

حفاظت از داده

حفاظت از داده یعنی اطمینان از این‌که داده‌ها در برابر دسترسی، استفاده یا افشای غیرمجاز محافظت می‌شوند. سیستم‌های production اغلب با داده‌هایی سروکار دارند که افشایشان حساس است، اما ممکن است در مسیر مجوزدهی قرار نگیرند. مثلاً داده کاربر ممکن است از طریق یک endpoint مثل createFriendRequest در معرض دید قرار بگیرد.

بسیاری از این نشت‌ها با scraping کردن endpointها کشف می‌شوند. پس داشتن نوعی rate limiting یا throttling ایده خوبی است.

مانیتورینگ

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

مانیتورینگ معمولاً در سه سطح انجام می‌شود و بهتر است نام این سه سطح را بیاورید.

مانیتورینگ زیرساخت

این بخش سلامت و عملکرد زیرساخت را زیر نظر دارد. مواردی مثل مصرف CPU، حافظه، دیسک و شبکه. معمولاً با ابزارهایی مثل Datadog یا New Relic انجام می‌شود. هشدار پر شدن دیسک شاید خود سرویس را از کار نیندازد، اما معمولاً نشانه اصلی مشکلاتی است که باید رفع شوند.

مانیتورینگ سطح سرویس

این بخش سلامت و عملکرد سرویس‌ها را بررسی می‌کند. مواردی مثل تأخیر (latency) درخواست‌ها، نرخ خطا و نرخ گذردهی (throughput). اگر سرویس برای پاسخ دادن زیاد طول بکشد، احتمالاً کاربران روز بدی خواهند داشت. اگر throughput بالا برود، ممکن است به این دلیل باشد که ترافیک بیشتری را پردازش می‌کنید، یا ممکن است سیستم رفتار نامطلوبی داشته باشد.

مانیتورینگ سطح اپلیکیشن

این بخش سلامت و عملکرد خود اپلیکیشن را بررسی می‌کند. مواردی مثل تعداد کاربران، تعداد sessionهای فعال و تعداد اتصال‌های فعال. شاخص‌های کلیدی کسب‌وکار هم می‌توانند در این سطح قرار بگیرند. معمولاً با ابزارهایی مثل Google Analytics یا Mixpanel انجام می‌شود و اغلب مهم‌ترین سطح مانیتورینگ در مصاحبه‌های طراحی محصول است.