Redis یک ساختار ذخیره داده در حافظه اصلی است که از یک پایگاه داده با الگوی کلید-مقدار بهره میگیرید. استفاده از Redis و فریمورکی مانند لاراول به صورت همزمان برای ذخیره دادههایی که بیشتر برای خواندن هستند و کمتر دچار تغییر میشوند، موجب میشود که سرعت استخراج دادهها در مقایسه با پایگاههای...
1400/02/074916 بازدید
Redis یک ساختار ذخیره داده در حافظه اصلی است که از یک پایگاه داده با الگوی کلید-مقدار بهره میگیرید. استفاده از Redis و فریمورکی مانند لاراول به صورت همزمان برای ذخیره دادههایی که بیشتر برای خواندن هستند و کمتر دچار تغییر میشوند، موجب میشود که سرعت استخراج دادهها در مقایسه با پایگاههای دادهای مانند Mysql به میزان قابلملاحظهای افزایش یابد.
استفاده از لاراول و Redis
مواردی که در این آموزش فراخواهیم گرفت:
نحوه نصب Redis و گزینههایی که در این رابطه برای شما وجود دارند.
انواع دادههای Redis همراه با مثالهای مرتبط
ایجاد یک eCommerce ساده با استفاده از لاراول به همراه Redis برای ذخیره داده
استفاده از Laravel Websocket به همراه Redis queue برای نمایش بروزرسانی لحظهای به کاربران بدون نیاز به تازهسازی صفحه
پیشنیازها
برای دنبال کردن این آموزش به موارد زیر احتیاج خواهید داشت.
یک پروژه لاراول x جدید که در دایرکتوری ریشه وب شما قرار داشته باشد.
استفاده از سیستمعامل لینوکس یا مکینتاش
نصب کمپوزر به صورت گلوبال بر روی سیستم
استفاده از PHP نسخههای بالاتر از 2
قبل از شروع هر کاری، باید کلاینت Redis را حتماً در سیستم خودتان نصب کنید. بهترین راه توصیه شده، کامپایل مستقیم آن از منبع است. برای این منظور فرمانهای زیر را به ترتیب در ترمینال خود وارد کنید.
حالا با اجرای فرمان از طریق ترمینال، از صحت عملکرد ابزار خود مطمئن شوید.
php
1redis-cli
در صورتی که همه چیز به خوبی پیش رفته باشد، به رابط کاربری خط فرمان Redis هدایت خواهید شد.
نصب PHP Redis
دو گزینه برای نصب همزمان Redis و لاراول وجود دارد. سادهترین و اولین روش، استفاده از کمپوزر برای نصب بسته predis/predis است.
php
1composer require predis/predis
با این وجود، این بسته در لاراول 7.x توسط برنامهنویس اصلی کنار گذاشته شده و قرار است که در نسخههای بعدی لاراول حذف شود.
گزینه دوم که بیشتر توصیه شده و البته به زمان و کار بیشتری نیاز دارد، نصب افزونه PHPRedis است. این افزونه یک API برای ارتباط با سرور Redis ایجاد میکند. PHPRedis برخلاف بسته کمپوزر predis، بیشتر قابلاعتماد و سریع است و میتواند در اپلیکیشنهای بزرگتر مورد استفاده قرار گیرد.
در اینجا از PECL برای نصب افزونه PHPRedis استفاده میکنیم. برای آنهایی که با این ابزار آشنایی ندارند، باید گفت که PECL منبعی برای افزونههای PHP است.
نکته: عبارت peclX.Y را با نسخه PHP خودتان جایگزین کنید. برای بررسی این موضوع میتوانید از فرمان php -v در ترمینال استفاده نمایید. بر این اساس اگر نسخه PHP شما برابر 7.2 باشد، فرمان به صورت sudo pecl7.2-sp install redis درخواهد آمد.
وقتی نصب افزونه با موفقیت به پایان رسید، یک فایل تنظیمات برای افزونه Redis ایجاد کنید. پس باید با فرمان زیر PHP را دوباره راهاندازی نمایید.
php
1sudo bash -c "echo extension=redis.so > /etc/php5.X-sp/conf.d/redis.ini"23sudo service php7.X-fpm-sp restart
نصب در مکینتاش
فرمان زیر را اجرا کنید.
php
1pecl install redis
این فرمان میتواند منجر به بروز خطا شده و افزونه را به شکل کامل نصب نکند. در چنین صورتی، فرمان زیر را تایپ و اجرا کنید. در این فرمان، 7.x.x نسخه PHP شماست. همچنین با کمک فرمان ls /usr/local/Cellar/php میتوانید لیست تمام فایلهای موجود در دایرکتوری را مرور کرده و مسیر درست را برای pecl مشخص کنید.
php
1rm /usr/local/Cellar/php/7.x.x/pecl
حالا فایل php.ini بارگذاریشده را باید ویرایش کنید. برای مشخصکردن فایل php.ini بارگذاریشده، یک فایل phpinfo.php بسازید و عبارت <?php echo phpinfo(); را در آن قرار دهید. سپس خروجی را به منظور یافتن نسخه بارگذاریشده بررسی کنید و در ادامه، این فایل را ویرایش کرده و خط زیر را در آن حذف کنید.
php
1extension="redis.so"
اکنون فایل php.ini را ذخیره کرده و از آن خارج شوید.
نهایتاً یک فایل /usr/local/etc/php/7.X/conf.d/ext-redis.ini بسازید و با ویرایشگر vim یا nano آن را باز کنید. به خاطر داشته باشید که به جای 7.X باید نسخه PHP خودتان را وارد کنید.
سرویس php-fpm را دوباره راهاندازی کرده و اگر هم از لاراول استفاده میکنید، فرمان valet restart را اجرا کنید.
انواع دادههای Redis
Redis انواع مختلفی از داده دارد که عبارتند از: String، Lists، Sets، Sorted Sets، Hashes & Bitmaps و Hyperlogs. در اینجا درباره همه انواع دادههای در دسترس، به جز مورد آخر صحبت خواهیم کرد.
بر اساس هدفی که این آموزش دنبال میکند، نمونههای این نوع دادهها را از طریق رابط کاربری خط فرمان Redis آزمایش میکنیم. بنابراین، یک ترمینال جدید باز کرده و فرمان زیر را اجرا کنید.
php
1redis-cli
داده String
این یکی از پایهایترین نوع داده در دسترس است. رشتههای String به صورت binary safe هستند. به این معنا که یک رشته Redis میتواند هر نوع دادهای، مثلاً یک تصویر JPEG یا یک آبجکت کدبندیشده در بر داشته باشد.
در اینجا یک نمونه را در خط فرمان Redis بررسی میکنیم.
php
1127.0.0.1:6379> SET user:1:name Oluwafemi23127.0.0.1:6379> GET user:1:name45"Oluwafemi"
دادههای Lists
این نوع داده، در واقع لیستی از رشتههاست که بر اساس ورود مرتب شدهاند و آیتمها را میتوان به ابتدا یا انتهای لیست اضافه کرد. لاراول باعث میشود که این نوع داده برای ذخیره وظایف در یک صرف استفاده گردد. سپس این وظایف مطابق زمان اضافهشدن به لیست، اجرا میشوند.
دستهها مجموعهای نامرتب از رشتهها هستند که امکان اضافه، حذف و تست وجود اعضا در آنها وجود دارد. در همین حال، امکان تکرار آیتمها در دستهها نیست و در هنگام استخراج آیتمها، ترتیب خاصی در خروجی نخواهد بود.
همچنین امکان انجام برخی عملیات بین دو یا چند دسته، از جمله پیدا کردن اشتراکات یا ترکیب آنها وجود خواهد داشت.
Redis Hashها تبدیلهایی بین میدان رشتهها و مقادیر رشتهها به شمار میروند. بر این اساس، نوع داده مناسبی برای ارائه آبجکتها خواهند بود. در هنگام چت یا گفتگو بین دو کاربر، هر کدام از پیامها و جزئیات آن را میتوان در یک hashmap بیان کرد.
دستههای مرتب شباهت زیادی به دستههای ساده Redis دارند. با این تفاوت که هر کدام از اعضای یک دسته مرتب با یک نمره (Score) همراه است که ترتیب آن را در دسته مشخص میکند. به عنوان مثال، میتوان یک دسته مرتب با نمره از کوچک به بزرگ در اختیار داشت.
به عنوان نمونه، می توانید یک دسته مرتب از پیامها را در تاریخچه گفتگوی دو کاربر تصوّر کنید. به این ترتیب، میتوان در استخراج پیامها بر اساس مقاطع زمانی اقدام کرد که در اینجا، مقاطع زمانی پیامها به عنوان «نمره» درنظر گرفته میشود.
تقریباً تمام عملیاتی که برای دستههای ساده قابلانجام هستند، برای یک دسته مرتب نیز کاربرد دارند.
برای مطالعه بیشتر در مورد سری دادههای Redis میتوانید به متون رسمی در این رابطه نیز مراجعه کنید.
اپلیکیشن Ecommerce با استفاده از لاراول و Redis
در اینجا فرض میشود که شما از قبل یک پروژه لاراول جدید در دایرکتوری ریشه وبسایت خود نصب کردهاید. سپس باید موارد مربوط به تأییدیه ورود را انجام داده و از طریق مرورگر، از اپلیکیشن خود بازدید نمایید.
در صورتی که چنین کاری را انجام ندادهاید، فرمانهای زیر را اجرا نمایید.
php
1composer create-project --prefer-dist laravel/laravel ecommerce23cd ecommerce45composer require laravel/ui67php artisan ui bootstrap --auth89npm install1011npm run dev
یک پایگاه Mysql جدید برای ecommerce بسازید.
php
1mysql -u root -p23Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.45mysql> create database ecommerce ;67Query OK, 1 row affected (0.24 sec)
در ویرایشگر PHP خودتان، پروژه لاراول ecommerce را باز کنید. ابزار مورد استفاده در اینجا PHPStorm است. سپس فایل تنظیمات .env پروژه را ویرایش کنید تا با جزئیات پایگاه داده مطابقت داشته باشد.
سپس فرمان php artisan migrate را اجرا کنید تا کاربران و جداول بازیابی پسورد در پایگاه داده ecommerce ساخته شود.
طرح پایگاه داده لاراول و Redis
برای درک بهتر نقش Redis در ذخیره داده، در ادامه طرحی از یک پایگاه داده را بررسی میکنیم. منظور از «طرح» یا “schema” در اینجا، سازماندهی داده به عنوان علامتی از نحوه تشکیل پایگاه داده است و بنابراین، یک موضوع چندان پیچیده نیست.
اضافهکردن یک محصول
خطوط زیر را به فایل روت web.php خودتان اضافه کنید.
نهایتاً ProductController خود را بروزرسانی کنید تا با کد زیر مطابقت داشته باشد.
php
1<?php23namespace App\Http\Controllers;45use Illuminate\Http\Request;67use Illuminate\Support\Facades\Redis;89class ProductController extends Controller1011{1213public function __construct()1415{1617$this->middleware('auth');1819}2021public function create()2223{2425return view('products.create');2627}2829public function store(Request $request)3031{3233$tags = explode(',',$request->get('tags'));3435$productId = self::getProductId();3637if(self::newProduct($productId, [3839'name' => $request->get('product_name'),4041'image' => $request->get('product_image'),4243'product_id' => $productId4445])){4647self::addToTags($tags);4849self::addToProductTags($productId, $tags);5051self::addProductToTags($productId, $tags);5253}5455return redirect()->route('product.all');5657}5859public function viewProducts()6061{6263$tags = Redis::sMembers('tags');6465$products = self::getProducts();6667return view('products.browse')->with([6869'products' => $products,7071'tags' => $tags7273]);7475}7677/*7879* Increment product ID every time8081* a new product is added, and return8283* the ID to be used in product object8485*/8687static function getProductId()8889{9091(!Redis::exists('product_count'))9293Redis::set('product_count',0);9495 9697return Redis::incr('product_count');9899}100101/*102103* Create a hash map to hold a project object104105* e.g HMSET product:1 product "men jean" id 1 image "img-url.jpg"106107* Then add the product ID to a list hold all products ID's108109*/110111static function newProduct($productId, $data) : bool112113{114115self::addToProducts($productId);116117return Redis::hMset("product:$productId", $data);118119}120121/*122123* A Ordered Set holding all products ID with the124125* PHP time() when the product was added as the score126127* This ensures products are listed in DESC when fetched128129*/130131static function addToProducts($productId) : void132133{134135Redis::zAdd('products', time(), $productId);136137}138139/*140141* A unique Sets of tags142143*/144145static function addToTags(array $tags)146147{148149Redis::sAddArray('tags',$tags);150151}152153/*154155* A unique set of tags for a particular product156157* eg SADD product:1:tags jean men pants158159*/160161static function addToProductTags($productId, $tags)162163{164165Redis::sAddArray("product:$productId:tags",$tags);166167}168169/*170171* A List of products carry this particular tag172173* ex1 RPUSH men 1 3174175* ex2 RPUSH women 2 4176177*/178179static function addProductToTags($productId, $tags)180181{182183foreach ($tags as $tag){184185Redis::rPush($tag,$productId);186187}188189}190191/*192193* In a real live example, we will be returning194195* paginated data by calling the lRange command196197* lRange start end198199*/200201static function getProducts($start = 0, $end = -1) : array202203{204205$productIds = Redis::zRange('products', $start, $end, true);206207$products = [];208209foreach ($productIds as $productId => $score)210211{212213$products[$score]= Redis::hGetAll("product:$productId");214215}216217return $products;218219}220221}
حالا اگر در مرورگرتان به آدرس /products/create بروید، با یک فرم ایجاد یک محصول جدید روبرو میشوید.
برای سادهسازی بیشتر آموزش استفاده از لاراول و Redis، در اینجا لیستی از ۵ محصول به همراه یک تصویر از آنها را در سرور s3 آماده کردهایم تا کار را با آنها شروع کنید. استفاده از آدرس تصاویر تنها به منظور پیشبرد اهداف این آموزش است و مسلماً برای کارهای حرفهای چنین کاری توصیه نمیشود.
پس از اضافه کردن تمام محصولات به ترتیب دلخواه، احتمالاً با چیزی شبیه به زیر روبرو میشوید.
نمونه نمایش محصول
فیلتر کردن بر اساس برچسبها
گاهی اوقات میخواهیم که با کلیک بر روی یک برچسب، به تمام محصولات مرتبط با آن دست پیدا کنیم. برای این منظور، یک متد جدید به ProductController اضافه کنید.
همانطور که مشاهده میکنید، امکانات زیادی در استفاده از Redis به عنوان پایگاه داده وجود دارد. به عنوان یک تمرین یا چالش بیشتر میتوانید نمایش یک محصولات و محصولات مشابه را در زیر آن امتحان کنید.
راهنمایی: محصولات مشابه از تگهای یکسان با محصولی که نمایش داده میشود، استفاده میکنند.