در این مقاله برای نمایش کد ها از GitHub Gist استفاده شده و ممکن است Load شدن کد ها کمی طول بکشد یا به نرم افزار های رفع تحریم نیاز داشته باشید.
امروزه در وبسایت های شخصی و تجاری یکی از مهم ترین پارامتر ها سرعت پاسخگویی درخواست ها به وبسایت است. طبق آمار ، کاربران آنلاین کنونی که ما با آن ها طرفیم سطح تحملشان به سه ثانیه در یک صفحه میرسد پس ما باید بتوانیم سرعت وبسایت های خودمان را تا حد ممکن بهبود بخشیم. از طرفی پارامتر سرعت ، روی سئو گوگل هم تاثیر بسزایی داره و Ranking وبسایت شمارا تا حد زیادی افزایش میدهد. قطعا همه میدانید که سرعت وبسایت و برنامه چقدر مهم هست پس زیاده گویی نمیکنیم و میرویم سراغ اصل مطلب.
یکی از کارهایی که میتوانیم برای افزایش سرعت برنامه انجام دهیم استفاده از Cache هست. خیلی ساده Cache یعنی قرار دادن دیتای پرکاربرد در یک حافظه نزدیک تر از دیتابیس که هروقت به آن نیاز داشتیم دسترسی سریعی داشته باشیم و سرعت واکشی اطلاعات از سرعتی که دیتابیس به ما میدهد بیشتر باشد تا درخواست های ما با پاسخ سریع تری همراه شوند.
این حافظه Ram هست و عمل Caching به اینصورت خواهد بود که هر وقت دیتای مورد نظر یکبار از دیتابیس واکشی شود از دفعات بعد آن دیتا را در Ram ذخیره میکند و برای درخواست های بعدی به دیتابیس Query نمیزند و دیتای مورد نیازش را از Ram میگیرد.
این امر در کنار مزایایی که دارد ، حساسیت بالایی هم بهمراه خواهد داشت چرا که حافظه مورد استفاده Ram و یک حافظه محدود هست همچنین میتواند برای هر سخت افزاری متفاوت باشد پس پیاده سازی این سیستم نیاز به دو دو تا چهارتا و ساختار درست دارد ، در غیر اینصورت Cache کردن دیتای غلط میتواند به تنهایی وبسایتتان را Down کند پس خیلی باید به این موضوع دقت داشت.
خیر.
پس اکنون میدانید که میتوانیم داده های بی نهایت در دیتابیس ذخیره کنیم و فقط با ارزش ترین ها و پر مصرف ترین هارا در حافظه کش ذخیره میکنیم.
عملیات Cache در Asp.Net Core توسط اینترفیس های IMemoryCache و IDistributedCache مدیریت میشود و میتوانید با تزریق این اینترفیس ها براحتی از متدهایشان استفاده کنید اما قبل از استفاده لازم است با عملکرد هر یک آشنا شویم.
معمول ترین و ابتدایی ترین روش برای کش کردن اطلاعات روش Local Caching و بصورت In-Memory است که اطلاعات را در حافظه Ram همان سروری که برنامه در آن اجرا میشود کش میکند.
این روش تا زمانی که برنامه ما برای اجرا شدن تنها از یک سرور استفاده کند بهترین انتخاب خواهد بود چرا که به دلیل نزدیک بودن سریع ترین بازخورد را نیز به درخواست ها اراعه میدهد.
اما شرایطی را فرض کنید که برنامه از چندین سرور برای اجرا شدن استفاده میکند و به طبع هر سرور درخواست های خودش را داراست که ما باید برای هر یک بصورت جداگانه یک کش In-Memory در حافظه Ram هرکدام ایجاد کنیم.
فرض کنید دیتای ما 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 باشد. بخشی از دیتا در Server 1 کش میشود (1 , 3 , 5 , 9) و بخشی دیگر در Server 2 کش خواهد شد (2 , 4 , 6 ,7 , 8 , 10).
در اینجا مشکلات و ضعف هایی به وجود خواهد آمد :
روش هایی وجود دارد که بتوان از سیستم Local Caching در حالت چند سروری هم استفاده کرد و این مشکلات را از بین برد اما روش استاندارد در حالت چند سروری استفاده از Distributed Cache ها است.
در این روش برنامه ما برای اجرا شدن از چندین سرور شبکه شده به هم در حال استفاده هست و Cache برنامه توسط سرورها به اشتراک گذاشته شده.
در این حالت سرور های ما از یک کش عمومی استفاده میکنند که مزایای آن شامل :
■ درخواست ها به چندین سرور مختلف از هم ارسال شده اما دیتای کش بصورت منسجم در هریک وجود خواهد داشت.
■ با خراب شدن یا Down شدن یک سرور ، کش موجود در سرور های دیگر پاک نمیشود و کماکان قابل استفاده است.
■ به حافظه Ram یک سرور محدود نیست و مشکلات زیادی همچون کمبود سخت افزاری و محدودیت های حافظه Ram را تا حد معقولی کاهش میدهد.
در پارامتر اول این متد (CacheKey) یک کلید برای اطلاعاتی که میخواهیم کش کنیم قرار میدهیم. دقت کنید که این کلید شناسه دیتای شماست و باید طوری آن را در نظر گرفت که با صدا زدن این کلید از سرویس کش همان دیتای مورد نظر را برگشت دهد (هر Object دیتا باید کلید Uniq خود را داشته باشد).
در پارامتر دوم دیتای مورد نظر که میخواهیم کش کنیم را به متد میدهیم و در پارامتر سوم نیز زمان اعتبار و تاریخ انقضای دیتای کش شده را وارد میکنیم به این معنی که دیتای کش شده بعد از مدت زمان گفته شده از حافظه کش(Ram) حذف شود و برای دسترسی دوباره و کش کردن دوباره اطلاعات ، نیاز به خواندن مجدد از دیتابیس باشد.
تنها پارامتر ورودی این متد کلید از قبل نسبت داده شده به اطلاعات کش هست که با استفاده از یکسان بودن کلید در ورودی این متد و کلید Set شده از قبل در حافظه Ram ، دیتا مربوط به آن را برگشت میدهد.
این متد ابتدا بررسی میکند که کلیدی با نام "CacheKey" وجود دارد یا خیر. در صورت عدم وجود آن را میسازد و دیتای مورد نظر را به آن نسبت میدهد.
در اینجا absolute expiration به این معنی است که یک زمان قطعی را برای منقضی شدن کش ها مشخص میکند به عبارتی میگوییم کش با کلید فلان در تاریخ و ساعت فلان حذف شود.
اما در sliding expiration یک بازه زمانی برای منقضی شدن کش ها مشخص میکنیم یعنی میگوییم بعد از گذشت فلان دقیقه از ایجاد کش ، آن را حذف کن.
این تنظیمات را میتوانید در قالب یک option زمان Set کردن یک کش به آن بدهید.
در مثال بالا هردو option اضافه شده یک کار را انجام میدهند با این تفاوت که absolute expiration تاریخ now را گرفته و یک دقیقه بعد را به آن اضافه کرده و تاریخ انقضای کش را با آن تاریخ set میکند. اما sliding expiration از حالا بمدت یک دقیقه اعتبار دارد.
1_ NeverRemove = 3
2_ High = 2
4_ Normal = 1
5_ Low = 0
این الویت بندی ها زمانی کاربرد خواهد داشت که حافظه اختصاصی Ram برای کش ها پر شده باشد و در این حالت سیستم کشینگ بصورت خودمختار کش های با الویت پایین را از حافظه حذف میکند و کش ها با الویت ببیشتر در حافظه باقی میماند. این با شماست که الویت را برای دیتا های خود تعیین کنید پس باید با دقت و فکر شده این کار را انجام دهید.
به این صورت میتوانید الویت های متفاوت را در قالب option به کش های خود اختصاص دهید.
در این مقاله سعی شد مفاهیم اولیه Cache طوری گفته شود تا برای افرادی که میخواهند به تازگی این سیستم را بیاموزند و در پروژه های خود استفاده کنند کاربردی باشد و درک نسبی را نسبت به مزایا و محدودیت های این سیستم بدست آورند.
در قسمت دوم همین مقاله بطور تخصصی تر به این مبحث میپردازیم و یک پکیج آماده را معرفی میکنیم که خیلی راحت تر و اصولی تر کش را برای ما پیاده سازی میکند.
مقالات بیشتر در دات نت زوم