Настройка Redis для хранения сессий веб-приложения
Файловые сессии не масштабируются горизонтально — если у вас два веб-сервера, пользователь, попавший на второй сервер, потеряет сессию с первого. Redis решает это: централизованное хранилище сессий доступно всем серверам. Дополнительно Redis быстрее файловой системы при высокой нагрузке и позволяет устанавливать TTL на каждую сессию.
Конфигурация Redis для сессий
Сессии — данные, которые нельзя терять (пользователь разлогинится). Настройки Redis для сессий отличаются от настроек кэша:
# Персистентность обязательна для сессий
appendonly yes
appendfsync everysec
# Политика вытеснения: не трогать ключи без TTL
# Если используете Redis только под сессии:
maxmemory-policy volatile-lru
# Если Redis shared (кэш + сессии):
# Сессии кладите с TTL, политика volatile-lru защитит их от вытеснения
Отдельный инстанс Redis под сессии (рекомендуется):
# /etc/redis/redis-sessions.conf
port 6380
bind 127.0.0.1
requirepass SessionsRedisPassword
maxmemory 512mb
maxmemory-policy volatile-lru
appendonly yes
appendfsync everysec
databases 1
Laravel Session Driver
config/session.php:
return [
'driver' => env('SESSION_DRIVER', 'redis'),
'lifetime' => env('SESSION_LIFETIME', 120),
'expire_on_close' => false,
'encrypt' => env('SESSION_ENCRYPT', true), // Шифрование данных сессии
'files' => storage_path('framework/sessions'),
'connection' => 'sessions', // Отдельное redis подключение
'table' => 'sessions',
'store' => null,
'lottery' => [2, 100],
'cookie' => env('SESSION_COOKIE', 'laravel_session'),
'path' => '/',
'domain' => env('SESSION_DOMAIN'),
'secure' => env('SESSION_SECURE_COOKIE', true), // HTTPS только
'http_only' => true,
'same_site' => 'lax',
];
Добавить sessions подключение в config/database.php:
'redis' => [
'sessions' => [
'host' => env('REDIS_SESSION_HOST', '127.0.0.1'),
'password' => env('REDIS_SESSION_PASSWORD'),
'port' => env('REDIS_SESSION_PORT', '6380'),
'database' => 0,
'read_timeout' => 60,
'persistent' => false,
],
],
.env:
SESSION_DRIVER=redis
SESSION_LIFETIME=120
SESSION_ENCRYPT=true
REDIS_SESSION_HOST=127.0.0.1
REDIS_SESSION_PASSWORD=SessionsRedisPassword
REDIS_SESSION_PORT=6380
Шифрование данных сессии
SESSION_ENCRYPT=true включает шифрование содержимого сессии через APP_KEY. Даже если получить доступ к Redis, данные сессии нечитаемы без ключа приложения.
Важно: APP_KEY должен быть уникальным и храниться в безопасном месте. Ротация ключа инвалидирует все сессии.
PHP-FPM + Redis Sessions (без Laravel)
Нативная настройка PHP для хранения сессий в Redis:
# /etc/php/8.2/fpm/php.ini или conf.d/redis-sessions.ini
session.save_handler = redis
session.save_path = "tcp://127.0.0.1:6380?auth=SessionsRedisPassword&database=0&weight=1&timeout=2.5"
session.gc_maxlifetime = 7200
session.cookie_secure = 1
session.cookie_httponly = 1
session.cookie_samesite = Lax
session.use_strict_mode = 1
Для Redis Cluster:
session.save_path = "tcp://redis-node1:6379?auth=password,tcp://redis-node2:6379?auth=password,tcp://redis-node3:6379?auth=password"
Управление активными сессиями
Redis позволяет просматривать и принудительно завершать сессии — функция, которую сложно реализовать с файловыми сессиями.
class SessionManager
{
private Redis $redis;
private string $prefix = 'laravel_session:';
public function getUserSessions(int $userId): array
{
// Если при создании сессии сохранять user_id -> session_id mapping
$sessionIds = $this->redis->smembers("user_sessions:{$userId}");
$sessions = [];
foreach ($sessionIds as $sessionId) {
$data = $this->redis->get($this->prefix . $sessionId);
if ($data) {
$ttl = $this->redis->ttl($this->prefix . $sessionId);
$sessions[] = [
'id' => $sessionId,
'ttl' => $ttl,
'data' => $this->decodeSession($data),
];
}
}
return $sessions;
}
public function invalidateUserSessions(int $userId): void
{
$sessionIds = $this->redis->smembers("user_sessions:{$userId}");
$pipe = $this->redis->pipeline();
foreach ($sessionIds as $sessionId) {
$pipe->del($this->prefix . $sessionId);
}
$pipe->del("user_sessions:{$userId}");
$pipe->execute();
}
}
В обработчике входа — сохранять связь пользователя с сессией:
// После успешного Login
$this->redis->sadd("user_sessions:{$user->id}", session()->getId());
$this->redis->expire("user_sessions:{$user->id}", config('session.lifetime') * 60);
Sticky Sessions vs. централизованные
Некоторые используют sticky sessions (nginx ip_hash) вместо централизованного хранилища. Это технический долг: один сервер падает — все его сессии теряются, балансировка нагрузки неравномерна.
Redis-сессии работают правильно: любой сервер обслуживает любого пользователя.
Мониторинг сессий
# Количество активных сессий
redis-cli -p 6380 -a SessionsRedisPassword DBSIZE
# Средний TTL сессий
redis-cli -p 6380 -a SessionsRedisPassword INFO keyspace
# Использование памяти
redis-cli -p 6380 -a SessionsRedisPassword INFO memory | grep used_memory_human
# Размер отдельной сессии (для дебага bloated sessions)
redis-cli -p 6380 -a SessionsRedisPassword DEBUG OBJECT "laravel_session:abc123"
Если сессии неожиданно большие — проверить, что в них хранится. Частая ошибка: хранить в сессии большие коллекции объектов вместо только ID.
Сроки
Настройка Redis Sessions для Laravel приложения на одном или нескольких серверах — 4–8 часов. Включает настройку отдельного Redis инстанса, конфигурацию шифрования, проверку корректности сессий после деплоя.







