Вы сейчас здесь
«Облако» тэгов
link, small, tagless, tiny, 2003, big, 2008, 2010, январь, декабрь, сентябрь, 2001, 2004, 2002, август, март, апрель, июль, 2009, игры, октябрь, май, июнь, февраль, 2007, ноябрь, img, 2011, quote, wow, huge, блоги, кино, игровой дизайн, ребенок, половой вопрос, технологии, lytdybr, вебдев, фразы, живой журнал, жизнь, яндекс, язык, php, людишки, 2006, 2005, software, поисковики, video, inglish, 2000, смишно, диалоги, музыка, книги, культ личности, политика, дейтинг, интернет, 1999, rss, контент, flash, реклама, я, авторские проекты, next-gen mmo, прон, ореховые скорлупки, сми, 2012, js, программирование, fight club, register, социгры, спам, english reviews, iphone, потребление, американас, идеи, беллетристика, мое величие, usability, пидорасты, battle.net, lifestyle, starcraft 2, Тёма, соционика, spectator.ru, британские ученые, развитие, Масква, фото, бабло, литература, mobile, work, болкман, титаны, hard, hobius, mysql, интеллектуальный юмор, хостинг, blogowar.ru, графика, SEO, blogowar, magic, журналистика, злоба дня, религия, стартапы, social, tf2, браузеры, цитаты, gzip, warhammer, велосипед, киви, медикаментоз, общество, оговорки, html, воспитание, мифы, паранойа, письма в редакцию, учеба, 1998, mongodb, soft, soviet, twdnkumus, глянцевые журналы, монетизация, норкотики, сайты, сиськи, типографика, тьюринг, дизайн, железо, живут же люди, лолвут, плагиат, твиттер, еда, тренд, about, бабушки, вещи, видео, зомбоящик, игрушки, социопатия,
Персональное
об авторе и сайте
мойкруг (резюме)
на G+
порнотумблер (rss)
инстаграм (хипстерские фото)

facebook
twitter

skype: acerbial
gtalk: dmitry.smirnov


C любовью к людишкам™,
♥ 1998 - 2013.

powered by mongodb.



Как мы побороли flock

Дано: файл, в который часто пишется информация и часто из него считывается. Например, простой текстовый счетчик на страницу.

Проблема: рано или поздно, но обязательно случится ситуация, когда одновременно к файлу будет несколько обращений — и на запись и на чтение. И вся информация, натурально, потеряется.

Чтобы этого не случилось, существует специальный оператор в PHP — flock. Который, по идее, должен с этим бороться — сначала мы получаем эксклюзивные права доступа к файлу, пишем туда, что хотим, а потом эти права теряем.

В идеале это работает. Но — цитирую документацию по PHP — «flock() will not work on NFS and many other networked file systems. Check your operating system documentation for more details». Если почитать все ту же документацию, то в комментариях пользователей приводится множество способов побороть flock, вплоть до самых экзотичных.

Стоит ли говорить, что у меня ни сам flock, ни другие способы просто не работали?

В конце концов, я набрел в одном англоязычном блоге на интересную фразу как раз по этому поводу: «A file rename operation is guaranteed to be atomic by the operating system, and is very efficient as file functions are always highly optimized».

То есть, rename — это атомарная, сиречь неделимая функция операционной системы. К тому же она очень эффективная, потому что файловые функции всегда хорошо оптимизированы.

Так что я попробовал побороть flock следующим образом: сначала пишем все, что нам нужно, в временный файл (не забудьте выставить правильный chmod на директорию, в которую он будет писаться), а потом просто переименовываем этот файл в тот файл, который нужно. Причем в unix-овых системах старый файл удалять нет необходимости — все будет перезаписано сверху.

Я написал две функции. Первая функция — это функция записи в файл, вторая — чтения из файла. Эти две функции интенсивно работают у меня вот уже больше месяца, и пока не было ни одного сбоя.

Запись в файл:

function S_fw ($COUNT_FILE, $text)
{
$z=rand (0,100000);
$fp = @fopen($COUNT_FILE.".".$z, "wb+");
@fwrite($fp,$text);
@fclose($fp);
if (@rename ($COUNT_FILE.".".$z, $COUNT_FILE)==false)
{
@unlink ($COUNT_FILE);
@rename ($COUNT_FILE.".".$z, $COUNT_FILE);
}
}

Чтение из файла (flock здесь стоит «на всякий случай»):

function S_fr ($COUNT_FILE)
{
clearstatcache();
$fp = @fopen($COUNT_FILE, "rb");
@flock ($fp,LOCK_SH);
$conts=@fread ($fp, filesize ($COUNT_FILE));
@fclose ($fp);
@flock($fp, LOCK_UN);
return $conts;
}

Пользуйтесь на здоровье.

PS. Мне тут подсказывают про функцию tempnam. Использовать ее будет более правильно, чем rand.

PSS. Прислали ссылку на еще один способ, как это можно сделать. Я не проверял.

8 лет назад
0
Привет, Anonymous! Чтобы оставлять комментарии, надо авторизоваться.