استراتژی های Cache – چطوری بهترین استراتژی کش را انتخاب کنم؟

استراتژی های Cache – چطوری بهترین استراتژی کش را انتخاب کنم؟

Cache کردن یکی از ساده ترین راه ها برای افزایش عملکرد سیستم است. دیتابیس ها در خواندن و ارائه ی اطلاعات ممکن است کند باشند (حتی NoSQL ها دوست عزیز!) و همانطور که می دانید، کلید موفقیت در جلب رضایت کاربرها، سرعت است.

Cache چیست؟

🧩 بیایید در ابتدای کار ببینم cache به چه معناست. کلمه ی cache در مقاله ها و مطالب کامپیوتری فارسی زبان با عنوان حافظه ی نهان یا حافظه ی پنهان ترجمه می شود که به نظر می رسد مفهوم بسیار گنگی دارد و قابل درک نیست. این ترجمه (شاید اشتباه) به این دلیل است که ریشه ی کلمه ی cache از زبان فرانسوی آمریکای شمالی می آید که به معنای مکان مخفی شدن است. ولی در علوم کامپیوتر به معنای "حافظه کوتاه مدت کامپیوتر، که در آن اطلاعات برای بازیابی آسان ذخیره می شود." استفاده می شود. این توضیح را دادم تا بگویم با توجه به اینکه مخالف ترجمه ی حافظه ی نهان هستم، در ادامه ی این مقاله، برای درک بهتر از واژه Cache یا کش، استفاده خواهم کرد.

دریافت اطلاعات در سرتاسر وب نیازمند قدرت پردازش و زمان است. داده ها باید از یک سرور به سرور دیگر منتقل شوند. استفاده از Cache این زمان و مصرف منابع را کاهش می دهد.

پاسخ دادن به اینکه Cache چیست بستگی به موضوع مقاله دارد و اینکه در چه لایه ای می خواهیم به این پرسش، پاسخ بدهیم. به طور کلی، Cache راهی برای ذخیره و به یاد آوردن سریع اطلاعات پرکاربرد است.

به تصویر زیر دقت کنید:

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

هرکدام از مراحل Cache شدن نیازمند مقاله و آموزش های مشخصی برای خودش است. ولی در این مقاله قصد داریم استراتژی هایی را برای Cache اطلاعات در آخرین لایه یعنی بین برنامه، سرور و دیتابیس آن مطرح کنیم.

اگر استراتژی مناسبی را انتخاب و به درستی آن را پیاده سازی کرده باشید، Cache کردن اطلاعات می تواند مزایای زیر را برایتان به همراه داشته باشد:

  • زمان پاسخ گویی (Response Time) برنامه ی شما را کاهش می دهد.
  • بار و فشار کاری روی دیتابیس را کم می کند.
  • هزینه های برنامه ی شما را پایین می آورد.

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

  • آیا برنامه ی شما مانند یک سیستم ذخیره ی لاگ مبتی بر زمان، میزان "نوشتن" زیاد است و میزان "خواندن" کم و به ندرت؟
  • آیا اطلاعات در برنامه ی شما مانند یک پروفایل کاربران، یک بار "نوشته" می شود و بارها "خوانده" می شود؟
  • آیا اطلاعاتی که از برنامه ی شما بازگردانده می شود، مانند پرس و جوهای جستجو، هربار منحصر به فرد است؟

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

استراتژی Cache-Aside

این شاید متداول ترین روش Cache کردن باشد. در این روش Cache در سرراه ارتباط برنامه و دیتابیس قرار ندارد و برنامه مستقیماً با Cache و پایگاه داده صحبت می کند.

همانطور که در تصویر بالا می بینید:

  1. برنامه ی شما ابتدا Cache را بررسی می کند.
  2. اگر اطلاعاتی که می خواست در cache وجود داشته باشد، Cache Hit می شود. اطلاعات از cache خوانده شده و برای کلاینت ارسال می شود.
  3. اگر اطلاعات در Cache پیدا نشود، Cache Miss شده است. در نتیجه برنامه باید چند کار اضافه را به ترتیب زیر انجام دهد:
    1. ابتدا Query به سمت دیتابیس می فرستد تا اطلاعات خواسته شده را بخواند.
    2. سپس اطلاعات را برای کاربر ارسال می کند.
    3. اطلاعات گرفته شده از دیتابیس را در cache ذخیره می کند تا درخواست های بعدی cache hit شود.

🧩 از دو عبارت cache hit و cache miss استفاده کردیم که در ادامه ی مقاله هم این دو عبارت را بارها خواهیم دید. Cache hit به معنای این است که اطلاعات خواسته شده از cache در آن وجود داشته است، پس با موفقیت درخواست ما جواب داده می شود. ولی در مقابل cache miss به معنای زمانی است که اطلاعات مورد نیاز ما در cache وجود نداشته است، پس باید برویم سراغ بدست آوردن این اطلاعات از راههای دیگر.

موارد استفاده، مزایا و معایب cache-aside

روش cache اطلاعات به صورت cache-aside، یکی از روش های معمول و همه منظوره در Cache اطلاعات است ولی برای برنامه هایی که بار خواندن اطلاعات در آنها خیلی زیاد است به خوبی کمک می کند. برای این روش معمولا از Memcached و Redis استفاده می شود. 

برنامه هایی که از cache-aside استفاده می کنند در برابر خراب شدن cache مقاوم هستند و آسیبی به عملکرد سیستم وارد نمی شود. اگر تمام cache هایی که در برنامه قرار داده اید خراب شده و از مدار خارج شوند، باز هم برنامه به خوبی کار می کند. زیرا در این ساختار، برنامه می تواند به طور مستقیم با دیتابیس ارتباط برقرار کند. البته وقتی که حجم زیادی از درخواست ها به سمت برنامه ی شما سرازیر شده است، اینکه cache از مدار خارج شود ممکن است در بهترین حالت زمان پاسخگویی برنامه به درخواست ها را زیاد کند و در بدترین حالت هم دیتابیس را از کار بیاندازد.

مزیت دیگر cache-aside این است که می توانیم از دو مدل مختلف برای ذخیره سازی اطلاعات در cache و دیتابیس استفاده کنیم. مثلا می توانیم نتیجه ی یکسری از درخواست های پرتکرار را دقیقا همانطور که میخواهیم به سمت کاربر بفرستیم و براساس مثلا ID خاصی تنظیم شده است، در cache ذخیره کنیم.

وقتی از cache-aside استفاده میکنیم، استراتژی مان در مورد ذخیره ی اطلاعات، نوشتن آنها به صورت مستقیم در دیتابیس است. با این استراتژی، طبیعی است که cache و دیتابیس با هم هماهنگ نیستند. و در صورتی که اطلاعات موجودی در Cache در دیتابیس تغییر کند، کاربر اطلاعات قدیمی تر را مشاهده خواهد کرد. برای برطرف کردن این ایراد، برنامه نویس ها از TTL یا مدت زمان اعتبار برای داده های ذخیره شده در Cache بهره می برند. یعنی تا سر رسیدن آن زمان اطلاعات قدیمی به کاربر نمایش داده می شود و بعد از  آن، اطلاعات از روی Cache حذف شده و در درخواست های بعدی، Cache هم به روز می شود. ولی اگر نیازمندی برنامه ی ما، تضمین به روز و هماهنگ بودن اطلاعات باشد، برنامه نویس های مجبور هستند از استراتژی دیگری استفاده کنند که در همین مقاله توضیح خواهیم داد.

استراتژی Read-Through 

در استراتژی Read-Through، کش طراحی شده در برنامه، با دیتابیس در یک راستا قرار می گیرد. هنگامی که که Cache Miss اتفاق می افتد، اطلاعات مورد نیاز از دیتابیس تامین می شود. بعد از خواندن اطلاعات از دیتابیس، ابتدا اطلاعات خوانده شده در Cache ذخیره می شود و سپس به برنامه می آید.

هر دو استراتژی Cache-aside و Read-through در صورتی که اولین بار بخواهند یک داده ای را بخوانند، کمی کند هستند.

موارد استفاده، مزایا و معایب Read-through

با اینکه read-through و cache-aside خیلی شبیه به هم هستند، ولی دو تفاوت هم وجود دارد:

  1. در cache-aside، برنامه موظف است اطلاعات را از دیتابیس دریافت کرده و در cache بریزد. ولی در read-through، این کار بر عهده کتابخانه ها یا توابع مستقلی هست که توسط سازنده ی cache فراهم شده است.
  2. برخلاف cache-aside، در استراتژی read-through مدل ذخیره ی اطلاعات در cache و دیتابیس نمی توانند دو مدل مختلف باشند.

روش read-through برای زمان هایی که بار خواندن اطلاعات در برنامه ی ما خیلی زیاد است، مناسب است. البته اطلاعاتی که قرار نباشد به ازای درخواست های مختلف به گونه های مختلفی خوانده شود و همانند همان چیزی که در دیتابیس است را بخواهیم به برنامه تحویل بدهیم. برای مثال وقتی قرار است یک خبر را به کاربر نشان دهیم، می توانیم از این روش Cache اطلاعات استفاده کنیم. 

نقطه ی ضعف این روش این است وقتی است که برای اولین بار درخواست خواندن اطلاعاتی به برنامه داده می شود. در این شرایط علاوه بر اینکه Cache Miss اتفاق می افتد و اطلاعات مورد نظر در Cache یافت نمی شود، قبل از اینکه این اطلاعات به برنامه داده شود، باید هزینه ی زمانی ذخیره ی آنها در Cache را هم تحمل کنیم.

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

استراتژی Write-Through 

در روش Write-Through، تمامی اطلاعاتی که قرار است در دیتابیس ذخیره شود، ابتدا در Cache ذخیره شده و سپس در دیتابیس ذخیره می شود. در این روش Cache، همراستا با دیتابیس قرار می گیرد و همه ی اطلاعات ابتدا در Cache نوشته شده و سپس به دیتابیس اصلی می رود.

موارد استفاده، مزایا و معایب Write-Through

به خودی خود، به نظر نمی‌رسد که روش write-through کار چندانی انجام دهد، در واقع، آنها تأخیری را در مرحله ی نوشتن به برنامه اضافی می‌کنند زیرا داده‌ها ابتدا در Cache و سپس در دیتابیس اصلی نوشته می‌شوند. اما وقتی این روش با روش read-through جفت می‌شود، از تمام مزایای read-through و همچنین تضمین هماهنگی اطلاعات موجود در Cache و دیتابیس برخوردار می‌شویم.

DynamoDB Accelerator (DAX) نمونه خوبی از Cache با روش های ترکیبی read-through و write-through است. DAX در کنار DynamoDB و برنامه شما قرار می گیرد و خواندن و نوشتن در DynamoDB را می توان از طریق DAX انجام داد. (توجه! اگر قصد استفاده از DAX را دارید، لطفاً مطمئن شوید که با نحوه ی ارتباط آن با DynamoDB و البته نحوه ی هماهنگ سازی اطلاعات در آن به طور کامل آشنا شده اید.)

استراتژی Write-Around

در این روش، اطلاعات مستقیماً در دیتابیس نوشته می‌شوند و تنها اطلاعاتی که درخواست خوانده شدن برایشان می آید به Cache ذخیره می شوند.

موارد استفاده، مزایا و معایب Write-Around

Write-around می تواند با read-through یا cache-aside ترکیب شود و عملکرد خوبی را در شرایطی که اطلاعات یک بار نوشته می شوند و خیلی کم خوانده می شوند یا هرگز خوانده نمی شوند، مانند پیام های ارسال شده در گروه های چت، ارائه دهد.

استراتژی Write-Back

در روش write-back، برنامه اطلاعات را در Cache می نویسد و توسط Cache دریافت و ذخیره سازی اطلاعات تایید می شود. پس از مدتی تأخیر، اطلاعات ذخیره شده در Cache به صورت دسته ای در دیتابیس ذخیره می شود.

به این روش در بعضی از منابع write-behind هم گفته می شود.

موارد استفاده، مزایا و معایب Write-Back

روش write-back عملیات نوشتن در دیتابیس را بهبود می دهد و برای برنامه هایی که بارکاری نوشتن در آنها زیاد است بسیار مناسب است. وقتی با read-through ترکیب شود، برای برنامه هایی که هم خواندن زیاد و هم نوشتن زیاد دارند به خوبی کار می کند. در این ترکیب از طراحی cache، جدیدترین اطلاعات به روز شده همیشه در cache موجود است.

این روش در برابر خرابی های دیتابیس مقاوم است و می تواند بعضی از این خرابی ها را تحمل کند. همچنین در شرایطی که ارائه دهنده ی سرویس دیتابیس شما بر اساس تعداد درخواست ها به آن هزینه های شما را شارژ می کند، این روش می تواند با ارسال چندین درخواست در قالب یک دسته، هزینه های شما را کاهش بدهد.

برخی از توسعه دهنده ها، از Redis برای cache اطلاعات هم به صورت cache-aside و هم write-back استفاده می کنند. با این تکنیک در زمان های اوج درخواست ها به برنامه، می توانند بار کاری و درخواست های به سمت دیتابیس را مدیریت کنند. ولی ایراد این کار هم اینجاست که اگر به هر دلیلی cache آسیب ببیند، همه اطلاعات ذخیره شده روی آن هم پاک خواهند شد.

InnoDB و اکثر موتورهای ذخیره ی سازی دیتابیس های رابطه ای روش cache کردن به صورت write-back را به صورت پیش فرض در خودشان دارند. در این موتورها، ابتدا پرس و جوها روی Memory ذخیره م یشود و بعد به صورت یک جا روی disk ریخته می شوند.

خلاصه

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

  • اهداف ما از cache کردن اطلاعات چیست؟
  • الگوهای خواندن و نوشتن اطلاعات در این پروژه چیست؟

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

اگر یک استراتژی اشتباهی را انتخاب کنید چه اتفاقی می افتد؟ در بدترین حالت ممکن است تاخیر اضافه ای را در پاسخ گویی برنامه ایجاد کنید، یا در بهترین حالت از تمام مزایایی که آن استراتژی می توانست برای شما داشته باشد، بهره نمی بردید. مثلا فرض کنید شما استراتژی ترکیبی write-through/read-through را انتخاب کرده اید، در حالی که بهترین ترکیب برای نیازمندی برنامه ی شما write-around/read-through بوده است. در این حالت شما اطلاعات اضافه ای در cache خود دارید که شاید خیلی مورد استفاده قرار نمی گیرند.

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

امیدوارم از این آموزش لذت برده باشید. باتوجه به این که انتخاب استراتژی مناسب می تواند اهمیت بالایی داشته باشد، در زیر تصویری را برایتان قرار می دهم که هم خلاصه ای از مطالب گفته شده است و هم می توانید به عنوان یک Cheat Sheet از آن بهره ببرید.

 

پیشنهادات بیشتر سکان بلاگ برای شما