Redis with Laravel
Redis with Laravel
Laravel provides first-class support for Redis through elegant APIs including Cache, Redis facade, queues, sessions, and broadcasting. Learn how to leverage Redis to build high-performance Laravel applications.
Laravel Redis Configuration
Configure Redis connections in config/database.php:
'redis' => [
'client' => env('REDIS_CLIENT', 'phpredis'),
'options' => [
'cluster' => env('REDIS_CLUSTER', 'redis'),
'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'),
],
'default' => [
'url' => env('REDIS_URL'),
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD'),
'port' => env('REDIS_PORT', 6379),
'database' => env('REDIS_DB', 0),
],
'cache' => [
'url' => env('REDIS_URL'),
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD'),
'port' => env('REDIS_PORT', 6379),
'database' => env('REDIS_CACHE_DB', 1),
],
],
REDIS_CLIENT=phpredis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
REDIS_DB=0
REDIS_CACHE_DB=1
# Or use URL format
REDIS_URL=redis://user:password@127.0.0.1:6379
- phpredis: PHP extension, faster performance (recommended for production)
- predis: Pure PHP library, easier installation, no extension required
pecl install redis && echo "extension=redis.so" > /etc/php/conf.d/redis.iniLaravel Cache Facade
Use Cache facade with Redis driver for high-performance caching:
'default' => env('CACHE_DRIVER', 'redis'),
'stores' => [
'redis' => [
'driver' => 'redis',
'connection' => 'cache',
'lock_connection' => 'default',
],
],
use Illuminate\Support\Facades\Cache;
# Store value for 1 hour
Cache::put('key', 'value', now()->addHours(1));
# Store forever (no expiration)
Cache::forever('key', 'value');
# Retrieve value
$value = Cache::get('key');
# Retrieve with default
$value = Cache::get('key', 'default');
# Retrieve and delete
$value = Cache::pull('key');
# Check existence
if (Cache::has('key')) {
// Key exists
}
# Delete key
Cache::forget('key');
# Clear all cache
Cache::flush();
# Retrieve or store if not exists
$users = Cache::remember('users', 3600, function () {
return DB::table('users')->get();
});
# Remember forever
$settings = Cache::rememberForever('settings', function () {
return DB::table('settings')->get();
});
# Increment/Decrement
Cache::increment('counter');
Cache::decrement('counter');
Cache::increment('counter', 5);
Cache::decrement('counter', 5);
Cache Tags (Redis Only)
Cache tags allow you to group related cache items and flush them together:
# Store with tags
Cache::tags(['users', 'authors'])->put('user:1', $user, 3600);
Cache::tags(['users'])->put('user:2', $user2, 3600);
# Retrieve with tags
$user = Cache::tags(['users'])->get('user:1');
# Flush all items with specific tag
Cache::tags(['users'])->flush();
# Flush multiple tags
Cache::tags(['users', 'authors'])->flush();
# In UserController
public function index()
{
return Cache::tags(['users', 'index'])->remember('users.all', 3600, function () {
return User::all();
});
}
# After user update, invalidate cache
public function update(Request $request, User $user)
{
$user->update($request->all());
Cache::tags(['users'])->flush();
return redirect()->back();
}
Redis Facade - Direct Redis Commands
Use Redis facade for direct access to Redis commands:
use Illuminate\Support\Facades\Redis;
# String operations
Redis::set('name', 'John');
$name = Redis::get('name');
# Hash operations
Redis::hset('user:1', 'name', 'John');
Redis::hset('user:1', 'email', 'john@example.com');
$user = Redis::hgetall('user:1');
# List operations
Redis::lpush('queue:jobs', json_encode($job));
$job = Redis::rpop('queue:jobs');
# Set operations
Redis::sadd('tags', 'php', 'laravel', 'redis');
$tags = Redis::smembers('tags');
# Sorted Set operations
Redis::zadd('leaderboard', 100, 'user:1');
Redis::zadd('leaderboard', 200, 'user:2');
$top = Redis::zrevrange('leaderboard', 0, 9);
# Use default connection
Redis::get('key');
# Use cache connection
Redis::connection('cache')->get('key');
# Define custom connection
$redis = Redis::connection('custom');
$redis->set('key', 'value');
Redis Transactions and Pipelines
Execute multiple commands atomically or in batch:
Redis::transaction(function ($redis) {
$redis->set('key1', 'value1');
$redis->set('key2', 'value2');
$redis->incr('counter');
});
# All commands execute atomically
Pipelines (Batch Commands):
Redis::pipeline(function ($pipe) {
for ($i = 0; $i < 1000; $i++) {
$pipe->set("key:$i", "value$i");
}
});
# Commands sent in single network round trip
Rate Limiting with Redis
Laravel provides Redis-based rate limiting for API endpoints and actions:
use Illuminate\Routing\Middleware\ThrottleRequests;
# In routes/api.php
Route::middleware(['throttle:60,1'])->group(function () {
Route::get('/user', [UserController::class, 'index']);
});
# 60 requests per 1 minute
# Named rate limiter
Route::middleware(['throttle:api'])->group(function () {
// Routes
});
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Support\Facades\RateLimiter;
# In AppServiceProvider
RateLimiter::for('api', function (Request $request) {
return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
});
# Custom rate limit per user tier
RateLimiter::for('api', function (Request $request) {
return $request->user()->isPremium()
? Limit::none()
: Limit::perMinute(100);
});
use Illuminate\Support\Facades\RateLimiter;
$executed = RateLimiter::attempt(
'send-email:'.$user->id,
$maxAttempts = 5,
function () use ($user) {
Mail::to($user)->send(new Newsletter());
},
$decaySeconds = 60
);
if (!$executed) {
return 'Too many emails sent!';
}
Queues with Redis
Use Redis as queue driver for background job processing:
'default' => env('QUEUE_CONNECTION', 'redis'),
'connections' => [
'redis' => [
'driver' => 'redis',
'connection' => 'default',
'queue' => env('REDIS_QUEUE', 'default'),
'retry_after' => 90,
'block_for' => null,
],
],
use App\Jobs\ProcessPodcast;
# Dispatch to queue
ProcessPodcast::dispatch($podcast);
# Dispatch to specific queue
ProcessPodcast::dispatch($podcast)->onQueue('processing');
# Delay execution
ProcessPodcast::dispatch($podcast)->delay(now()->addMinutes(10));
# Run queue worker
php artisan queue:work redis --queue=high,default,low
- Fast job enqueuing and processing
- Multiple queues with priority
- Job retry and failure handling
- Delayed jobs
- Real-time visibility with Horizon
Broadcasting with Redis
Use Redis for real-time event broadcasting with WebSockets:
'default' => env('BROADCAST_DRIVER', 'redis'),
'connections' => [
'redis' => [
'driver' => 'redis',
'connection' => 'default',
],
],
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class OrderShipped implements ShouldBroadcast
{
public $order;
public function broadcastOn()
{
return new Channel('orders.' . $this->order->id);
}
}
# Trigger event
event(new OrderShipped($order));
# Listen with Laravel Echo + Socket.io
Echo.channel('orders.1')
.listen('OrderShipped', (e) => {
console.log(e.order);
});
Session Driver with Redis
Store user sessions in Redis for speed and scalability:
'driver' => env('SESSION_DRIVER', 'redis'),
'connection' => 'default',
.env:
SESSION_DRIVER=redis
SESSION_LIFETIME=120
Cache Locking (Atomic Operations)
Prevent race conditions with distributed locks:
use Illuminate\Support\Facades\Cache;
$lock = Cache::lock('process-orders', 10);
if ($lock->get()) {
try {
// Process orders (exclusive access for 10 seconds)
processOrders();
} finally {
$lock->release();
}
} else {
// Another process is already running
return 'Already processing';
}
# Block until lock is available
$lock->block(5); // Wait up to 5 seconds
// Critical section
$lock->release();
Laravel Horizon - Redis Queue Monitoring
Horizon provides a dashboard for monitoring Redis queues:
composer require laravel/horizon
php artisan horizon:install
php artisan migrate
# Start Horizon
php artisan horizon
# Access dashboard at /horizon
Route::get('/horizon', function () {
return view('horizon::layout');
});
- Real-time queue metrics
- Failed job management
- Job throughput graphs
- Worker monitoring
- Auto-scaling workers
- Job tagging and searching
Best Practices
- ✅ Use Cache::remember() for database query caching
- ✅ Use cache tags to group related cache items
- ✅ Configure separate Redis databases for cache, sessions, queues
- ✅ Use phpredis extension in production for better performance
- ✅ Implement rate limiting for API endpoints
- ✅ Use queues for slow operations (emails, image processing, etc.)
- ✅ Monitor Redis with Laravel Horizon
- ✅ Use cache locks to prevent race conditions
- ✅ Set appropriate TTL values to avoid memory bloat
- ✅ Use Redis for sessions in multi-server deployments