Redis یک پایگاهدادهی کلید-مقدار است که داده را در حافظهی RAM نگه میدارد، نه روی دیسک. به همین دلیل خواندن و نوشتن در آن معمولاً زیر یک میلیثانیه طول میکشد. کاربرد اصلیاش جایی است که سرعت مهمتر از نگهداری بلندمدت است: کش کردن نتیجهی کوئریهای سنگین، نگهداری سشن کاربران، صف کارهای پسزمینه، شمارندهها و محدود کردن تعداد درخواست.
Redis معمولاً جایگزین MySQL یا PostgreSQL نیست؛ کنار آنها مینشیند. پایگاهدادهی اصلی منبع حقیقت است و Redis لایهای سریع برای چیزهایی که یا موقتیاند یا میشود دوباره ساختشان. در ادامه میبینیم Redis دقیقاً به چه دردی میخورد، چطور با Docker اجرایش کنیم، چطور امنش کنیم و کی اصلاً لازمش نداریم.
Redis چطور کار میکند
هر چیزی در Redis یک کلید دارد، مثل user:42:profile، و یک مقدار. تفاوتش با یک دیکشنری ساده در این است که مقدار میتواند ساختار دادهی کامل باشد (لیست، مجموعه، هش و...) و Redis برای هر کدام دستورهای اتمی دارد. «اتمی» یعنی اگر صد درخواست همزمان یک شمارنده را زیاد کنند، نتیجه دقیقاً صد واحد بیشتر است.
دو ویژگی دیگر هم مهم است:
- TTL: هر کلید میتواند تاریخ انقضا داشته باشد و خودش پاک شود. برای کش و سشن عالی است.
- تکنخی بودن اجرای دستورها: دستورها یکییکی اجرا میشوند، پس مسئلهی همزمانی ساده میشود. در عوض، یک دستور سنگین مثل
KEYS *روی میلیونها کلید همه را معطل میکند.
کاربردهای اصلی Redis
کش
رایجترین کاربرد. نتیجهی یک کوئری یا محاسبهی سنگین را برای مدتی در Redis میگذارید و درخواستهای بعدی از آنجا میخوانند. اینکه چه چیزی را و چقدر کش کنید، موضوع مقالهی کش در لاراول؛ کجا و تا کی است.
سشن
وقتی برنامه روی بیش از یک سرور اجرا میشود، سشنهای فایلی جواب نمیدهند، چون هر سرور فایلهای خودش را دارد. Redis یک محل مشترک و سریع برای سشن همهی سرورهاست.
صف
لیستهای Redis پایهی خوبی برای صف کارهای پسزمینهاند. Laravel، Sidekiq در Ruby و Celery و RQ در Python همه از Redis به عنوان صف پشتیبانی میکنند. جزئیات صف در Laravel را در این مقاله نوشتهایم.
محدود کردن نرخ درخواست
«هر IP حداکثر ۶۰ درخواست در دقیقه». با INCR و EXPIRE این کار چند خط است و بین همهی سرورها یکسان کار میکند.
Pub/Sub
یک بخش پیام منتشر میکند و هر کس مشترک آن کانال است، فوراً دریافتش میکند. برای اعلانهای لحظهای مناسب است، با این قید که اگر مشترکی در آن لحظه وصل نباشد، پیام را از دست میدهد. برای پیامهایی که نباید گم شوند، Redis Streams گزینهی بهتری است.
انواع داده با مثال redis-cli
این دستورها را میشود مستقیم در شل اجرا کرد؛ اگر وارد محیط تعاملی redis-cli شدهاید، خود کلمهی redis-cli و توضیح بعد از # را ننویسید.
String؛ سادهترین نوع، برای کش و شمارنده:
redis-cli SET page:home "<html>...</html>" EX 300 # با انقضای ۳۰۰ ثانیه
redis-cli GET page:home
redis-cli TTL page:home # چند ثانیه مانده
redis-cli INCR stats:visits # شمارندهی اتمی
Hash؛ مثل یک رکورد با چند فیلد:
redis-cli HSET user:42 name "Sara" plan "pro"
redis-cli HGET user:42 plan
redis-cli HGETALL user:42
List؛ صف یا آخرین موارد:
redis-cli LPUSH jobs "send-invoice:1001"
redis-cli RPOP jobs
redis-cli LRANGE recent:posts 0 9 # ده مورد اول
Set؛ مجموعهی بدون تکرار:
redis-cli SADD online:users 42 57 91
redis-cli SISMEMBER online:users 42
redis-cli SCARD online:users
Sorted Set؛ مجموعه با امتیاز، برای جدول ردهبندی:
redis-cli ZADD leaderboard 1500 "ali" 2100 "sara" 1800 "reza"
redis-cli ZRANGE leaderboard 0 2 REV WITHSCORES # سه نفر اول
و الگوی محدود کردن نرخ:
redis-cli INCR rate:203.0.113.5
redis-cli EXPIRE rate:203.0.113.5 60 NX # فقط اگر انقضا نداشت
اگر مقدار برگشتی INCR از ۶۰ بیشتر شد، درخواست را رد میکنید. گزینهی NX در EXPIRE از Redis 7 به بعد وجود دارد.
ماندگاری: RDB و AOF
داده در RAM است، پس با ریاستارت چه میشود؟ Redis دو روش برای نوشتن روی دیسک دارد:
| روش | چطور کار میکند | مزیت | عیب |
|---|---|---|---|
| RDB | هر چند وقت یک عکس کامل از داده در فایل dump.rdb |
فایل فشرده، بالا آمدن سریع | تغییرات بعد از آخرین عکس از دست میرود |
| AOF | هر دستور نوشتن به انتهای یک فایل اضافه میشود | با appendfsync everysec حداکثر حدود یک ثانیه داده از دست میرود |
فایل بزرگتر، بازسازی کندتر |
برای صف و سشن، AOF را روشن کنید. برای کش خالص، حتی میشود ماندگاری را کامل خاموش کرد؛ کش خالی فقط یعنی چند درخواست اول کندتر است.
چرا Redis پایگاهدادهی اصلی شما نیست
- حجم داده محدود به RAM است و RAM گرانتر از دیسک است.
- کوئریگیری ندارد: نمیشود پرسید «سفارشهای ماه گذشتهی کاربران تهران». فقط با کلید دسترسی دارید.
- روابط، قیود و تراکنش به معنای SQL ندارد.
- حتی با AOF، تضمینهای ماندگاریاش به پای یک پایگاهدادهی رابطهای نمیرسد.
قاعدهی ساده: اگر کلیدی از Redis پاک شود، باید بتوانید از پایگاهدادهی اصلی دوباره بسازیدش. برای انتخاب پایگاهدادهی اصلی، این مقاله را ببینید.
اجرای Redis با Docker
اگر Docker ندارید، اول Docker را روی Ubuntu 24.04 نصب کنید. بعد:
docker run -d --name redis \
--restart unless-stopped \
-p 127.0.0.1:6379:6379 \
-v redis-data:/data \
redis:8-alpine \
redis-server --appendonly yes --requirepass "$REDIS_PASSWORD"
دقت کنید که پورت به 127.0.0.1 بسته شده است. اگر فقط -p 6379:6379 بنویسید، Docker پورت را روی همهی کارتهای شبکه باز میکند و قانونهای ufw را هم دور میزند.
برای تست:
docker exec -it redis redis-cli
AUTH <your-password>
PING
در یک پروژه با Docker Compose، بهتر است Redis اصلاً پورتی به بیرون منتشر نکند و برنامه از طریق شبکهی داخلی Compose با نام سرویس به آن وصل شود:
services:
redis:
image: redis:8-alpine
command: ["redis-server", "--appendonly", "yes", "--requirepass", "${REDIS_PASSWORD}"]
volumes:
- redis-data:/data
restart: unless-stopped
volumes:
redis-data:
جزئیات Compose را در Docker Compose به زبان ساده توضیح دادهایم. بدون Docker هم روی Ubuntu با sudo apt install redis-server نصب میشود.
برای اتصال Laravel، در .env کافی است:
REDIS_CLIENT=phpredis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=your-password
REDIS_PORT=6379
CACHE_STORE=redis
SESSION_DRIVER=redis
QUEUE_CONNECTION=redis
امنیت: حداقلهایی که نباید فراموش شود
Redis برای اجرا در شبکهی مورد اعتماد طراحی شده است. یک Redis باز روی اینترنت، در زمان کوتاهی پیدا و سوءاستفاده میشود.
- هرگز پورت 6379 را روی اینترنت باز نکنید. در فایل
redis.confمقدارbind 127.0.0.1 -::1بماند وprotected-mode yesخاموش نشود. - رمز بگذارید، با
requirepassیا بهتر، با ACL و کاربر جداگانه برای هر برنامه. - فایروال را طبق چکلیست ساعت اول سرور تنظیم کنید و یادتان باشد پورتهای Docker از ufw رد میشوند.
- دستورهای خطرناک مثل
FLUSHALLوCONFIGرا برای کاربر برنامه با ACL ممنوع کنید. - حافظه را محدود کنید: با
maxmemoryسقف بگذارید. برای کش، سیاستallkeys-lruمناسب است؛ برای صف ازnoevictionاستفاده کنید تا Redis بیصدا کار شما را پاک نکند.
کی Redis لازم نیست
Redis یک سرویس دیگر است که باید نصب، مانیتور، بهروز و پشتیبانگیری شود. این موارد معمولاً بدون آن هم خوب کار میکنند:
- سایت کوچک روی یک سرور: کش فایلی یا پایگاهدادهای Laravel و صف
databaseبرای شروع کاملاً کافی است. - وقتی کندی از کوئری بد است: اول ایندکس بگذارید و کوئری را درست کنید. کش کردن کوئری بد، مشکل را پنهان میکند، حلش نمیکند.
- هاست اشتراکی که اجازهی اجرای Redis نمیدهد؛ در این حالت شاید وقت مهاجرت به VPS باشد، نه دور زدن مسئله.
نشانههای اینکه وقتش رسیده: پایگاهداده زیر بار خواندنهای تکراری کند شده، برنامه روی بیش از یک سرور اجرا میشود و سشن مشترک میخواهد، یا صف database دیگر جواب حجم کارها را نمیدهد.
یک نکتهی جانبی: در سال ۲۰۲۴ مجوز Redis تغییر کرد و پروژهی متنباز Valkey از آن جدا شد؛ از Redis 8 گزینهی مجوز متنباز AGPL دوباره اضافه شده است. برای بیشتر پروژهها، هر دو با دستورها و کلاینتهای یکسان کار میکنند.
جمعبندی
Redis یک انبار کلید-مقدار در حافظه است: بسیار سریع، با ساختارهای دادهی کاربردی و TTL. برای کش، سشن، صف، شمارنده و محدودیت نرخ ابزار درجهیکی است، ولی منبع حقیقت دادههای شما نیست. با Docker در یک دقیقه بالا میآید؛ فقط آن را به 127.0.0.1 یا شبکهی داخلی ببندید، رمز بگذارید و سقف حافظه تعیین کنید. و اگر سایتتان کوچک است، تا وقتی نشانهی واقعی نیاز ندیدهاید، اضافهاش نکنید. مستندات رسمی در redis.io/docs است.