برنامه‌نویسی

Cache چیست؟

cache چیست؟

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

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

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

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

اگر دقت کرده‌ باشید این تکنیک در اکثر فناوری‌های مدرن به کار گرفته شده است. ما تصاویر را در مرورگر خود Cache می‌کنیم تا بلافاصله آن‌ها را در بازدید مجدد مشاهده کنیم. ما یک آبجکت json از داده‌های کاربر را در کتابخانه‌ای مرتبط با مدیریت stateها (state management) ذخیره می‌کنیم، به این صورت دیگر مجبور نیستیم هر بار برای نمایش اطلاعات کاربر درخواستی به سرور ارسال کنیم. ما حتی می‌توانیم تمام برنامه‌ی وب را در مرورگر Cache کنیم تا کاربران بدون اتصال به اینترنت، فقط با یک بار بارگیری برنامه به آن دسترسی داشته باشند. به اصطلاح به این برنامه‌ها PWA (Progress Web Application) می‌گوییم.

پس چرا همه چیز را برای همیشه Cache نمی‌کنیم؟

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

دانستن اینکه چه چیزی را باید Cache کنیم و برای چه مدت آن را نگه داریم، یکی از مشکل‌هایی است که شما را ملزم می‌کند دلیل Cache کردن هر یک از داده‌ها را در نظر بگیرید و به این فکر کنید که اهمیت نمایش فوری تغییرها تا چه اندازه مهم است. ما در ادامه مثال‌هایی را بررسی خواهیم کرد که در میان آن‌ها نکته‌هایی مرتبط با Cache کردن داده‌ها وجود دارد.

انواع Cache

به عنوان یک توسعه‌دهنده‌ی فرانت‌اند با پیشرفت در مسیر خود با انواع Cache روبرو خواهید شد.

JavaScript Cache

اولین موردی که در کدهای خود با آن روبرو هستید و معمولا خودتان آن را ایجاد می‌کنید، Cache کردن داده‌ها با استفاده از زبان JavaScript است. این یکی از روش‌هایی است که می‌توانید از طریق آن داده‌های دریافت شده از API را در حافظه‌ی سیستم کاربر نگهداری کنید.

پیاده سازی ساده Cache بدون invalidation می‌تواند به صورت زیر باشد:

let cache = {};
async function getCachedValue(key, callback) {
  if (cache.hasOwnProperty(key)) {
    return cache[key];
  }
  const result = await callback();
  cache[key] = result;
  return result;
}

ما در اینجا یک آبجکت با نام Cache از نوع global داریم که با اجرای این فانکشن داده را Cache می‌کند. در قسمت اول بررسی می‌کنیم آیا Cache دارای key است یا خیر، در صورت وجود key به سادگی مقدار Cache را return می‌کنیم و اگر اینگونه نباشد فانکشن callback را اجرا می‌کنیم تا داده را دریافت و آن را Cache کنیم و سپس داده را به کاربر return کنیم.

استفاده از فانکشن بالا به این صورت است که key را در آرگومان‌های ورودی فانکشن قرار می‌دهیم و callback هم به صورت asynchronous داده‌ها را fetch می‌کند.

const user = getCachedValue("user", async () => {
  const res = await fetch("/api/user");
  return res.json();
});

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

تعداد زیادی کتابخانه وجود دارد که در این امر به شما کمک می‌کنند. در React می‌توانید از SWR و react-query استفاده کنید که علاوه بر پیاده‌سازی عالی Cache به شما ویژگی‌های اضافی دیگری نیز ارائه می‌دهند.

HTTP cache

Cache کردن یکی از اساسی‌ترین ویژگی‌های مرورگرهای وب است که برای دهه‌ها وجود داشته است به همین دلیل این قابلیت در پروتکل اصلی انتقال داده‌ها از سرور به کاربران یعنی HTTP وجود دارد و یک header مخصوص به خود در هر response نیز دارد که سرور به کمک آن می‌تواند به مرورگر دستور دهد تا فایل‌های خاصی را برای مدت زمان مشخصی ذخیره کند. شما با تحقیق کردن درباره‌ی Cache-Control می‌توانید اطلاعات بیشتری از این header کسب کنید.

احتمالا اصطلاح پاک کردن Cache را به عنوان راهی برای رفع اشکال‌های عجیب و غریب در وبسایت‌ها شنیده‌اید، HTTP Cache نوع مدنظر آن‌ها بوده است.

ذخیره‌ی داده‌ها از طریق HTTP یکی از خارق‌العاده‌‌ترین روش‌ها برای بهبود سایت است. با افزودن cache headerها و شاید ایجاد فایل‌های منحصربه‌فرد برای همه‌ی داده‌های استاتیک می‌توانید منابع را به صورت نامحدود در سمت کاربر ذخیره کنید و تا زمانی که کاربر Cache را از سیستم خود پاک نکند، داده‌های شما ذخیره خواهند ماند. حتی اگر این قابلیت با دقت پیاده‌سازی شود می‌توانید داده‌های پویا را نیز Cache کنید. اگر دوست دارید عمیقا به تکنیک‌های HTTP Cache بپردازید می‌توانید از مستندات MDN در این زمینه استفاده کنید.

Service worker cache

برخی اوقات شما به قدرت HTTP Cache در کنار JavaScript نیاز پیدا می‌کنید. اینجاست که Service Workerها به شما کمک می‌کنند. Service workerها به شما امکان می‌دهند که تمام داده‌ها را به صورت local اما با داشتن کنترل کامل Cache کنید، مثلا می‌توانید تعریف کنید که چه موقع و برای چه مدت داده‌ها Cache شوند.

Service Workerها به عنوان واسطه‌ای برای کلیه‌ی درخواست‌های شبکه عمل می‌کنند. مثلا هر زمان که برنامه‌ی وب شما داده‌ای مانند یک تصویر را درخواست می‌کند، به کمک Service Worker می‌توانید نسخه‌ی Cache شده را به کاربر برگردانید و همه‌ی این‌ها در حالی اتفاق می‌افتد که نسخه‌ی به‌روز شده سایت را در پس زمینه دریافت کرده‌اید. به کمک یک فایل manifest ساده، Service Workerها به شما امکان می‌دهند پس از بازدید سایت، تجربه‌ی کاملی از حالت آفلاین بر روی آن وبسایت داشته باشید و این یک ویژگی فوق‌العاده ارزشمند است.

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

خوشبختانه ابزارهایی مانند Google workbox وجود دارند که شما کمک می‌کنند Service Worker Cacheهایی بسازید که از قبل آماده و پیکربندی شده‌اند.

Backend cache

آخرین قطعه‌ی پازل از Caching ارتباطی با فرانت‌اند ندارد و در سرور برنامه انجام می‌شود. اما چرا ما به Caching در بک‌اند نیاز داریم؟ سرورها معمولا از منابع و پایداری شبکه‌ی بسیار بیشتری نسبت به کاربران برخوردار هستند، پس چه نیازی به Cache کردن داده‌ها است؟

در سرور داده‌ها از سرویس‌های دیگری نیز دریافت می‌شوند، برای مثال یک دیتابیس را در نظر بگیرید. جستجو برای یک درخواست در رکوردهای یک دیتابیس بزرگ ممکن است چند ثانیه زمان لازم داشته باشد. به‌جای اینکه این کار را بارها و بارها انجام دهید، می‌توانید در بک‌اند این داده‌ها را برای مدت کوتاهی ذخیره کنید. همچنین Cache کردن داده‌هایی که از سایر سرویس‌های خارجی دریافت می‌کنیم می‌تواند مزیت‌های بسیار زیادی برای ما داشته باشد.

در سرور مفهوم distributed cache وجود دارد که کاملا مسئله‌ای پیچیده است. از آنجا که احتمالا بیش از یک سرور در زیرساخت برنامه‌ی ما در حال اجرا است و هر درخواست به یکی از آن سرورها هدایت می‌شود باید یک Cache مشترک میان سرورها وجود داشته باشد. پیاده‌سازی این سیستم با ابزارهای موجود نیز آسان‌تر شده است اما هنوز هم برای بسیاری از موارد موانعی وجود دارد.

پاک کردن داده‌های Cache شده

برخی اوقات تصمیم می‌گیرید که دیگر چیزی Cache نشود. این امر به طور معمول سه دلیل دارد:

  1. به ندرت از داده‌ها استفاده می‌شود.
  2. داده‌ها قدیمی هستند.
  3. داده‌ها تغییر کرده‌اند.

به ندرت از داده‌ها استفاده می‌شود

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

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

داده‌ها قدیمی هستند

روش دیگری برای کنترل فضای درگیر شده توسط Cache وجود دارد، ضمن اطمینان از جدید بودن داده‌ها می‌توانید داده‌های قدیمی را حذف کنید. ممکن است بخواهید تصاویر را مدت زمان بیشتری نسبت به داده‌های کاربر ذخیره کنید زیرا تصاویر به ندرت تغییر می‌کنند اما شاید در برخی موارد نیاز شود نسخه‌ی جدیدی از تصویر را قرار دهید.

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

داده‌ها تغییر کرده‌اند

Cache invalidation تکنیکی است که می‌توانید مجموعه‌ای از داده‌های Cache شده را حذف کنید. معمولا از این تکنیک برای به‌روزرسانی داده‌های Cache شده و نمایش نسخه‌ی جدید برنامه استفاده می‌شود.

بسته به اینکه فایل‌های خود را چگونه Cache می‌کنید، راه‌های مختلفی برای انجام این کار نیز وجود دارد. اگر از زبان برنامه‌نویسی مانند JavaScript استفاده می‌کنید می‌توانید به راحتی Cache را پاک کرده و در پس زمینه داده‌های جدید را دریافت کنید.

جمع‌بندی

Cache کردن داده‌ها بسیار سخت است زیرا روش‌ها و موارد مختلفی وجود دارد که باید به آن‌ها توجه داشته باشید. ما در این مقاله توضیحاتی در این باره به شما ارائه دادیم، مثلا می‌توانید داده‌ها را در برنامه‌ی خود از طریق HTTP یا Service Workerها یا حتی در بک‌اند، Cache کنید. پس انتخاب هر کدام از این روش‌ها به خود شما بستگی دارد.

منبع: https://blog.logrocket.com/what-is-a-cache