Ninja Learn | نینجا لرن
前往频道在 Telegram
یادگیری برنامه نویسی به سبک نینجا 🥷 اینجا چیزایی یاد میگیری که فقط نینجاهای وب بلدن 🤫 👥 ɢʀᴏᴜᴘ: https://t.me/+td1EcO_YfSphNTlk
显示更多1 046
订阅者
-124 小时
-27 天
-230 天
正在加载数据
相似频道
标签云
进出提及
---
---
---
---
---
---
吸引订阅者
十月 '2610月 '26
十月 '26
+3
在0个频道中
九月 '260
在0个频道中
Get PRO
八月 '260
在0个频道中
Get PRO
七月 '260
在0个频道中
Get PRO
六月 '260
在0个频道中
Get PRO
五月 '260
在0个频道中
Get PRO
四月 '260
在0个频道中
Get PRO
三月 '260
在0个频道中
Get PRO
二月 '260
在1个频道中
Get PRO
一月 '26
+8
在0个频道中
Get PRO
十二月 '25
+16
在0个频道中
Get PRO
十一月 '25
+20
在1个频道中
Get PRO
十月 '25
+47
在3个频道中
Get PRO
九月 '25
+41
在2个频道中
Get PRO
八月 '25
+54
在2个频道中
Get PRO
七月 '25
+64
在3个频道中
Get PRO
六月 '25
+31
在0个频道中
Get PRO
五月 '25
+87
在0个频道中
Get PRO
四月 '25
+56
在2个频道中
Get PRO
三月 '25
+131
在4个频道中
Get PRO
二月 '25
+78
在1个频道中
Get PRO
一月 '25
+240
在5个频道中
Get PRO
十二月 '24
+70
在2个频道中
Get PRO
十一月 '24
+54
在1个频道中
Get PRO
十月 '24
+113
在3个频道中
Get PRO
九月 '24
+634
在4个频道中
| 日期 | 订阅者增长 | 提及 | 频道 | |
| 18 十月 | 0 | |||
| 17 十月 | +1 | |||
| 16 十月 | 0 | |||
| 15 十月 | 0 | |||
| 14 十月 | +1 |
频道帖子
| 2 | 没有文字... | 218 |
| 3 | ای شرقی غمگین بازم خورشید درامد | 398 |
| 4 | WSGI vs ASGI: دو مدل ارتباط بین Web Server و Application 🌐
وقتی یه Request به یه Application میرسه، معمولاً Web Server مستقیماً با کد اصلی Application صحبت نمیکنه. بین این دو، یه Interface قرار میگیره که مشخص میکنه Requestها چطور دریافت، پردازش و Responseها چطور برگردونده بشن.
دو تا از معروفترین استانداردها توی اکوسیستم پایتون، WSGI و ASGI هستن.
WSGI چیه؟ 🧠
WSGI یه استاندارد برای ارتباط بین Web Server و Application هست که برای مدل سنتی Web Applicationها طراحی شد. توی این مدل، هر Request به Application داده میشه و Application باید تا آماده شدن Response، پردازش مربوط به اون Request رو انجام بده.
این مدل برای خیلی از Applicationهای معمولی کاملاً مناسب بود، چون بیشتر درخواستها شامل پردازش کوتاه و چند عملیات ساده مثل خوندن از Database بودن. اما با رشد Applicationهای Real-time و سرویسهایی که تعداد زیادی Connection همزمان دارن، محدودیتهای این مدل بیشتر مشخص شد.
ASGI چیه؟ ⚡️
ASGI نسخهی جدیدتری از این ایده هست که برای نیازهای مدرنتر طراحی شده. برخلاف WSGI که بیشتر روی مدل سادهی Request/Response تمرکز داشت، ASGI امکان استفاده از مدلهای Asynchronous و Connectionهای طولانی مثل WebSocket رو هم فراهم میکنه.
توی این مدل، Application میتونه موقع انتظار برای عملیاتهایی مثل Network یا I/O، اجرای خودش رو متوقف کنه و اجازه بده کارهای دیگه هم انجام بشن.
تفاوت اصلی WSGI و ASGI چیه؟ ⚖️
تفاوت اصلی این دوتا توی مدل اجرای Requestهاست.
WSGI برای اجرای Synchronous طراحی شده؛ یعنی هر Request معمولاً یه مسیر مشخص رو طی میکنه و تا زمانی که پردازش اون کامل نشه، نتیجه برنمیگرده.
اما ASGI برای محیطهایی ساخته شده که تعداد زیادی عملیات همزمان و انتظارهای طولانی وجود داره. با استفاده از Async، برنامه میتونه منابع رو بهتر مدیریت کنه و مواقعی که منتظر پاسخ یه عملیات I/O هست، بلاک نشه.
به همین دلیل ASGI بیشتر برای سیستمهایی مناسبتره که با Connectionهای زیاد، WebSocket یا عملیاتهای I/O-heavy سروکار دارن.
حالا ASGI همیشه بهتره؟ 🤔
نه. Async بودن به معنی سریعتر بودن همهی برنامهها نیست. اگه یه Application بیشتر درگیر پردازشهای سنگین CPU باشه، ASGI به تنهایی مشکل خاصی رو حل نمیکنه.
مزیت اصلی ASGI زمانی مشخص میشه که برنامه بیشتر زمان خودش رو صرف انتظار برای منابع خارجی مثل Database، APIهای دیگه یا Network میکنه.
WSGI و ASGI در Python 🐍
تو اکوسیستم Python این دو استاندارد خیلی معروف شدن. فریمورک هایی مثل Django، Flask و FastAPI بسته به نیاز میتونن با یکی از این مدلها اجرا بشن.
مثلاً FastAPI معمولاً با ASGI Serverهایی مثل Uvicorn استفاده میشه و Django هم توی نسخههای جدیدتر پشتیبانی از ASGI رو اضافه کرده.
اما خود مفهوم WSGI و ASGI فقط مخصوص یه Framework خاص نیست؛ این ها استانداردهایی برای نحوهی ارتباط Server و Application هستن.
جمعبندی ✍️
WSGI برای نسل قدیمیتر Web Applicationها ساخته شد؛ جایی که مدل اصلی ارتباط، Request و Response ساده بود.
ASGI برای دنیایی طراحی شد که Applicationها باید Connectionهای بیشتر، عملیاتهای همزمان و ارتباطات Real-time رو مدیریت کنن.
تفاوت اصلی این دو در اینه که WSGI روی مدل Synchronous تمرکز داره، ولی ASGI امکان استفاده از مدل Asynchronous و Event-driven رو فراهم میکنه.
#️⃣ #programming #backend #python
➖➖➖➖➖➖➖➖➖➖
🌙 CHANNEL | GROUP | 389 |
| 5 | son💔💔💔💔 | 421 |
| 6 | 没有文字... | 430 |
| 7 | ایول | 394 |
| 8 | 🧠 حافظه توی کامپیوتر چیه و چجوری کار میکنه؟
میرسیم به یکی از مهم ترین مباحث علوم کامپیوتر!
اول باید انواع حافظه رو بدونیم.
📦 انواع حافظه در کامپیوتر
- حافظه کش سی پی یو
- رجیستر
- رم
- حافظه دائمی (HDD, SSD)
⚡ کش
یه حافظه کوچیک در حد چند مگابایت در کنار سی پی یو هست و سی پی یو بهش دسترسی داره و روی عملکرد سی پی یو خیلی تاثیر گذاره.
🎯 رجیستر
واحد های بسیار کوچیک داخل خود سی پی یو هست که میتونه اطلاعات رو نگه داره و وحشتناک هم سریعه، نقشش صرفا نگهداری اطلاعات نیست و عملا سی پی یو با این رجیستر ها کار میکنه.
📌 رم
مهم ترین و اصلی ترین حافظه ای که یه برنامه نویس باهاش کار داره.
رم در ساده ترین حالت یه قطعه الکترونیکی هست که مقدار محدودی اطلاعات رو به صورت موقت نگه داری میکنه.
کاربردش چیه؟ 🧐
سرعت بالای رم این اجازه رو میده که سیستم مجبور نباشه هر بار اطلاعات رو از یه درایو دائمی دریافت کنه که سرعت به مراتب پایین تری داره و عملکرد رو مختل میکنه.
و اجازه میده برنامه ها داخلش ذخیره بشن تا سی پی یو اونارو اجرا کنه.
🐢 شما تصور کنید یکی از برنامه های سیستم که اهمیت زیادی داره مجبور بود هر سری اطلاعات رو از درایو دریافت کنه.
در این صورت سیستم شما بسیار کند میشد.
🧩 تقسیمبندی نرمافزاری رم
خود رم از لحاظ نرم افزاری به دو بخش تقسیم میشه:
هیپ و استک
چرا میگیم «از لحاظ نرم افزاری»؟
چون از لحاظ سخت افزاری چیزی تحت عنوان هیپ و استک در هنگام ساخت رم داخل کارخونه براش تعریف نشده و این دو بخش توسط سیستم عامل شما فرض شده و تقسیم بندیش انجام شده.
به همین دلیل، اندازه استک میتونه تو سیستم عامل های مختلف فرق کنه اما عموما یه مقدار استاندارد تعریف میشه.
🔍 رم چجوری کار میکنه؟
ببینید، 🧊 رم کامپیوتر مثل یه قالب یخ به تعداد زیادی خونه تقسیم شده
هر کدوم از این خونه ها ۸ بیت جا دارن
بیت چیه؟
بیت همون صفر و یک خودمونه.
یه خونه حافظه میتونه ۸ تا از اینا نگه داری کنه
داخل هر خونه حافظه، نوع قرارگیری صفر و یک در کنار هم، مقدار ذخیره شده داخلش رو نشون میده.
یعنی چی؟
شما فرض کنید: 01100111
این چیدمان به ما ممکنه عدد ۸ رو بده
یا این چیدمان: 10111011 ممکنه حرف N رو بده ما
🖥️ توی کامپیوتر شما هیچ وقت مستقیم با بیت ها کار نمیکنید
تقریبا همیشه با بایت ها کار میکنید یعنی یک خونه حافظه
هر بایت یه آدرس داره مثل:
0x0001
به صورت hex code هست این آدرس.
🎯 و هر زمان که شما به آدرس یه خونه حافظه دسترسی داشته باشید، به خود اون خونه هم دسترسی دارید.
🧱 ساختارهای داده در حافظه
شما میتونید با خونه های حافظه ساختار های داده مختلف پیاده کنید
مثلا اگه تعدادی از خونه های حافظه رو به هم دیگه وصل کنید میشه آرایه!
لازم نیست این خونه ها کنار هم باشن اما معمولا کنار هم هستن.
صرفا کرنل شما و زبان برنامه نویسی شما این مورد رو برای شما هندل میکنن.
مثلا میتونید بگید هر عضو آرایه از ۱۰ بایت تشکیل شده
یعنی هر عضو ۱۰ تا خونه حافظه رو اشغال میکنه.
و هر خونه حافظه هم خودش ۸ تا بیت داره و میتونه با چیدمان این صفر یک ها، یا عدد ذخیره کنه یا حرف یا ...
حالا اگر بخواید آرایه ۲۰ تا عضو داشته باشه
یعنی مجموعا چقدر از حافظه اشغال میشه؟
20 × 10 = 200
مجموعا ۲۰۰ بایت
🔗 ساختار های داده تو حافظه مثلا آرایه، شبیه یک شی واحد نیست که بشه بهش دسترسی داشت
بیشتر مثل یه زنجیر عمل میکنه و به هم دیگه وصله
سوال: اگه یه شی نیست، پس چجوری بهش دسترسی پیدا میکنیم؟
سوال خوبیه.
معمولا اولین خونه حافظه برای اشاره به کل یه آرایه به کار میره.
یعنی اگر یه آرایه ۵ تا عضو داره:
a, b, c, d, e
ما به a اشاره میکنیم اما میتونیم به کل آرایه هم دسترسی داشته باشیم.
زبان های برنامه نویسی خودشون اکثرا این رو هندل میکنن
اما بعضی زبان ها باید خودتون این کار رو بکنید
مثل C که با pointer arithmetic انجام میشه.
✅ جمعبندی
فعلا تا همین جا کافیه :)
پست بعدی در مورد هیپ و استک و مشکلات و قوانین مموری خواهد بود.
- Silox | 388 |
| 9 | جیگر اونی که استار میزنه رو باید خورد | 337 |
| 10 | یادش بخیر دوران رعیسی چه پستایی میذاشتیم | 424 |
| 11 | خیلی دوست دارم خودمم بک بزنم منتهی انگیزش نیست | 449 |
| 12 | Circuit Breaker چطور جلوی Chain Failure رو میگیره؟ 🤔
توی یه سیستم ساده، اگه یه سرویس Down بشه، معمولاً فقط همون سرویس دچار مشکل میشه. اما توی یه سیستم توزیع شده و بزرگ که چندین سرویس به هم وابستهان، قضیه میتونه خیلی سریع پیچیده بشه.
فرض کنین Service A برای انجام یه Request به Service B نیاز داره و Service B هم به Service C وابسته است. حالا اگه Service C دچار مشکل بشه، Requestهای Service B شروع به شکست خوردن میکنن و این شکستها میتونن به Service A هم منتقل بشن.
اگه Service A همچنان به Service B درخواست بفرسته و منتظر Timeout بمونه، کمکم Connectionها و منابعش هم درگیر میشن و ممکنه در نهایت خود Service A هم از کار بیفته.
اینجاست که Circuit Breaker وارد میشه.
Circuit Breaker دقیقاً چیه؟ 🧠
Circuit Breaker یه الگوی طراحی برای جلوگیری از ادامه پیدا کردن درخواستها به یه سرویس خراب یا غیرقابل دسترسه. ایدهی اصلیش شبیه Circuit Breakerهای برق هست. وقتی سیستم تشخیص بده تعداد زیادی از درخواستها دارن شکست میخورن، به جای اینکه همچنان درخواستهای جدید رو ارسال کنه، مسیر ارتباط رو موقتاً قطع میکنه.
توی این حالت Requestها دیگه به سرویس مشکلدار ارسال نمیشن و Application میتونه سریعتر یه Error یا Fallback برگردونه. این کار باعث میشه یه Failure محدود، به Failure بزرگتری در کل سیستم تبدیل نشه.
Closed State 🔵
در حالت عادی، Circuit در وضعیت Closed قرار داره. توی این حالت Requestها مثل همیشه به سرویس مقصد ارسال میشن و Circuit Breaker نتیجهی اونها رو بررسی میکنه.
اگه Requestها موفق باشن، اتفاق خاصی نمیفته. اما اگه تعداد خطاها یا Timeoutها از یه Threshold مشخص بیشتر بشه، Circuit Breaker متوجه میشه که احتمالاً سرویس مقصد دچار مشکل شده و Circuit رو باز میکنه.
Open State 🔴
وقتی Circuit وارد حالت Open میشه، Requestهای جدید دیگه به سرویس مقصد ارسال نمیشن. به جای اینکه Application هر بار یه Connection ایجاد کنه، منتظر Timeout بمونه و دوباره شکست بخوره، Circuit Breaker خیلی سریع Request رو Fail میکنه.
این موضوع هم از ارسال Requestهای اضافی جلوگیری میکنه و هم باعث میشه منابع Application برای مدت طولانی درگیر سرویس خراب نشن. در همین مدت، سرویس مقصد هم فرصت پیدا میکنه بدون دریافت حجم زیادی از Requestهای جدید، Recovery کنه.
Half-Open State 🟡
اما Circuit نمیتونه برای همیشه Open باقی بمونه. بعد از گذشت یه مدت مشخص، Circuit وارد وضعیت Half-Open میشه تا بررسی کنه سرویس مقصد دوباره سالم شده یا نه. توی این حالت معمولاً تعداد محدودی Request اجازه پیدا میکنن به سرویس مقصد ارسال بشن.
اگه این Requestها موفق باشن، Circuit دوباره به حالت Closed برمیگرده و ارتباط عادی ادامه پیدا میکنه. اما اگه دوباره Failure اتفاق بیفته، Circuit دوباره Open میشه و مدتی دیگه Requestها رو متوقف میکنه.
Circuit Breaker و Timeout چه فرقی دارن؟ ⏱️
Timeout فقط مشخص میکنه Application تا چه مدت برای دریافت جواب یه Request صبر کنه. اما Circuit Breaker یه قدم جلوتر میره.
اگه یه سرویس مرتب Timeout بشه، بدون Circuit Breaker همچنان Requestهای جدید ارسال میشن و هرکدوم ممکنه تا زمان Timeout منابع Application رو درگیر کنن.
Circuit Breaker بعد از تشخیص این الگوی شکست، جلوی Requestهای جدید رو میگیره و اجازه نمیده منابع سیستم به خاطر یه سرویس خراب بیدلیل مصرف بشن.
Fallback همیشه جواب نیست 💡
وقتی Circuit باز میشه، Application معمولاً باید یه رفتار جایگزین داشته باشه. مثلاً ممکنه به جای دریافت اطلاعات از سرویس اصلی، دادهی Cache شده رو برگردونه یا یه جواب سادهتر به کاربر بده.
اما Fallback نباید فقط برای مخفی کردن Error استفاده بشه. اگه Fallback خودش وابسته به یه سرویس خراب دیگه باشه، ممکنه مشکل فقط از یه سرویس به سرویس دیگه منتقل بشه. پس باید دقت کنیم مسیر جایگزین واقعاً مستقل و قابل استفاده باشه.
جمعبندی ✍️
Circuit Breaker قرار نیست یه سرویس خراب رو درست کنه. کاری که انجام میده اینه که Failure رو محدود میکنه و نمیذاره مشکل یه سرویس به بخشهای دیگهی سیستم سرایت کنه.
با سه وضعیت اصلی Closed، Open و Half-Open، تشخیص میده چه زمانی درخواستها عادی باشن، چه زمانی متوقف بشن و چه زمانی دوباره سلامت سرویس رو بررسی کنه.
#️⃣ #system_design #backend #programming
➖➖➖➖➖➖➖➖➖➖
🌙 CHANNEL | GROUP | 437 |
| 13 | یا اتفاقی نهنگ آبی بازی نکنم | 408 |
| 14 | از نظر روحی به دوره ای نیاز دارم که نگرانیم این بود مو مو بهم پیام نده | 465 |
| 15 | نگاهی به روش های مختلف Cache invalidation
Cache یکی از رایجترین راهکارا برای افزایش Performance توی سیستمهاست. به جای اینکه برای هر Request مستقیم به Database مراجعه کنیم، دادههایی که زیاد استفاده میشن رو توی یک لایهی سریعتر نگهداری میکنیم. این کار باعث میشه تعداد Queryها کمتر بشه، Latency کاهش پیدا کنه و فشار روی Database پایین بیاد. اما یک مشکل مهم وجود داره:
اگه دادهی اصلی تغییر کنه، چه اتفاقی برای نسخهای که داخل Cache داریم میفته؟
فرض کنیم اطلاعات یه کاربر داخل Cache ذخیره شده. حالا کاربر اسم خودش رو تغییر میده و این تغییر داخل Database ثبت میشه. اما اگه مقدار قدیمی هنوز داخل Cache وجود داشته باشه، درخواستهای بعدی ممکنه همون دادهی قدیمی رو دریافت کنن.
اینجاست که مفهوم Cache Invalidation اهمیت پیدا میکنه.
Cache Invalidation دقیقاً یعنی چی؟ 🧠
Cache Invalidation یعنی مدیریت منقضی شدن یا حذف دادههایی که دیگه معتبر نیستند. به زبان ساده، وقتی دادهی اصلی تغییر میکنه، باید یه تصمیمی بگیریم:
باید Cache رو حذف کنیم؟ یا مقدار جدید رو داخل Cache قرار بدیم؟ یا اجازه بدیم بعد از مدتی خودش منقضی بشه؟
این تصمیم یکی از چالشهای مهم طراحی سیستمهاست. چون Cache و Database معمولاً دو منبع جدا از هم هستن و همیشه باید بین سرعت بالا و Consistency تعادل ایجاد کنیم.
روش اول: Cache Aside (Lazy Loading) 📦
یکی از رایجترین روشها، Cache Aside هست. تو این مدل، Application خودش مسئول مدیریت Cache و Database هست. وقتی یه داده درخواست میشه، اول Cache بررسی میشه. اگه داده وجود داشته باشه، همون مقدار برگردونده میشه. اگه Cache Miss اتفاق بیفته، Application داده رو از Database میخونه، داخل Cache قرار میده و بعد جواب رو برمیگردونه.
اما بخش مهم این روش، زمان نوشتن هست. وقتی داده تغییر میکنه، معمولاً Application اول تغییر رو توی Database ذخیره میکنه و بعد مقدار مربوطه رو از Cache حذف میکنه. با این کار، درخواست بعدی مجبور میشه دادهی جدید رو از Database بخونه و دوباره Cache رو پر کنه. مزیت این روش سادگی و کنترل خوب روی Cache هست. به همین دلیل یکی از رایجترین الگوها توی سیستمهای واقعی محسوب میشه.
روش دوم: TTL (Time To Live) ⏳
یکی از سادهترین روشها برای مدیریت Cache، تعیین یک زمان انقضا برای دادههاست. هر داده ای فقط تا زمان مشخصی معتبره. بعد از تموم شدن این زمان، داده حذف میشه و درخواست بعدی مقدار جدید رو دریافت میکنه.
مزیت TTL اینه که نیاز نداریم تمام تغییرات Database رو دنبال کنیم. اما مشکلش اینه که ممکنه داده قبل از منقضی شدن، تغییر کرده باشه. یعنی تا زمانی که TTL تمام نشده، کاربرا ممکنه مقدار قدیمی رو ببینن. به همین دلیل TTL بیشتر برای دادههایی مناسبه که تغییراتشون حساس نیست یا Stale بودن کوتاهمدت براشون قابل قبوله.
روش سوم: Write Through 🔄
توی Write Through، موقع تغییر داده، Application همزمان Cache و Database رو بهروز میکنه.
یعنی هر Write باید در هر دو مکان انجام بشه.
مزیت این روش اینه که Cache همیشه مقدار جدید رو داره و احتمال Stale Data کمتر میشه. اما هزینهی بیشتری داره، چون هر تغییر باید چند عملیات مختلف انجام بده. همچنین اگه یکی از این عملیاتها شکست بخوره، باید مکانیزمی برای هماهنگ کردن دوبارهی دادهها وجود داشته باشه.
روش چهارم: Event-Based Invalidation 📡
تو سیستمهای بزرگتر، گاهی سرویسها از Event استفاده میکنن. یعنی وقتی تغییری داخل Database اتفاق میوفته، یه Event منتشر میشه. سرویسهای دیگه این Event رو دریافت میکنن و Cache مربوط به اون داده رو حذف یا بهروز میکنن.
این روش باعث میشه سرویسها وابستگی مستقیم به هم نداشته باشن. اما در عوض، معماری پیچیدهتر میشه و باید مواردی مثل Duplicate Event، ترتیب Eventها و خطاهای احتمالی مدیریت بشن.
پس بهترین روش کدومه؟💡
مثل بیشتر تصمیمهای معماری، یک جواب ثابت وجود نداره.
اگه دادهها زیاد تغییر نمیکنن و کمی قدیمی بودنشون مشکلی ایجاد نمیکنه، TTL میتونه کافی باشه.
اگه Performance و سادگی مهم باشه، Cache Aside معمولاً انتخاب مناسبیه.
اگه Consistency اهمیت زیادی داشته باشه، باید سراغ روشهایی مثل Write Through یا Event-Based Invalidation رفت.
انتخاب روش مناسب به این بستگی داره که سیستم ما بیشتر به چه چیزی نیاز داره:
Performance بیشتر یا دادهی همیشه بهروز؟
جمعبندی ✍️
Cache کردن دادهها بخش سادهی ماجراست. چالش واقعی زمانی شروع میشه که داده تغییر کنه و باید تصمیم بگیریم Cache چه زمانی و چطور بهروز بشه.
#️⃣ #system_design #cache #backend
➖➖➖➖➖➖➖➖➖➖
🌙 CHANNEL | GROUP | 621 |
| 16 | connection Pooling چطور ارتباط با Database رو بهینه میکنه؟ 🤔
وقتی یه درخواست وارد یه Backend Service میشه، معمولاً نیاز داره برای گرفتن یا تغییر دادن دادهها با Database ارتباط برقرار کنه. در نگاه اول شاید ساده به نظر برسه:
درخواست میاد → Connection ساخته میشه → Query اجرا میشه → Connection بسته میشه
اما توی یه سیستم واقعی که صدها یا هزاران درخواست در ثانیه دریافت میکنه، این مدل میتونه تبدیل به یه مشکل بزرگ بشه. چون ساختن یه Database Connection فقط یه عملیات ساده نیست.
برای ایجاد یه اتصال، Client باید مراحلی مثل برقراری ارتباط TCP، احراز هویت و آمادهسازی Session با Database رو انجام بده. اگه برای هر درخواست یه Connection جدید ساخته بشه، بخش زیادی از منابع سیستم صرف ساختن و از بین بردن Connectionها میشه، نه پردازش واقعی Queryها.
اینجاست که مفهومی به اسم Connection Pooling وارد میشه.
Connection Pooling دقیقاً یعنی چی؟ 🧠
Connection Pooling یعنی به جای اینکه برای هر درخواست یه Connection جدید بسازیم، تعدادی Connection از قبل ایجاد کنیم و اونها رو بین درخواستهای مختلف به اشتراک بذاریم. این Connectionها داخل یه Pool نگهداری میشن و هر زمان یه درخواست نیاز به Database داشته باشه، یکی از Connectionهای آزاد Pool رو دریافت میکنه.
بعد از تموم شدن Queryها، Connection بسته نمیشه؛ بلکه دوباره به Pool برمیگرده تا درخواست بعدی بتونه از اون استفاده کنه. در واقع Connection Pool مثل یه لایهی مدیریت بین Application و Database عمل میکنه و چرخهی عمر Connectionها رو کنترل میکنه.
بدون Connection Pool چه اتفاقی میفته؟ ⚠️
فرض کنیم یه API داریم که در هر درخواست یه Connection جدید به PostgreSQL ایجاد میکنه. اگه در یه لحظه 1000 درخواست وارد سیستم بشه، Application ممکنه تلاش کنه 1000 اتصال جداگانه بسازه. اما Database هم محدودیت داره.
هر Connection معمولاً منابعی مثل Memory, Thread, Process, Session State مصرف میکنه. در نتیجه تعداد زیاد Connectionها میتونه باعث بشه Database به جای اجرای Queryها، بیشتر درگیر مدیریت Connectionها بشه.
به همین دلیل داشتن Connection بیشتر همیشه به معنی Performance بهتر نیست.
Connection Pool چطور کار میکنه؟ ⚙️
یه Pool معمولاً با چند مقدار مهم مدیریت میشه.
مثلاً:
Minimum Connections:
حداقل تعداد Connectionهایی که همیشه آماده نگه داشته میشن.
Maximum Connections:
بیشترین تعداد Connectionهایی که Pool اجازه ایجادشون رو میده.
Idle Timeout:
مدتی که یه Connection بدون استفاده میتونه در Pool باقی بمونه.
Connection Lifetime:
حداکثر عمر یه Connection قبل از اینکه دوباره ساخته بشه.
وقتی تعداد درخواستها بیشتر از تعداد Connectionهای آزاد Pool بشه، بسته به تنظیمات سیستم یا درخواست منتظر آزاد شدن یه Connection میمونه یا بعد از یه زمان مشخص خطا دریافت میکنه.
Connection Pool و Database چه رابطهای دارن؟ 🗄
یکی از اشتباهات رایج اینه که فکر کنیم هرچی Pool بزرگتر باشه، سیستم سریعتر میشه. اما Database هم ظرفیت محدودی داره. اگه Application چندین Worker داشته باشه و هر Worker تعداد زیادی Connection باز کنه، ممکنه خیلی سریع تعداد Connectionها از توان Database بیشتر بشه.
برای مثال: یه سرویس با 10 Worker داریم. اگه هر Worker یه Pool با حداکثر 100 Connection داشته باشه، در بدترین حالت ممکنه 1000 Connection به Database ارسال بشه. در حالی که شاید Database برای چنین تعداد Connectionهایی طراحی نشده باشه.
به همین دلیل اندازهی Pool باید با توجه به ظرفیت Database، نوع Queryها و حجم Traffic تنظیم بشه.
Connection Pooling چه مشکلی رو حل میکنه؟ 🤔
Connection Pooling باعث میشه هزینه ساخت Connection های تکراری کم بشه، Database کمتر درگیر مدیریت Connection ها بشه، Latency درخواست ها کمتر باشن و در نهایت منابع سیستم بهتر استفاده بشن.
اما در کنارش باید درست تنظیم بشه. یه Pool خیلی کوچک باعث میشه Requestها منتظر Connection بمونن و یه Pool خیلی بزرگ، میتونه Database رو تحت فشار قرار بده.
جمعبندی ✍️
Connection Pooling یکی از بخشهای مهم طراحی Backendهای مقیاسپذیره. ایدهی اصلی ساده هست:
به جای ساختن و نابود کردن مداوم Connectionها، اونها رو مدیریت و دوباره استفاده میکنیم.
اما پیادهسازی درستش نیاز به شناخت رفتار Application و Database داره، چون تعداد Connectionهای بیشتر همیشه به معنی Performance بهتر نیست.
#️⃣ #system_design #databsae #backend
➖➖➖➖➖➖➖➖➖➖
🌙 CHANNEL | GROUP | 503 |
| 17 | 没有文字... | 499 |
| 18 | 没有文字... | 514 |
| 19 | Database Replication دقیقاً یعنی چی؟ 🧠
Replication یعنی ایجاد چند نسخه از دادهها روی چند Database Server مختلف. توی این معماری، معمولاً یه Node اصلی داریم که مسئول دریافت تغییرات داده هست و Nodeهای دیگه یک کپی از دادهها رو نگهداری میکنن. هدف اصلی Replication این نیست که فضای بیشتری برای ذخیرهسازی داشته باشیم. هدف اصلی اینه که بتوانیم تعدا Request بیشتری رو مدیریت کنیم و فشار روی Database اصلی رو کم کنیم. به زبان ساده، به جای اینکه همهی کاربرا به یه Database متصل بشن، کار بین چند Database تقسیم میشه.
Primary-Replica Architecture 🔄
یکی از رایجترین مدلهای Replication، معماری Primary-Replica هست. توی این مدل، یک Database به عنوان Primary انتخاب میشه و تمام عملیات های نوشتن(INSERT, UPDATE, DELETE) روی اون انجام میشن. بعد تغییرات ایجاد شده به Replicaها منتقل میشن تا اونا هم نسخه جدیدی از داده هارو داشته باشن. الان میتونیم از Replicaها برای عملیات های Read استفاده کنیم و اونارو به Replicaها ارسال کنیم تا فشار روی Primary کمتر بشه.
Replication چطور دادهها رو منتقل میکنه؟ ⚙️
برای انتقال تغییرات، Database معمولاً تغییرات انجام شده رو توی یه Log ثبت میکنه. تو PostgreSQL، این کار با استفاده از WAL (Write-Ahead Log) انجام میشه. قبل از اینکه تغییرات اصلی روی Data Fileها ذخیره بشن، اطلاعات داخل WAL ثبت میشه.
Replicaها این Logها رو دریافت میکنن و با اجرای دوبارهی اون ها، Database خودشون رو به وضعیت Primary نزدیک میکنن. به همین دلیل Replication معمولاً یک فرآیند Continuous هست که دائماً تغییرات جدید رو دنبال میکنه.
Synchronous و Asynchronous Replication 🔄
یکی از تصمیمهای مهم در طراحی Replication اینه که تغییرات چطور به Replicaها منتقل بشن.
توی Primary, Synchronous Replication قبل از تأیید یه عملیات Write باید مطمئن بشه که Replica هم اون تغییر را دریافت کرده. مزیت این روش اینه که احتمال از دست رفتن داده خیلی کم میشه. اما مشکل اینجاست که سرعت Write کاهش پیدا میکنه، چون Primary باید منتظر Replicaها بمونه.
توی Primary, Asynchronous Replication بعد از ذخیرهی تغییر خودش پاسخ رو برمیگردونه و انتقال تغییرات به Replica تو پسزمینه انجام میشه. این روش Performance بهتری داره، اما ممکنه برای مدت کوتاهی Replicaها دادهی جدید را نداشته باشند. به این فاصله، Replication Lag گفته میشه.
مشکل Replication Lag چیه؟ ⏳
توی معماری Replica، همیشه این احتمال وجود داره که یه Replica کمی عقبتر از Primary باشه.
مثلاً یه کاربر اطلاعات خودش رو تغییر میده. Write روی Primary انجام میشه، اما قبل از اینکه Replica این تغییر رو دریافت کنه، درخواست Read به Replica ارسال میشه. توی این حالت ممکنه کاربر هنوز مقدار قدیمی دادهی خودش رو ببینه. این مشکل یکی از چالشهای مهم سیستمهای توزیع شده هست، چون افزایش Performance معمولاً با هزینهی پیچیدهتر شدن Consistency همراه میشه.
Replication چه مشکلاتی رو حل میکنه؟ 💡
Replication بیشتر برای حل دو مشکل استفاده میشه:
اول، Scaling Readها: وقتی تعداد Readها زیاد باشه، میتونیم اون ها رو بین چند Replica تقسیم کنیم و فشار روی Primary رو کاهش بدیم.
دوم، High Availability: اگر Primary از دسترس خارج بشه، میشه یه Replica رو به عنوان Primary جدید انتخاب کرد تا سرویس ادامه پیدا کنه.
البته این فرآیند معمولاً نیاز به مکانیزمهایی مثل Failover و مدیریت دقیق وضعیت Nodeها داره.
Replication همیشه جواب مناسبیه؟ 🤔
Replication یک راهکار قدرتمند برای افزایش مقیاسپذیری و دسترسپذیریه، اما بدون هزینه نیست.
با اضافه شدن Replicaها، مدیریت سیستم پیچیدهتر میشه و مشکلاتی مثل Replication Lag, انتخاب Primary جدید و Consistency بین Nodeها به سیستم اضافه میشن و باید درست مدیریت بشن.
به همین دلیل Replication بیشتر یه Trade-off هست، نه یi راهحل جادویی برای همهی مشکلات Database.
جمعبندی ✍️
Database Replication یکی از تکنیکهای اصلی برای ساخت سیستمهای مقیاسپذیر و قابل اعتماده. با نگهداری چند نسخه از دادهها، میتونیم فشار Readها رو تقسیم کنیم و در برابر خرابیها مقاومتر باشیم.
اما در کنار این مزایا، باید چالشهایی مثل Consistency و Replication Lag رو هم توی طراحی سیستم در نظر بگیریم.
#️⃣ #system_design #databsae #backend
➖➖➖➖➖➖➖➖➖➖
🌙 CHANNEL | GROUP | 436 |
| 20 | ایران: | 362 |
