برای محصولی لازم بود یک دیتابیسی استفاده کنیم که بتواند 600K ریکویست بر ثانیه را پاسخگو باشد، بر اساس تجربه تصمیم گرفتیم که از سرویس Redis استفاده کنیم. خیلی درگیر شدیم با Redis و هرچقدر که جلو میرفتیم مشکلات و مفاهیم جدید تری برخورد میکردیم. که باعث شد تجربیات خوبی توی این زمینه کسب کنیم.
یکم با خودم فکر کردم و به این نتیجه رسیدم که چرا این تجربیات و مشاهدات رو با بقیه به اشتراک نزارم. و اینگونه شد که تصمیم گرفتم این سری از پست ها رو براتون بنویسم. ( این پست تجربیات و مشاهدات شخصی است)
برای این که بتوانیم دقیق تر درک کنیم که Redis چیه بهتره از عمق مطالب شروع کنیم به یادگیری. پس بریم ببینیم که Redis چیکار میکنه:
سرویس Redis یک دیتابیس Key/Value In-Memory هست به این معنی که بهش اطلاعات با یک شناسه میدیم و میگیم که این اطلاعات برای این شناسه باشه و Redis این شناسه و اطلاعات رو یه جایی از رم ذخیره میکنه برامون. و هر موقع خواستیم شناسه رو بهش میدیم و ازش اطلاعات که ذخیره کرده بودیم رو میگیریم.
قبل از این که بفهمیم چطوری کار میکنه لطفا مقاله طریقه استفاده از ردیس را بخوانید.
( منتظر میمونم تا بخونید و برگردید? )
خوب حالا که متوجه شدیم چطور میتوانیم از ردیس استفاده کنیم. بریم ببینیم ردیس چطوری کار میکنه.
تصور کنید شما یک شناسه و اطلاعاتی را برای ردیس ارسال کردید. ردیس اطلاعات شما را داخل یک انتضاعی به نام اسلات ذخیره سازی میکند. به صورت پیشفرض Redis اطلاعات شما را بین 16384 اسلات بر اساس الگوریتم زیر پخش خواهد کرد:
HASH_SLOT = CRC16(key) mod 16384
این الگوریتم با استفاده از CRC16/XMODEM برای کلید شما ، یک عددی را تولید میکند و 14 بیت از 16 بیت خروجی داده شده توسط این الگوریتم را برداشته و باقیمانده تقسیم اون عدد به تعداد کل اسلات ها (16384) را گرفته و اطلاعات شما را داخل آن اسلات ذخیره میکند. این الگوریتم باعث میشود که اطلاعات شما تقریبا به صورت یکسانی داخل اسلات ها پخش شوند. یعنی اگر اسلات 1 شامل 50 کلید هست اسلات های دیگر هم به احتمال خیلی زیاد 45 تا 55 کلید را شامل میشوند. الگوریتم CRC16 همیشه یک عدد یکسانی را برای کلید شما تولید خواهد کرد و زمانی که شما به اطلاعات یک کلید نیاز داشته باشید با دادن کلید به این الگوریتم میتوانید آدرس اسلاتی که اطلاعات مربوط به آن کلید را شامل میشود را دریافت کنید. نمونه ای از پیاده سازی این الگوریتم داخل ردیس را توی این لینک میتوانید ببینید لینک .( شما میتوانید برای محاسبه آدرس اسلات الگوریتم های شخصی سازی شده بنویسید(قابلیت تنظیم دارد)).
از این الگوریتم میتوانیم متوجه بشیم که ادرس اسلاتی که اطلاعات شما رو ذخیره میکنه به شناسه وابسته است پس همیشه یک کیلد داخل یک اسلاتی از ردیس ذخیره خواهد شد.
برای مثال اگر شما داخل ردیس یک کلید به نام test تعریف کردید با هر اطلاعاتی، داخل اسلات 6918 ذخیره خواهد شد. برای تست این مسئله میتوانید کد زیر را اجرا کنید:
x.x.x.x:yyyy> SET test test2 x.x.x.x:yyyy> CLUSTER KEYSLOT test
عددی که دریافت میکنید 6918 خواهد بود.
و یا کد زیر را اجرا کنید:
x.x.x.x:yyyy> SET somekey test x.x.x.x:yyyy> CLUSTER KEYSLOT somekey
عددی که دریافت میکنید 11058 خواهد بود.
میتوانیم نتیجه بگیریم که کلید های test و somekey و هر کلید دیگری در همه سرویس های ردیس داخل اسلات های مشخصی ذخیره خواهد شد.
نکته (مهم): در صورتی که از دستور HSET استفاده بکنید تمام اطلاعات شما بر اساس کلید پخش خواهد شد. نه بر اساس فیلد مثال زیر را ببینید:
x.x.x.x:yyyy> HSET hsettest field 1 x.x.x.x:yyyy> CLUSTER KEYSLOT hsettest
در این صورت عدد 7198 را دریافت خواهید کرد.
پس در نتیجه هیچ وقت از HSET های خیلی بزرگ استفاده نکنید تا پخش اطلاعات شما بر روی اسلات ها به درستی انجام شوند.
دیتابیس های In-Memory به صورت General مزایایی دارند که در ادامه میاریم:
1- مشکل هایی Infrastructure که موقع استفاده از دیتابیس هایی On-Disk میتونیم بهش بر بخوریم رو توی In-Memory دیتابیس ها مشاهده نمیکنیم. و یا خیلی کمتر دیده میشه. ( مثلا: پر شدن io هارد ، وابستگی پرفرمنس دیتابیس به سرعت کارکرد هارد یا بار پردازشی بالا و ... )
2- در دیتابیس های In-Memory با توجه به استفاده از Ram به عنوان ذخیرهساز کاری و بالا بودن سرعت کاری ( کلاک) دیتا ها سریع ترین زمان ممکن ذخیره و برگردونده میشن.
3- دیتابیس های In-Memory برای پیدا کردن مکان اطلاعات معمولا از الگوریتم های هش تیبل استفاده میکنند که تقریبا پیچیدگی زمانی شبیه به O(1) رو میبینید.
دیتابیس Redis امکانات جالبی نسبت به بقیه دیتابیس های In-Memory بهمون ارایه میده که در ادامه میاریم:
1- ردیس اجازه ذخیره سازی داده هایی به حجم 512 مگابایت ( کلید همراه با مقدار) را برای شما میده.
2- ردیس به شما اجازه میده تا دیتا هاتون روو به صورت مپ ذخیره کنید. کد زیر رو ببینید:
java: Map<String, String> user = new HashMap<>(); user.put("username", "john123"); user.put("firstName", "John"); // use Jedis client jedis.hmset("user:john123", user); // منبع کد DZone
3- ردیس به شما امکان تکرار داده های ذخیره شده در Node های مختلف رو ارایه میده.( Replication )
4- ردیس تقریبا برای تمام زبان های برنامه نویسی و تمام پلتفرم ها کلاینت ها و کتابخانه های کاملی ارایه داده.
5- این سرویس به شما امکان ایجاد چنل Pub/Sub میدهد ( کاربردی مانند Message Broker)
6- ردیس سرویس سبکی بوده منابع زیادی مصرف نمیکند.(بسته به ساختار داده شما میتواند متفاوت باشد)
7- ردیس میتواند از transactions پشتیبانی کند. (اجرای همزمان چند دستور)
8- ردیس به شما این امکان را میدهد که الگوریتم های شخصی سازی شده برای پخش داده های شما بر روی اسلات ها بنویسید.
9- کلاسترینگ بسیار کامل ولی پیچیده ای برای شما ارایه میده.
10- ابزار های کاملی برای تست و ترابلشوتینگ و بهینه سازی ارایه داده.