نام استاد : داود يعقوبي تبار
نام دانشجو : امیراحمد اسلامپناه
شماره دانشجویی : 942211114024
موضوع ارائه : بررسی و معرفی Redis
درس : شیوه ارائه مطالب علمی وفنی
برای یک WEB SERVICE با ترافیک زیاد، الزام است که از نوعی مکانیزم caching بهرهمند باشد. Caching راهی برای ذخیره دادههای محاسبه شده در RAMاست، تا بعدا درخواستها بتوانند به سرعت حاضر شوند. همچنین اگر این کار به خوبی پیادهسازی شود، از برخی ارجاعها به لایه دادهها و محاسباتی در کنارههای برنامه جلوگیری میکند. Redis و Memcached دو عدد از معروفترین مخازن موجود، بر پایه رم هستند.ردیس علاوه بر caching، میتواند برای برنامههای دیگری که در آنها نیازی به دسترسی سریع و مکرر به دادهها وجود ندارد نیز استفاده شود. در این مقاله قصد داریم تا با ماهیت و ویژگیهای ردیس آشنا شویم.
در تعریف ساده redis یک دیتابیس است و آن را میتوان در دسته دیتابیسهای NoSQL قرار داد و معنی این حرف این است که مانند دیتابیسهای mysql یا sql server نیاز به تعریف کردن جدول وجود ندارد و شما میتوانید بدون ساختار مشخص اطلاعات خود را در ردیس ذخیره سازی کنید و از آنجایی که redis اطلاعات را در RAM سیستم ذخیره میکند، دارای سرعت خواندن و نوشتن نسبتا بالای است.به زبانی دیگر یک مخزن ساختار داده در داخل رم است، که از بسیاری انواع داده مانند رشتهها، hashها، setها، setهای مرتب شده و... پشتیبانی میکند. به طور اساسی ردیس یک دیتابیس key/value است، یعنی هر نوعی از مقدار داخل Redis در قبال کلیدی که به طور باینری امن است، ذخیره شده است و این مقدار میتواند هر چیزی از یک رشته خالی گرفته تا یک رشته hash طولانی باشد.
درست است که ردیس اطلاعات را در رم ذخیره میکند اما به این معنی نیست که پس از خاموش شدن و یا هر اتفاقی که باعث خالی شدن رم شود، دادههای ما پاک میشوند.بلکه ردیس برای نگه داری دائمی دادهها آنها را با توجه به تنظیماتی که برای آن مشخص کردهایم به دیسک اصلی سیستم منتقل کرده و بعد از پاک شدن رم مجدد میتواند آنها را منتقل کند و کار را از سر بگیرد.این ویژگی باعث شده اصطلاحا به آن on-disk persistence بگویند و این کار را میتواند در سطوح مختلفی انجام دهد.این سطوح شامل موارد زیر می شوند:
ردیس کاربردهای زیادی دارد از جمله:
کاربرد Caching در Redis
زمانی از Caching استفاده میشود که قصد داشته باشیم دسترسی به هارد دیسک کمتر انجام شود، به عبارت دیگر در Caching اطلاعات در حافظه موقت ذخیره میشود که این فرآیند سرعت دسترسی به اطلاعات و بارگذاری آنها را افزایش میدهد. به این ترتیب به جای چندین بار مراجعه برای بازخوانی اطلاعات از سرورها، این اطلاعات یک بار دریافت شده و در قالب حافظه نهان که همان Caching است در ردیس قرار میگیرد.از این طریق در کنار صرفهجویی در زمان و افزایش سرعت، دسترسی کمتری به منابع نیاز انجام میشود که این امر نیز به بهینهسازی بیشتر کمک میکند.در این بین به این نکته نیز باید اشاره کرد که در ردیس اطلاعات در حافظه موقتی و Cache ذخیره میشوند، این امر باعث میشود دسترسی به آنها با سرعت بسیار بیشتری انجام شود اما این سکه روی دیگری نیز دارد و امکان ذخیرهسازی دائمی اطلاعات را در Redis نخواهید داشت. به این ترتیب برای نمونه اگر قصد دارید اطلاعات مهم یک مجموعه تجاری را به صورت دائم ذخیرهسازی کنید، Redis در این زمینه کاربردی نخواهد داشت. اما از طرف دیگر روی Redis برای ذخیره کوکیها، Session، اطلاعات مربوط به ورود و خروج کاربران و به اشتراکگذاری دادهها میتوانید حساب باز کنید. بهعبارت سادهتر هر دادهای که لزومی به ذخیره دائم ندارد را میتوان با Redis مدیریت کرد.
یک مثال از Redis: فرض کنید یک وبسایت خبری چند زبانه دارای بخشهای خبری مختلف امکان جستجو و فیلتر اخبار را در وبسایت گذاشته و کاربران می توانند بر اساس زبان، بخش، تاریخ و... اخبار را جستجو و فیلتر کنند. در صورتی که تعداد کاربران جستجو کننده زیاد باشد باشد فشار زیادی به بانک اطلاعاتی می آید اما اگر نتایج جستجو را هر 15 دقیقه یکبار تولید و در حافظه ذخیره کنیم سرعت جستجو بسیار زیاد خواهد شد. با کمک Redis برای هر جستجو پارامترهای زبان، گروه خبری، تاریخ خبر را به صورت یک رشته سر هم کرده که Key جستجومی شود و value خروجی این جستجو خواهد شد. اگر کلید جستجو در Redis بود مقدار آن را به عنوان خروجی به کاربر میدهیم در غیر این صورت به DB مراجعه میکنیم، نتیجه را به کاربر برمیگردانیم و در Redis ذخیره میکنیم.
مقابسه Redis و Memcached:
هر دو پروژه متنباز هستند و در عین حال دیتا را در حافظه اصلی ذخیره میکنند. اما تفاوت این دو جایی معلوم میشود که به سراغ ویژگیها و قابلیتهای آنها میرویم. Memcached اغلب برای پروژههای ساده که حافظه Ram کمی مصرف میکنند عالی است، اما در همین حین در مواجه با دادههای مرتب شده و یا serialize شده نامناسب است. به دلیل پشتیبانی Redis از اکثر ساختار دادههای مختلف، قدرت و کارایی بیشتری در برخورد با مجموعه دادههای بسیار زیاد دارد. همچنین توانایی بیشتری در بهبود cache و راندمان در برنامههای مخصوص دارد.
مقایسه Redis و MongoDB:
تفاوت این دو در این است که یکی به صورت دیتابیسی در حافظه، دیگری دیتابیسی بر روی دیسک است و هر کدام برای هدف خاصی طراحی شدهاند اما اغلب در کنار هم با هدف افزایش سرعت پردازش و کارایی دیتابیسهای NoSQL استفاده میشوند. به دلیل قابلیت cache که در Redis وجود دارد، خیلی سریعتر میتوان به دادهها دسترسی پیدا کرد. در نتیجه میتوانیم از این قابلیت بهره ببریم و Redis را به عنوان رابطی برای MongoDB استفاده کنیم تا بتوانیم سریعتر و موثرتر دادههای بیشتر و بزرگتری را real-time تر بروزرسانی و ویرایش کنیم. به دلیل این که MongoDB میتواند حجم قابل توجهی از دادهها را ذخیره کند و از طرف دیگر با توجه به سرعت بسیار بالای Redis در پردازش آنها، استفاده از این دو درکنار یکدیگر میتواند راه حلی برای مسائل مختلفی که در آنها سرعت و کارایی حرف اول را میزند، باشد.
راهاندازی ردیس با داکر
بدیهی است که ردیس به عنوان یک دیتابیس دارای یک سرور برای ذخیره دادهها در رم و کلاینتها است که در قبال یک سرور، دستوراتی را اجرا میکند. برای راهاندازی سرور بر روی دستگاه خود، استفاده از Docker را پیشنهاد میکنم؛ زیرا شروع کار با آن بسیار ساده است. اگر Docker daemon را بر روی سیستم خود دارید، این دستور را اجرا کنید:
docker run --rm -it --name local-redis -p 6379:6379 redis
این دستور یک محفظه Docker با نام «local-redis» را بر روی localhost شما با پورت ۶۳۷۹ اجرا میکند. این دستور از تصویر رسمی Redis docker برای اجرای محفظه استفاده میکند.
برای کلاینت، میتوانیم از redis-cli برای اجرای دستورات از کنسول بر روی سرور Redis استفاده کنیم. یک تب جدید باز کنید، و دستور زیر را برای شروع یک redis-cli session که به یک نمونه سرور Redis داخلی متصل است، استفاده کنید:
docker run -it --link local-redis:redis --rm redis redis-cli -h redis -p 6379
اکنون چند دستور پایه از ردیس را بررسی میکنیم:
استفاده از Client برای زبان های مختلف
تقریبا برای تمامی زبان های مهم برنامه نویسی که در دنیا رایج هستند Client استفاده از Redis نوشته شده است. برای مثال در زبان PHP تعداد زیادی Redis Client وجود دارد که معروف ترین اونها phpredis و Predis هست. بنا براین شما با هر زبان برنامه نویسی در حال کد زدن هستید به راحتی می توانید به دیتا بیس Redis خود متصل شوید و دستورات خود را اجرا نمایید.
آشنایی با Data Type های اصلی ردیس
همانطور که گفته شد Redis تنها یک دیتا بیس ذخیره کننده key value به صورت ساده نیست بلکه می تواند انواع مختلفی از ساختار های دادهای را به عنوان value در خود ذخیره کند که از این رو می توان Redis را یک data structures server نیز نامگذاری کرد.این ساختار ها در ۵ دسته اصلی در Redis پشتیبانی می شوند:
حال این 5 دسته را بررسی میکنیم تا بیشتر با دستورهای آنها آشنا شویم:
۱. نوع Strings
در واقع وقتی string را به عنوان value ذخیره می کنید یک map بین string و string دارید. برای ساخت و یا در یافت string در ردیس کافی هست از دو دستور زیر استفاده نمایید:
1234> set mykey somevalue OK > get mykey "somevalue"
اگر یک key از قبل تعریف شده باشد و مجدد آن را set کنید برروی اولی تنها value را جایگزین می کند. از موارد استفاده این نوع داده ای شاید بتوان ذخیره فایل های html را مثال زد تا با cache کردن آنها بتوان مجدد به آنها دسترسی داشت و دوباره render نشوند.
۲. نوع Lists
این نوع برای داشتن لیستی از رشته ها هست. دقیقا لیستی که شما بتوانید از ابتدا یا انتهای آن مقادیر خود را اضافه و یا کم کنید. برای درک بهتر مثالی میزنم، یک timeline و یا یک تاریخچه چت رو در نظر بگیرید. باید به تریتب پیام ها ی رد و بدل شده بین دو کاربر را نگه دارید و یا برای timeline پست های منتشر شده مثل همین پست های ویرگول که یک ترتیبی بر اساس تاریخ وجود دارد. این نوع لیست را در ردیس می توان با نوع Lists و با کمک دستورات زیر ایجاد کرد:
1LPUSH mylist a
یک لیست به نام mylist ساختیم و مقدار a را به ابتدای آن اضافه کردیم. حالا میخواهیم به انتهای لیست هم مقداری اضافه کنیم:
1 RPUSH mylist c
الان یک لیست داریم که ۲ تا مقدار داخل آن هست و می توان با همین ۲ دستور مقادیر دیگری را هم اضافه کرد:
12LPUSH mylist b LPUSH mylist d
بعد از اجرای ۴ دستور بالا هم اکنون به ترتیب زیر لیستی به نام mylist داریم:
12341) "d" 2) "b" 3) "a" 4) "c"
از آنجایی که LPUSH به ابتدای لیست اضافه می کند، در لیست بالا مشخص هست که مقدار ابتدایی لیست چرا "d" هست.
خوب حالا می خواهیم با دستور زیر مقدار ابتدای لیست را بگیریم:
12> LRANGE mylist 0 0 1) "d"
دستور LRANGE می تواند با توجه به مقدار ابتدایی و انتهایی که به آن می دهیم به ترتیب مقادیر داخل List را به ما برگرداند. در مثال بالا از خانه 0 تا 0 یعنی تنها اولین مقدار لیست و در مثال پایین می توانیم تمام ۴ مورد رو بگیریم:
12345> LRANGE mylist 0 3 1) "d" 2) "b" 3) "a" 4) "c"
برای گرفتن یک مقدار از ابتدا و یا انتهای لیست و حذف آن باید به صورت زیر با دستورات POP کار کنیم:
123456> LPOP mylist "d" > LRANGE mylist 0 3 1) "b" 2) "a" 3) "c"
در ابتدا با LPOP مقدار ابتدای لیست را که "d" بود را گرفتیم و آن از لیست حذف شد.
همین کار با دستور RPOP برای انتهای لیست قابل انجام هست:
12345> RPOP mylist "c" > LRANGE mylist 0 3 1) "b" 2) "a"
توی این لیست تا دلتان می خواهد می تونید مقدار اضافه کنید چون Redis می تواند بیش از ۴ میلیارد المان در هر لیست نگه داری کند.
۳. نوع Sets
شاید اگر لیستی از رشته ها را بخواهید بسازید از List استفاده کنید ولی اگر لیستی بخواهید که؛ ترتیب در آن مهم نباشد، بخواهید که مقادیر تکراری وارد لیست شما نشوند، از هر کجای لیست که خواستید با سرعت خیلی بالا مقادیر را بگیرید و بررسی کنید که آیا مقداری که دنبال آن هستید در این لیست هست یا خیر، باید از Sets استفاده کنید.
در واقع نوع داده ای Sets در ردیس برای داشتن یک collection از رشتهها به عنوان مقادیر هست با این ویژگی مهم که دیگر نیاز به بررسی وجود این مقدار در collection نیست و هر چند بار که یک مقدار تکراری را به Set اضافه کنیم همان یک مقدار را در collection خودمون داریم. یکی دیگه از ویژگی های جالب Set این هست که شما می توانید چند تا Set را در Redis باهم Union کنید و از اونها استفاده کنید. از موارد پر کاربرد Set می توان به محاسبه ی تعداد کاربران یکتای بازدید کننده از سایت اشاره کرد به این صورت که یک Set از مقادیر ip تمام کاربران بازدید کننده داریم و از آنجایی که این مقادیر تکراری نمی باشد می توان با محاسبه تعداد آنها به بازدید یکتای سایت خود برسیم.
پس با دستورات زیر می توانیم بیش از ۴ میلیارد مقدار متفاوت را در یک Set اضافه کنیم:
123456> SADD myset "Hello" 1 > SADD myset "World" 1 > SADD myset "World" 0
در مثال بالا با دستور SADD یک Set به نام myset ساختیم و مقدار "Hello" و "World" رو ابتدا به آن اضافه کردیم و مقدار 1 را به صورت integer دریافت کردیم که نشان می دهد مقادیر به Set اضافه شد اما در دستور بعدی مجدد مقدار "World" را اضافه کردیم که مقدار 0 را بر گرداند که چون مقداری تکراری بود.
۴. نوع Sorted Sets
همان طور که از اسم این نوع داده مشخص هست شبیه Sets هست یعنی یک collection از مقادیر رشتهای بدون تکرار، اما بر خلاف Set می توان در Sorted Set یک مقدار به عنوان Score به هر المان داد. با این مقدار می توانیم از کمترین به بیشترین score المان های خودمون رو مرتب کنیم و این نکته را هم باید بدونیم که برخلاف مقادیر المان ها، score ها می توانند تکراری هم باشند. برای مثالی از کاربرد این نوع داده می توانیم لیستی از task ها را در نظر بگیریم که تکراری نیستند و هر کدام یک درجه اهمیتی دارند. حالا می توانیم این لیست را از هر کجایی که نیاز داریم مرتب کنیم. ساخت یک Sorted Set با دستور ZADD قابل انجام هست:
123456>ZADD myzset 1 "one" 1 > ZADD myzset 2 "two" 1 > ZADD myzset 3 "three" 1
خوب یک Sorted Set با نام myzset ساختیم و ۳ تا مقدار one, two, three رو با socre هایی به ترتیب 1,2,3 به آن اضافه کردیم.
حالا اگر بخواهیم score مقدار two را ببینیم با دستور ZSCORE خواهیم داشت:
12> ZSCORE myzset "two" "2"
در زمان استفاده از Sorted Set، احتمالا مواقعی نیاز داریم که المان هایی را که بین ۲ تا score وجود دارند را بگیریم یعنی کاری که با دستور پایین انجام دادیم:
123> ZRANGE myzset 2 3 1) "two" 2) "three"
بین ۲ تا مقدار 2 و 3 به عنوان score در myzset این ۲ المان وجود داشت. حذف یک مقدار از Sorted Set با دستور ZREM قابل انجام هست:
12> ZREM myzset "two" 1
۵. نوع Hashes
آخرین DATATYPE که در ردیس بررسی میکنیم بسیار می تواند پر کاربرد باشد و البته کار راه انداز! اگر می خواهید داخل هر key یک object نگه دارید Hash دقیقا پاسخ نیاز شماست. هر Hash داخل Redis این امکان رو به شما میدهد که به ازای هر key یک map از رشته هایی به صورت key value را نگه دارید یعنی دقیقا همان چیزی که از object انتظار دارید. از موارد کاربرد آن می توان به نگه داشتن اطلاعات کاربران لاگین شده به سیستم اشاره کرد. فرض کنید به ازای هر کاربری که به سیستم شما لاگین می شود یک key از نوع Hash بسازید و داخل آن اطلاعاتی مثل نام، ایمیل، تلفن و هر چیزی که نیاز دارید نگه داری کنید. بیایید همین مثال بالا را در redis cli اجرا کنیم، پس یک key به اسم user و مقدار id اون در دیتابیس که فرض می کنیم ۱۰۰۰ باشد می سازیم و مقادیری که می خواهیم را در آن نگه می داریم:
12> HMSET user:1000 username vahiiiid password 1234 age 26 OK
خوب همان طور که دیدید این کار با دستور HMSET انجام شد و مقادیری مثل username, password و age از کاربر نگه داری شد. حالا اگر تمام این اطلاعات کابر را بخواهیم کافی هست دستور زیر را اجرا کنیم:
1234567> HGETALL user:1000 1) "username" 2) "vahiiiid" 3) "password" 4) "1234" 5) "age" 6) "26"
برای تغییر یک مقدار از Hash می توانیم به صورت زیر عمل کنیم:
1HSET user:1000 password 12345
اگر فقط مقدار یک فیلد را بخواهیم بگیریم می توانیم از HGET استفاده کنیم:
12> HGET user:1000 age "26"
با دستور HEXISTS هم می توان از وجود یک فیلد در Hash اطلاع پیدا کنیم:
12> HEXISTS user:1000 age 1
در این مقاله تنها بخشی از دستورات برای آشنایی بیشتر با DATA TYPEهای ردیس بررسی کردیم اگر میخواهید با دستورات بیشتری آشنا شوید از این لینک اقدام کنید.
جمع بندی
ردیس ویژگیهایی نظیر سادگی، کارایی استثنایی و خاصیت atomic در ویرایش دادهها دارد که باعث میشود حل کردن مسائلی که در دیتابیسهای متداول رابطهای نظیر MySQL مشکل بود، به راحتی انجام شود و ردیس نقش آچار فرانسه در ذخیرهسازی دادهها را برای توسعهدهندگان داشته باشد. توسعه دهندگان همیشه به سرعت و کارایی بالا علاقه نشان میدهند.
منابع:
و چند سایت و مقاله دیگر
تقدیم به استاد داود یعقوبی تبار
با تشکر از وقتی که گذاشتید امیدوارم مورد رضایت بوده باشه