Налаштування 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 проти централізованих
Деякі використовують 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
# Розмір окремої сессії (для дебугу надмірних сессій)
redis-cli -p 6380 -a SessionsRedisPassword DEBUG OBJECT "laravel_session:abc123"
Якщо сессії несподівано великі — перевірити, що в них зберігається. Частата помилка: зберігання великих колекцій об'єктів замість тільки ID.
Таймлайн
Налаштування Redis Sessions для Laravel приложення на одному або кількох серверах — 4–8 годин. Включає налаштування окремого Redis інстансу, конфігурацію шифрування, перевірку коректності сессій після деплою.







