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


#1

Всем привет.

Решил навести порядок на сервере, в меру своих способностей. Заодно побороть давнейшую неприятную особенность (или глюк?). В чем нуждаюсь в помощи знающих.

Итак, в попытках ускорить сайт храню сессии в Редис. Я в курсе, что смысла в этом мало, но - тем не менее, это так.

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

Как я полагаю, сессия должна жить +2 недели от последнего посещения данного юзера, на практике же это не всегда так. Я проводил эксперимент на своей машине в разных браузерах - корзина может прожить и неделю и две, а может вдруг ХРЯСЬ - и через день опустеть.

Как я понял, происходит этот в тот момент, когда перезагружается сервер. В итоге все сессии (Редис же держит их в ОЗУ?) слетают

.
Однако в настройках Редис есть

save 900 1
save 300 10
save 60 10000

На диске есть база

/var/redis/6379/dump.rdb - весит 18 мегов (не много ли???) и дата ее - сегодняшним числом. Права к базе 644 (может на 777 сменить?)

В логах есть записи

1309:M 31 Jan 04:38:09.029 * 10 changes in 300 seconds. Saving...
1309:M 31 Jan 04:38:09.032 * Background saving started by pid 19469
19469:C 31 Jan 04:38:09.617 * DB saved on disk
19469:C 31 Jan 04:38:09.621 * RDB: 0 MB of memory used by copy-on-write

То есть база сохраняется без ошибок (правда почему 0 МВ???).

Как я понял, при перезапуске редис должен эту базу с диска читать и все сессии должны восстановиться, однако этого не происходит...

Плиз, помогите, ЧЯДНТ?


#2

Всем привет.

Решил навести порядок на сервере, в меру своих способностей. Заодно побороть давнейшую неприятную особенность (или глюк?). В чем нуждаюсь в помощи знающих.

Итак, в попытках ускорить сайт храню сессии в Редис. Я в курсе, что смысла в этом мало, но - тем не менее, это так.

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

Как я полагаю, сессия должна жить +2 недели от последнего посещения данного юзера, на практике же это не всегда так. Я проводил эксперимент на своей машине в разных браузерах - корзина может прожить и неделю и две, а может вдруг ХРЯСЬ - и через день опустеть.

Как я понял, происходит этот в тот момент, когда перезагружается сервер. В итоге все сессии (Редис же держит их в ОЗУ?) слетают

.
Однако в настройках Редис есть

save 900 1
save 300 10
save 60 10000

На диске есть база

/var/redis/6379/dump.rdb - весит 18 мегов (не много ли???) и дата ее - сегодняшним числом. Права к базе 644 (может на 777 сменить?)

В логах есть записи

1309:M 31 Jan 04:38:09.029 * 10 changes in 300 seconds. Saving...
1309:M 31 Jan 04:38:09.032 * Background saving started by pid 19469
19469:C 31 Jan 04:38:09.617 * DB saved on disk
19469:C 31 Jan 04:38:09.621 * RDB: 0 MB of memory used by copy-on-write

То есть база сохраняется без ошибок (правда почему 0 МВ???).

Как я понял, при перезапуске редис должен эту базу с диска читать и все сессии должны восстановиться, однако этого не происходит...

Плиз, помогите, ЧЯДНТ?

Скорее всего редис тут не причем, я посмотрел - у нас настройки такие же.

Мы сделали куку просто бессмертной у себя, по аналогии с vk, fb и прочими.

В чем может быть дело у вас? Когда будете делать подобный эксперимент, посмотрите не меняется ли session_id в куках на фронте. Дело в том, что она ставится на 2 недели, когда кинули товар в корзину, ей осталось жить как раз день. Мы эту куку регулярно рефрешим, чтобы она не умирала. Вам я думаю нужно делать примерно также.

18 мб это совсем немного, у нас в десятки раз больше.


#3

Скорее всего редис тут не причем, я посмотрел - у нас настройки такие же.

Мы сделали куку просто бессмертной у себя, по аналогии с vk, fb и прочими.
В чем может быть дело у вас? Когда будете делать подобный эксперимент, посмотрите не меняется ли session_id в куках на фронте. Дело в том, что она ставится на 2 недели, когда кинули товар в корзину, ей осталось жить как раз день. Мы эту куку регулярно рефрешим, чтобы она не умирала. Вам я думаю нужно делать примерно также.

18 мб это совсем немного, у нас в десятки раз больше.


Все хорошо, но я же тупой. Я не знаю как эту куку посмотреть. (Ее выйди то бишь) и уж тем более как ее обессмертить.

#4

Все хорошо, но я же тупой. Я не знаю как эту куку посмотреть. (Ее выйди то бишь) и уж тем более как ее обессмертить.

В хроме есть удобное расширение EditThisCookie, вот там можно увидеть список кук, которые есть на сайте.


#5

В хроме есть удобное расширение EditThisCookie, вот там можно увидеть список кук, которые есть на сайте.


Попробую. У меня есть old fashioned магазин, там сессии в файлах, и все работает норм. И с куками не заморачиваюсь. А с этим цс-картом, когда куки тоже были в файле, тоже вроде все норм было.
Да и кажется мне, когда сервак перезагружаешь - вот тогда и отваливаются сессии.

#6

Попробую. У меня есть old fashioned магазин, там сессии в файлах, и все работает норм. И с куками не заморачиваюсь. А с этим цс-картом, когда куки тоже были в файле, тоже вроде все норм было.
Да и кажется мне, когда сервак перезагружаешь - вот тогда и отваливаются сессии.

Когда именно сервер вполне может быть, мы вообще думаем редис выкинуть, он не сильно помогает при высокой нагрузке. Если у вас не так много трафика (судя по 18мб) смело ставьте вообще в БД. Там итак на каждой странице куча запросов, еще парочка не испортит ситуации.


#7

Когда именно сервер вполне может быть, мы вообще думаем редис выкинуть, он не сильно помогает при высокой нагрузке. Если у вас не так много трафика (судя по 18мб) смело ставьте вообще в БД. Там итак на каждой странице куча запросов, еще парочка не испортит ситуации.

Только когда сервер.

#8

Только когда сервер.

Я думал, что у вас проблемы когда redis server перегружается.

Ставьте в БД хранилище ) я думаю все нормально у вас будет.


#9

Я думал, что у вас проблемы когда redis server перегружается.

Ставьте в БД хранилище ) я думаю все нормально у вас будет.

Черт, глянул в конфиг, ау меня COOKIE_ALIVE_TIME = 1 неделя, когда SESSION_ALIVE_TIME и SESSIONS_STORAGE_ALIVE_TIME = 2 недели... Как я понял, первое убивает два вторых... Вот почему походу у меня раз в неделю заново в админке валюта сбрасывается...

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

Продолжаю наблюдение.

В БД не хочу пихать, и так блин цс-карт адски тормозной, причем именно из-за работы с БД...

Кстати, нашел тут костыль который ускорит время ответа сервера у меня вдвое... Пока правда нет статистики, только сегодня его применил.


#10

Черт, глянул в конфиг, ау меня COOKIE_ALIVE_TIME = 1 неделя, когда SESSION_ALIVE_TIME и SESSIONS_STORAGE_ALIVE_TIME = 2 недели... Как я понял, первое убивает два вторых... Вот почему походу у меня раз в неделю заново в админке валюта сбрасывается...

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

Продолжаю наблюдение.

В БД не хочу пихать, и так блин цс-карт адски тормозной, причем именно из-за работы с БД...

Кстати, нашел тут костыль который ускорит время ответа сервера у меня вдвое... Пока правда нет статистики, только сегодня его применил.

Чтобы база задышала попробуйте VPS с SSD диском, заметно веселее.


#11

Чтобы база задышала попробуйте VPS с SSD диском, заметно веселее.

Я понимаю, но так сложилось что нет SSD там где я хощусь... Правда и цена - 2 евро в месяц... Может с подоблюсь как оплаченные 2 года закончатся.


#12

Кстати, нашел тут костыль который ускорит время ответа сервера у меня вдвое... Пока правда нет статистики, только сегодня его применил.

Поделитесь "костылем", пожалуйста!


#13

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

По-умолчанию время жизни сессий (ключей) в 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, не создавая клиентский негатив с пропадающими корзинами и закладками.


#14

Способ 1. Увеличить общее время всех сессий.


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

ПОЧЕМУ время от времени корзина очищается явно не по таймауту? У меня есть подозрение на перезагрузку сервера, ибо просто перезапуск службы httpd не очищает корзину.

Корзина живет день, два , три, пять (у меня куча браузеров, специально один из них "бросаю") но вдруг может очиститься на следующий день.

Я пока строгой закономерности не уловил.

#15

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

ПОЧЕМУ время от времени корзина очищается явно не по таймауту? У меня есть подозрение на перезагрузку сервера, ибо просто перезапуск службы httpd не очищает корзину.

Корзина живет день, два , три, пять (у меня куча браузеров, специально один из них "бросаю") но вдруг может очиститься на следующий день.

Я пока строгой закономерности не уловил.

Во время своих тестов не сталкивался с такой ситуацией, все работает, как часы. Проверку я осуществлял на двух ноутбуках, в браузерах IE, Edge, Yandex, Firefox, Chrome, Opera и на двух смартфонах в Safari. То есть общее количество моих сессий составляло 14. Ни в одной из них за неделю после выставления вышеуказанных параметров не очистилась корзина. Была и перезагрузка сервера, и отключение тестового сервера в связи с неуплатой - результат один, данные восстанавливаются из кэша с диска.

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

Также проверьте конфигурацию Redis, может что-то настроено не так, как нужно.


#16

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


#17

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


Наблюдаю.

Еще такое есть сомнение по поводу сессий в Редисе. Так как они хранятся в ОЗУ и, если оно закончилось (maxmemory) то политика кеша выкидывает сессии, к которым обращения не было наиболее давно.

Но, с недавних пор Яндекс перестал принимать куки (точнее с давних, уже года два или три), соответственно 1000 страниц прошел = 1000 сессий образовалось.

У меня есть старый сайт, там это привело к переполнению диска, мне пришлось создавать отдельную директорию для сессий роботов и через хрон чистить ее раз в сутки.

НО! в ЦС-Карт я такого не наблюдаю, то есть при 3500 страницах сайта и обходе роботами примерно 1000 в сутки (то есть минимум Яндекс плодит 1000 в сутки * 28 дней = 28 000 сессий), у меня количество сессий очень похоже на количество посетителей...

Возможно, это как-то решено? Но как?

#18

Наблюдаю.

Еще такое есть сомнение по поводу сессий в Редисе. Так как они хранятся в ОЗУ и, если оно закончилось (maxmemory) то политика кеша выкидывает сессии, к которым обращения не было наиболее давно.

Но, с недавних пор Яндекс перестал принимать куки (точнее с давних, уже года два или три), соответственно 1000 страниц прошел = 1000 сессий образовалось.

У меня есть старый сайт, там это привело к переполнению диска, мне пришлось создавать отдельную директорию для сессий роботов и через хрон чистить ее раз в сутки.

НО! в ЦС-Карт я такого не наблюдаю, то есть при 3500 страницах сайта и обходе роботами примерно 1000 в сутки (то есть минимум Яндекс плодит 1000 в сутки * 28 дней = 28 000 сессий), у меня количество сессий очень похоже на количество посетителей...

Возможно, это как-то решено? Но как?

Я очень советую вам сессии запускать только, когда человек что-то хочет добавить в корзину или логинится.

Мы у себя в проекте так сделали, иначе мусорных сессий будет море. В коробке это точно никак не решается.


#19

Я очень советую вам сессии запускать только, когда человек что-то хочет добавить в корзину или логинится.

Мы у себя в проекте так сделали, иначе мусорных сессий будет море. В коробке это точно никак не решается.

Подскажите, пожалуйста, каким способом это можно реализовать? Необходимы изменения со стороны конфигурации сервера или конфигурации CS Cart?


#20

Подскажите, пожалуйста, каким способом это можно реализовать? Необходимы изменения со стороны конфигурации сервера или конфигурации CS Cart?


Конечно, править код. Сейчас session_start() выполняется сразу, а надо если логин или если корзина.

Но ч бы ни в коем случае не стал так делать- сессия весит мало, но зато так надежнее.