Если ваше приложение на Laravel использует драйвер сессий  database  или  file , просроченные сессии остаются в хранилище до тех пор, пока Laravel их не удалит. Начиная с Laravel 13.39 и новее, вы можете удалять их с помощью Artisan-команды  session:garbage-collect  по расписанию:

// routes/console.php
use Illuminate\Support\Facades\Schedule;

Schedule::command('session:garbage-collect')->hourly();

Эта команда выполняет ту же очистку, которую Laravel и так запускает во время некоторых веб-запросов. Если добавить команду в расписание и отключить лотерею, ни один веб-запрос не будет ждать завершения очистки.

Примечание: Драйверы  redis ,  memcached ,  dynamodb ,  apc  и  cookie  удаляют сессии по истечении срока действия без этапа очистки, поэтому приложениям, использующим их, эта команда не нужна.

#Отключение лотереи сессий

Без запланированной команды Laravel удаляет истекшие сессии во время обработки веб-запросов. Опция  lottery  в файле  config/session.php  определяет частоту:

'lottery' => [2, 100],

Эти два числа представляют собой вероятность. Значение по умолчанию  [2, 100]  дает каждому запросу, который инициирует сессию, шанс 2 из 100 запустить очистку. Такой запрос выполняет удаление до того, как дойдет до вашего роута, и ждет его завершения.

Вероятность остается неизменной независимо от вашего трафика. При 1 000 запросах в минуту примерно 20 запросов в минуту запускают удаление, и некоторые из них могут пересекаться. При 40 запросах в день очистка запускается реже одного раза в день, и истекшие сессии остаются в хранилище до этого момента.

Как только планировщик начнет удалять просроченные сессии, установите первое число в значение  0 . Шанс 0 из 100 означает, что ни один веб-запрос не будет запускать очистку:

// config/session.php
'lottery' => [0, 100],

Если оставить значение  [2, 100] , лотерея и команда будут удалять одни и те же истекшие сессии, и единственной платой за это будут лишние запросы к базе данных.

#Каким драйверам сессий нужна очистка

Драйвер Что делает очистка
 database  Удаляет строки, где  last_activity  старше времени жизни сессии
 file  Удаляет файлы сессий, которые старше времени жизни
 redis ,  memcached ,  dynamodb ,  apc  Ничего. Кэш-хранилище само завершает срок действия каждой сессии по TTL
 cookie  Ничего. Сессия хранится в браузере

В новых приложениях на Laravel 13 по умолчанию используется драйвер  database , а стандартная миграция  sessions  создает индекс для  last_activity , по которому выполняется фильтрация в запросе на удаление.

Пользователи не смогут загрузить истекшую сессию до запуска очистки, так как оба драйвера проверяют возраст сессии при её чтении. Очистка лишь освобождает место в хранилище, занятое просроченными сессиями.

#Запуск session:garbage-collect

Запустите команду вручную, чтобы проверить её перед добавлением в расписание:

php artisan session:garbage-collect
INFO  Session garbage collector ran successfully.

Команда использует ваш драйвер сессий по умолчанию и  session.lifetime , без опций для их изменения. Она не выводит количество удаленных сессий. При использовании драйвера на основе кэша она выведет то же сообщение об успешном завершении, но ничего не удалит.

Почасовой запуск — разумное расписание для стандартного времени жизни сессии в 120 минут. В этом случае просроченная сессия будет оставаться в хранилище максимум один час.

#Запуск очистки сессий на нескольких серверах

При использовании драйвера базы данных каждый сервер, на котором запущен планировщик, будет выполнять одинаковое удаление. Добавьте  onOneServer() , чтобы очистку выполнял только один сервер. Для блокировки ему потребуется общее кэш-хранилище:

Schedule::command('session:garbage-collect')
    ->hourly()
    ->onOneServer();

Если ваше приложение вызывает  Schedule::alwaysOnOneServer() , добавлять это не нужно. Информацию о такой настройке смотрите в статье Запуск планировщика Laravel на нескольких серверах.

При использовании файлового драйвера каждый сервер хранит свои собственные файлы сессий, поэтому запускайте команду на каждом сервере. Добавляйте  onOneServer()  только в том случае, если директория сессий находится на общем сетевом хранилище.

#Удаление просроченных сессий в версиях до Laravel 13.39

В Laravel 13.38 и более ранних версиях эта команда завершается с ошибкой  Command "session:garbage-collect" is not defined. . Запланируйте замыкание (closure), которое выполняет тот же вызов, что и команда:

// routes/console.php
use Illuminate\Support\Facades\Schedule;

Schedule::call(function () {
    app('session')->driver()->getHandler()->gc((int) config('session.lifetime') * 60);
})->name('delete-expired-sessions')->hourly()->onOneServer();

Замыкание получает обработчик для вашего драйвера сессий по умолчанию и вызывает его метод  gc() . Значение  session.lifetime  указано в минутах, а  gc()  ожидает секунды, поэтому время жизни умножается на 60.

Это работает в Laravel 11, 12 и 13. Запланированному замыканию требуется  name()  перед  onOneServer() , иначе Laravel выбросит исключение. В Laravel 10 добавьте замыкание в метод  schedule()  в файле  app/Console/Kernel.php  с помощью  $schedule->call() .

Затем настройте  'lottery' => [0, 100] , как показано выше.

#Дополнительные материалы

Andrew Brown добавил  session:garbage-collect  в пул-реквесте #62104, а Volodya Kurshudyan зарегистрировал его в Artisan в #62150.