Сессии В Redis И Время Жизни Корзины

Если вопрос для кого-то еще актуален, или если кто-то столкнулся с такой проблемой, то есть решение. Напишу на эту тему лонгрид.

По-умолчанию время жизни сессий (ключей) в Redis безгранично, то есть всегда хранится в ОЗУ и периодически (в зависимости от заданных настроек) вся информация сбрасывается в файл на диск, чтоб при перезагрузке сервера её можно было восстановить без потерь для пользователей. Сначала немного тестов.

Настройками CS Cart задано ограничение на время жизни ключей. Причем есть разные настройки.

В корневой папке сайта, в файле config.php есть строки:

// Session live time
define('SESSION_ALIVE_TIME', SECONDS_IN_HOUR * 2); // 2 hours
Эти строки формируют общее время жизни всех сессий (ttl) - авторизованных (пользователей, вошедших в админку или в личный кабинет) и нет.
В папке app/Tygh/Backend/Session/ лежит файл Redis.php, в котором указаны такие строки, которые формируют время жизни только неавторизованных сессий:
// An additional hour is needed because Redis may delete the record before the gc() method will be invoked,
// an record will not be transferred to the stored sessions storage.
$this->query('setTimeout', $this->id($sess_id), $this->config['ttl'] + SECONDS_IN_HOUR);
Эти строки, по формуле, в сумме дают общее время жизни неавторизованных сессий (ключей), получаем результат: 2 часа жизни сессий + секунды в одном часе = 3 часа (10 800 секунд). Столько живут ключи неавторизованных пользователей, которые отложили товар в закладки или добавили товар в корзину, а потом покинули сайт и не заходили на него за это время.
Проверить теорию можно легко, например подключившись к серверу через Putty:
1) Вводите команду redis-cli
2) Зайдите с другого браузера на свой сайт и добавляете товар в корзину. При заходе создается сессия (ключ).
3) В Putty вводите команду keys "session:*" - отобразится весь список ключей
4) Выбираете последний ключ (например session:1c4a15927d66ea5bdc0212d7a1781635-1-C, но предупреждаю, если есть заходы на сайт от других пользователей, то определить, какой ключ именно ваш, будет проблемно),
5) Вводите команду ttl session:1c4a15927d66ea5bdc0212d7a1781635-1-C (скопировать в Putty имя ключа можно просто выделив его, а вставить нажатием правой кнопки мыши)
6) После ввода команды отобразится время жизни выбранного ключа: например, (integer) 10873
То есть видно, что идет отсчет секунд, как сессия умрет и корзина очистится, а начало отсчета совпадает со временем, указанным в конфигурации файла Redis.php в CS Cart.
Чтобы убедиться, что это действительно так, в Putty укажите следующую команду на тот же самый ключ:
expire session:1c4a15927d66ea5bdc0212d7a1781635-1-C 15 - эта команда изменит время жизни сессии на 15 секунд.
Обновите страницу сайта через 15 секунд и увидите, что ваша корзина и список товаров в закладках очистился (при условии, что изначально вы выбрали именно ваш ключ, а не другого пользователя).
А теперь решение, как увеличить время жизни ключей неавторизованных пользователей, чтоб корзина и закладки хранились дольше.
Способ 1. Увеличить общее время всех сессий.
В файле config.php найдите строку:
// Session live time
define('SESSION_ALIVE_TIME', SECONDS_IN_HOUR * 2); // 2 hours
И поменяйте её на:
// Session live time
define('SESSION_ALIVE_TIME', SECONDS_IN_DAY * 7); // one week (количество дней можете задать свои)

Перезапускать службу redis или чистить кэш не обязательно. Таким образом время ваших новых сессий на сайте будет равно одной неделе (604 800 секунд). Если проверять новые ключи через команду ttl, то у всех ключей отсчет будет начинаться именно со значения 604800 и корзина с закладками у неавторизованных пользователей будет храниться неделю.

Важные моменты:

а) если в течение недели пользователь будет заходить на сайт, то время ключа будет обновляться обратно к неделе, то есть, в теории, время жизни ключа будет бесконечным, если пользователь будет периодически заходить на сайт до истечения время жизни его ключа. 1 пользователь = 1 ключ.

б) время жизни сессии в админке и в личном кабинете пользователей тоже станет одна неделя. То есть не придется каждый раз авторизовываться при заходе, а разъединение с админкой и с личным кабинетом произойдет через неделю, если вы или пользователь в течении этого времени не заходили туда.

Способ 2. Увеличить время жизни только неавторизованных сессий.

В файле Redis.php найдите строку:

// An additional hour is needed because Redis may delete the record before the gc() method will be invoked,

// an record will not be transferred to the stored sessions storage.
$this->query('setTimeout', $this->id($sess_id), $this->config['ttl'] + SECONDS_IN_HOUR);
И поменяйте её на:

// An additional hour is needed because Redis may delete the record before the gc() method will be invoked,

// an record will not be transferred to the stored sessions storage.
$this->query('setTimeout', $this->id($sess_id), $this->config['ttl'] + SECONDS_IN_DAY * 7);

Аналогично первому способу, время новых сессий теперь будет равно неделе. Но отличие в том, что время жизни авторизации админки или личного кабинета останется два часа. На жизнь корзины и закладок неавторизованных пользователей это не повлияет, они будут жить неделю и обновляться при периодическом заходе на сайт.

Вот и все. Несколько советов.

1) Не стоит забывать о том, что чем больше посетителей, тем больше ключей хранит Redis, поэтому задайте конфигурацию Redis (/etc/redis.conf) под ваш магазин: оптимальную периодичность сброса кэша на диск и лимит размера кэша, при достижении которого Redis будет удалять наименее используемые ключи из списка.

2) По поводу оптимального времени жизни ключей: я считаю, что это неделя. Незаинтересованный покупатель за это время не зайдет на сайт и его ключ спокойно умрет, а заинтересованный будет заходить периодически и тем самым поддерживать жизнь ключа. Авторизованному пользователю так вообще ничего не грозит - его корзина и закладки, видимо, хранятся в другом месте, потому что их время жизни не привязывается ко времени жизни ключей Redis (проверил это на практике).

3) Если вы хотите потестить ключи через Putty, но не знаете какой ключ ваш, то вы можете сопоставить название с куки-файлом из браузера.

В Chrome способ такой:

1) нажимаете слева от адреса сайта в адресной строке значок замка (если есть SSL) или буквы i в кружке

2) В открывшемся окне нажимаете на "Используется столько-то файлов cookie"

3) В новом окне находите в списке папку вашего сайта, в ней находите папку "Файлы cookie" и в ней ищите файл "sid_customer_номер". Нажав на файл, снизу в доп. информации, в строке "Контент" вы увидите полное имя файла, которое, как правило, совпадает с именем ключа в Redis. На время жизни файла в доп. информации внимание обращать не стоит - это время жизни куки-файла, а не ключа Redis.

Надеюсь, вся эта информация окажется кому-то полезной и поможет оптимизировать свой сайт под высокую посещаемость с помощью Redis, не создавая клиентский негатив с пропадающими корзинами и закладками.

4 лайка