Я хочу рассказать об одном нестандартном применении механизма сессий в PHP. Вспомнилось мне это в связи с позавчерашним постом Тормоза на тему, что опять в Даосе проблема с параллельным доступом к файлам - функция блокировки дала очередной сбой. И хотя Тормоз в комментах уже писал, что обкатывает исправленный алгоритм, успешно выдерживающий стресс-тест, я все же поделюсь своим решением. Сразу оговорюсь, все нижеизложенное было проделано just for fun и имеет свои недостатки. Зато и работает практически безотказно.
Перейду к технической части. По умолчанию механизм сессий в PHP использует хранилище данных в файлах - каждая сессия лежит в своем файле. При этом, чтобы обеспечить целостность данных используется нехитрый подход эксклюзивной блокировки доступа к файлу. Иными словами, в момент, когда мы делаем session_start(), движок PHP захватывает файл с требуемой сессией и отпускает ее только в момент явного вызова session_write_close() или завершения скрипта. И если в то время, пока мы работаем с сессией в рамках одного запроса, произойдет еще один запрос, использующий ту же сессию, то он заблокируется на session_start() до тех пор, пока первый не освободит файл. Обычно разные клиенты работают в разных сессиях и проблемы не возникает, однако (немного огрубляю) у одного и того же клиента в один момент времени исполняется только один запрос.
Реально проблема встает, когда во время выполнения некоторого длительного запроса (стримминг потока или long polling) надо обеспечить клиенту возможность посылать и другие запросы (ходить по страничкам) и вовремя получать ответы. Решают задаю обычно одним из трех путей:
Но я отвлекся. В нашем случае мы не только не будем избавляться от этого, но наоборот будем использовать для реализации мьютекса: будем создавать сессию с заранее известным session_id, к примеру db_mutex, выполнять критические действия и закрывать сессию. Именно эту функциональность и реализует мой класс PHP_Mutex.
Надо признать, такой подход имеет ряд недостатков по сравнению с полноценными мьютексами:
Но если все условия удовлетворены (кстати, класс по мере возможности сам отслеживает потенциально проблемные ситуации и выдает ворнинги), то блокировка будет железной - разработчики PHP постарались, чтобы данные сессии были в безопасности в любой среде окружения :) Поэтому класс вполне сгодится в небольших скриптах типа Даоса, где сессии не очень нужны. Ну а в сложных системах можно прибегнуть и к тяжелой артиллерии вроде встроенных семафоров, у которых лишь один недостаток - по умолчанию они отключены.
Сам класс вы найдете во вложении, распространяется он свободно согласно лицензии New BSD License. Если кому пригодится - на здоровье :-)
Для одного из моих проектов, над которым я сейчас активно работаю понадобилось сделать возможность выполнения длинных запросов с "обратной связью", т. е. с возможностью отсылки информации о ходе выполнения скрипта. Поскольку подключать к проекту какого-нибудь монстра типа JQuery ради одной этой возможности я посчитал нецелесообразным, решено было написать свою простую библиотеку, выполняющую эту функцию. результат я представляю вам в этом посте.
Последние комментарии
/Alek$/ 17 часов 30 минут назад
/Fish/ 20 часов 27 минут назад
/hexkey/ 3 дня 7 часов назад
/Alek$/ 1 неделя 1 день назад
/GrayWolf/ 1 неделя 1 день назад
/Alek$/ 2 недели 22 часа назад
/tachyon/ 2 недели 1 день назад
/Гость/ 2 недели 6 дней назад
/Alek$/ 3 недели 14 часов назад
/Анатолий/ 3 недели 5 дней назад