Daos и нагрузки
11.08.2010 технологии мои проекты
У меня есть важный вопрос к программистам. Нужна ваша помощь! Но сперва должен извиниться перед рекламодателями: вчера или сегодня сбросились все рекламные строчки. Извините, восстановить это невозможно.
Почему пропали данные?
В Daos не используются базы данных типа MySQL, всё работает на файлах. В самых первых версиях это иногда было причиной сбоев: при совпадении, когда файл одновременно и запрашивался и записывался. После я выпустил обновление, в котором проблема решалась с помощью встроенного в PHP механизма блокировки файлов (flock).
Однако, всё равно с тех пор было два или три аналогичных инцидента у моих клиентов и вот случилось это и со мной (было бы справедливо, если бы сразу произошло на моей площадке).
А вопрос такой: это из-за моей ошибки в функциях или всё же даже блокировка не может гарантировать сохранность данных? То есть можно обойтись малой кровью и переписать какой-то участочек кода, или в любом случае срочно надо переходить на MySQL?
Вот эти две злополучные функции: http://pastie.org/1084477
Правильно они написаны или есть какая-то трудноуловимая ошибка?
P.S. Есть ещё маленькая вероятность, что проблема локализована где-то снаружи этих функций, а не внутри.
Комментарии
Комментирование этой статьи закрыто.
это пипец. :)
первый раз вижу такой извращенный способ сохранять данные в файл.
может проще сериализовывать? нахрен строку из вар_экспорта в виде пхп кода сохранять а потом эвалить?
у этого твоего даоса исходники открыты?
а вобще я бы рассмотрел. возможность перехода на sqlite. его более чем достаточно для твоих задач.
и файлы лочить надо только при записи. чтение можно без локов делать
+1 за sqlite
я не спец по PHP, но вроде sqlite там встроен, тогда проблем вообще ноль
flock поддерживается только относительно новыми файловыми системами, в *nix носит рекомендательный характер, а в некоторых системах и вовсе его работа не гарантируется.
flock
Из-за этого и могут быть подобные сбои
Никак не пойму – чем тебя базы не устраивают?
Не проще. Сериализация глючит, если попадутся спецсимволы, например.
Да.
В данном случае нельзя.
Вот блин. Может, тогда перейти на вариант с копированием/удалением файла?
А sqlite разве на любом хостинге есть? Да и если всё равно работу с БД изучать надо, лучше уж на MySQL перейти.
Это усложнение установки для пользователя. Ну и пока у меня просто знаний не хватает, ни разу ничего не делал с базами.
sqlite конечно вариант.
Вообще базы выучить не помешает ;) Язык SQL очень похож на английский, вроде сложного ничего нет. Я лично за пару дней выучил SQL по курсам Oracle (SQL везде фактически один, так что в MySQL прекрасно применяю эти же знания).
Еще неизвестно сколько проблем возникнет при использовании sqlite, хостинги тоже бывают разные, поэтому лучше, наверное, придерживаться первоначальной концепции. А вот проблему с потерей данных можно решить, например, бэкапом основных состояний daos. Вариантов много
Подсмотрел когда то решение. Надо писать через временный файл потом переименование. У кого то cms там работает, если не изменяет склероз, то в Блоголёте вроде.
Вот я тогда изучал варианты как раз, в том числе и с переименованием. Но не помню сейчас, почему выбрал именно решение с flock. Были какие-то доводы против переименований.
Порылся, вроде нашёл похожее www.linkexchanger.su…
Спасибо, хорошая ссылка. Я это обсуждение как раз читал когда проблема впервые дала о себе знать.
я знаю всего один символ, ломающий сериализацию. это \0 (null byte). встречается он при сериализации объектов с private или protected переменными. и при желании легко экранируется. в остальном сериализация работает отлично.
sqlite лучше mysql именно потому что не требует доп. настроек. достаточно лишь прроверить что sqlite доступна в нашей сборке пхп. никаких юзеров/паролей/баз данных создавать не надо.
в чем конкретно состоит необходимость лочить файлы при чтении? я по прежнему уверен что лочить нужно только запись, дабы избежать попытки конкурентной записи в один файл из разных процессов.
где можно посмотреть исходники, раз они открыты?
>Это усложнение установки для пользователя.
Да ладно… Что, у кого-то проблемы с установкой WP или DLE? Едиственное, что надо будет предусмотреть – чтобы названия таблиц не совпали случайно (использовать префиксы, например)…
>Ну и пока у меня просто знаний не хватает, ни разу ничего не делал с базами.
Ну это дело попровимое, когда есть желание ;) Очень советую использовать какой-то враппер для базы, например этот: forum.dklab.ru/viewt…
обе функции меняются на
// запись
file_put_contents($file, serialize($dataArray), LOCK_EX);
// чтение
$dataArray = unserialize(file_get_contents($file));
Не хочу спорить и вспоминать детали, но в своё время намучался я с этой сериализацией (см. комменты), поэтому сознательно выбрал именно такой вариант, как есть сейчас. Да и какие минусы ты видишь? Сериализованный файл невозможно нормально читать и править, а мои можно и без всяких проблем.
Ну а если нет в сборке? Когда делаешь продукт, который должен работать на большинстве хостингов, приходится учитывать.
Если файл не лочить, чтение данных может произойти в момент, когда файл меняется, значит данные будут пустые или порченые. А они ведь могут использоваться перед записью. Я тоже наивно предполагал, что лочить только для записи нужно. Но именно практика показала мне, что я не прав :)
Открыты для покупателей, естественно. Я имел в виду, что никаких обфускаторов не используется, код как есть, с комментариями и простой возможностью изменений.
Да, я про них знаю, спасибо. Выберу что-нибудь. Было бы круто, кстати, чтобы был какой-то класс абстракции, то есть возможность одинаковой работы как с MySQL так и с файлами.
Не меняются. В первых версиях так и было и всё ломалось нахрен. Практика. Не всегда всё работает так, как задумано. Особенно с PHP :)
SQLite только в новой версии стал более менее быстро работать с INSERT‘ами. С SQLite придется использоваться PDO, скорее всего.
И зачем использовать serialize/unserialize? Ведь PHP5.2 уже давно на дворе, да и DAOS, надеюсь, на UTF-8 – вполне можно json_encode/json_decode обойтись.
И анлок файла делать не обязательно – он сам делается при fclose($handle);
Тоже глючит. Обещания красивые, но JSON в PHP не работает нормально (опять же, не вспомню сейчас деталей), при этом далеко не везде установлен.
Уже сколько пользуюсь – проблем ни разу не замечал. Кроме, конечно, использования кривой кодировки. По спеке, json только utf-8 поддерживает.
Да и есть он везде, где php >= 5.2.
Еще предложил бы NoSQL-хранилища, но далеко не все хостинги поддерживают это дело, к сожалению.
И раз уж пошла такая пьянка… В мануале по flock есть такое дело:
«On some operating systems flock() is implemented at the process level. When using a multithreaded server API like ISAPI you may not be able to rely on flock() to protect files against other PHP scripts running in parallel threads of the same server instance!»
А у тебя русские символы после JSON не перекодируются в ужасные нечитаемые последовательности? Это лишь одна из проблем была. Я потом углубился в изучение всяких сериализаций, даже до Google Protocol Buffer дошёл, и в результате принял решение хранить данные в файле через var_export. Я считаю, что это решение красивое и не вижу в нём ни одного недостатка в сравнении с JSON и другими сериализациями.
:) весело у тебя все.
это не работает, тут что-то глючит.
<blockquote>Если файл не лочить, чтение данных может произойти в момент, когда файл меняется, значит данные будут пустые или порченые.</blockquote>
чтение из файла не может произойти когда он меняется именно потому, что он будет залочен на время изменения. лочить файл при чтении НЕ НАДО. сто пудов.
упс. не. я не прав. сори. лочить при чтении все же нужно. :) забыл о том, что запись может начаться в промежутке между началом и концом чтения.
Тормоз, это от посещаловки.. если больше тысячи идет за n-время. У меня такое тоже было. Плюнул и сделал с базой. у кого посещений не много у тех все нормально будет.
Файлы не лучший вариант для хранения информации при нагрузках.
Не факт, просто вероятность инцидента будет значительно ниже. Так что просто закрыть глаза на эту проблему нельзя.
Можно сделать свою блокировку – на время записи создавать файл и удалять его после записи, так же при чтении
не знаю за эти функции, но у меня раньше юзалось блокировка переименованием. че нить типа file.txt в file.lock и куй к нему че обратится по старому имени
эх, давно я не брал в руки шашку.
у тебя race condition между flock($file, LOCK_UN) и fclose($file).
не отпускай локи, close это сделает за тебя.
алсо, стоит проверять код возврата close, что-бы удостовериться в успешности записи.
вдогонку
> flock поддерживается только относительно новыми файловыми системами
fucking nonsense.
flock появился 27 лет назад, а не всегда работает он только для удалённых файловых систем (nfs, etc)
Тоже подумалось — sqlite.
Про «медленно работает с инсертами» — тут они не нужны. Про то, где он стоит —
Не понял, что ты имел в виду.
Можно по-русски? :)
А статистика показов?
У меня уже второй раз так строчки слетают. В прошлый раз ты вроде даже не поверил :D
Вот блин. Постараюсь решить эту проблему в самое ближайшее время. Кстати, у тебя сейчас вообще Daos отключен что ли?
Я считаю что не нужно придумывать велосипед и использовать MySQL. Всё красиво и стабильно. И быстродействие на высоте.
flock действительно иногда тупит от настроек сервака.
извиняюсь за свои 5 копеек а как дела с XML?
А что с XML?
Тормоз, бэкапы то для кого придумали?
rumba.net.ru – говорит на XML – лутше чем на файлах… чесно не знаю просто предположение
$file = fopen($file, ‘a’);
…
fseek($file, 0); ftruncate($file, 0);
не равно $file = fopen($file, ‘w+’); ?
опять же.. в мануале рекомендуют b добавлять…
wb+ и rb+
тормоз, ну не гони на json, не гони))) это обычное экранироение не альфабетикал последовательностей в их ютф яваскрипт коды. если не веришь – почитай что такое json :D
атомарные операции аля – переименование в нужный файл должны помочь 100%.
@Тормоз
en.wikipedia.org/wik…
просто убери flock($file, LOCK_UN) из кода.
дело в том, что отпуская лок до закрытия файла ты допускаешь ситуацию, в которой не все операции записи ещё выполнены, но чтение или новые операция записи уже возможны.
так-же проверяй коды возврата write и close.
более подробно все эти вещи описаны в man 2 flock и man 2 close.
phpdude дело говорит. А временные файлы я бы рандомно именовал, а килял их по времени жизни- было бы откуда, если чего, откатываться
Тормоз, переведи DAOS на sqlite – будет очень удобно
SQL – это легко. А пошаговый (1-2 шага) инсталятор сделает для юзера процесс незаметным
Я против баз так как ето допольнительный геморой при псмене хостинга и бекапах.
Особенно для юзера.
Статистика — сохраняется чем-то другим. От логов до клиент-сервер базы. Для отдачи инфы — SQLite.
Да, отключен.
Старые строчки похерились, новые не покупают. Чего ему висеть…
Тормоз, сделай DAO для бизнес-сущностей и разные драйвера — для баз, для файлов.
Я понимаю, что это такое, но не понимаю зачем коверкать нормальный русский текст, если файл всё равно в UTF-8.
>> но не понимаю зачем коверкать нормальный русский текст, если файл всё равно в UTF-8.
потому что это яваскрипт, а там так – по стандарту, ведь неизвестно в принципе браузерам в какой кодировке файл, поэтому и используется «экранирование»
А серверные заголовки зачем придумали? Всё известно.
а сервер откуда знает? :)
не переспоришь, потому что я прав)
Ты не прав :) Сервер настроить не проблема, да и не всегда от сервера это зависит. Если я JSON вывожу через PHP, например, я могу послать заголовок (и так и делаю для всех файлов). Какие проблемы-то?
проблема в слишком много «если», поэтому и используется «наверняка», а не гадание на манной гуще.
Ну вот поэтому вместо модного JSON я использую обычный родной для PHP формат :) Кстати, меня тут в извращённости обвинили, но никак не аргументировали. Не вижу недостатков у вставки корректного PHP-файла с массивом. Теоретически это может быть менее быстро, чем сериализация и наверняка медленней базы данных, но вряд ли это существенно.
уху, варэекспорт медленнее сериализации, заметно будет на больших массивах.
а сравнивать с базой обе эти вещи))) ну скажу так – соединение с бд порвет по медлительности практически любую сериализацию в мыслимых пределах количества элементов в массиве :)
я сам использую сериализацию.
Хм. То есть именно ты Daos тоже сделал бы на файлах вместо БД?
я бы сделал его на memcachedb чисто ради прикола :D
тормоз, я байки погнал, если чо завтр потрещим, вставать ран, спокойной :)
зы: я последнее время много что на файлах делаю чисто ради прикола, да и вообще последнее время не дрочу на программирование, играюсь больше)
Давай, добрых снов. Чисто приколом мне нельзя руководствоваться, тогда вообще продаж не будет :) А деньги мне нужны.
memcachedb – это как хардкор мод в диабле, советую все проекты хранить так!
А пользователям, которые ничего про это не знают как быть? Вешаться? :)
>ну скажу так – соединение с бд порвет по медлительности практически любую сериализацию
Ребят, вы о чем? Приземлитесь – у вас же не миллионы показов в секунду. Да, соединение с базой медленнее, чем работа с массивом или со строкой, но В ДАННОМ ПРОЕКТЕ это не важно! А какие плюсы дает база: отсутствие такого бага, как в посте, возможность хранить неограниченно историю рекламы на сайте и многое другое. Да хотя бы возможность отслеживания уникальных показов и уникальных кликов! Только за это рекламодатели спасибо скажут! Учитывая данные, которые работают в Daos – прикручивай mysql и не парься.
P.S.: вот только sqlite не надо plz. Да, sqlite меньше, проще и т.д., чем mysql. НО! Не на каждом хостинге есть, медленее, чем mysql. Да и не поддерживает многие вещи.
@Тормоз
моё пояснение было понято или нет?
Это? Нет, не понято :) Можно человеческим языком?
@Тормоз
нет, это другой анонимус. там совсем нерелевантное твоей ситуации предложение.
вот это пояснение
Понял теперь, спасибо. Но остаётся неясным вопрос, почему я так сделал изначально :) Блин, вот когда много времени проходит с момента написания кода, вспомнить уже тяжело. Наверняка не просто так же.
Я кстати тебе давно писал про это
Прикручивать надо memcache, все sql идут в жопу
В жопу идет как раз мемкеш, которого нет на большинстве хостингов =)
Большинство хостингов – говно
Вчера приобрел Daos($66), а только что прочитал этот топ.
Очень важно!!
Тормоз, а на сегодняшний день решена проблема со сбрасыванем рекламных строчек?!! Мы, допустим, не хотим выглядеть обманщиками перед своими пользователями.
6 000 уников, 60 000 просмотров
А я выгляжу обманщиком что ли? Все строчки вернул вручную тогда, ну а сейчас вообще проблема решена. Ещё с 17 октября.
Лично у меня с тех пор были сбросы ещё два или три раза, но это связано с внезапной перезагрузкой сервера. В таких условиях и база могла бы полететь. Каждый раз просто откатывался на прошлый день в резервных копиях, без всяких проблем.
Про случаи сброса у других людей с тех пор ничего не известно. Скорей всего их просто не было.