Люблю то, что делаю!
С нами с 22.10.06
Сообщения: 5053
Рейтинг: 4418
|
Добавлено: 15/12/16 в 22:18 |
Нужно реализовать генерацию с определенным повторением имен, без БД, только файлы.
Нюанс в том, что генерация не разовая, а дергается по крону и затем имя пишется в файл, при всем при этом имена должны генерироваться рандомно, но учитывая % повторяемости
К примеру:
имя|% повторяемости
A|40
B|20
C|15
D|10
E|5
F|5
G|3
H|2
J|1
На основе подобного дампа всё и должно генерироваться, в данном примере только 9 имен, по факту их может быть до нескольких тысяч.
Как вариант, добавить еще один параметр в дамп (относительный %):
На начальной стадии относительный % = 0, у всех
имя|% повторяемости|относительный %
A|40|0
B|20|0
C|15|0
D|10|0
E|5|0
F|5|0
G|3|0
H|2|0
J|1|0
Затем после первой генерации, относительный процент у одного из имен (кторое сгенерировано первым) будет равен 100%, затем второй раз рандомно берем из дампа строку и сравниваем, если относительный процент меньше должного %-повторяемости, то генерим это имя, если больше, то берем другую строку дампа и также сравниваем, при этом вероятнее всего, нужно будет добавить еще один параметр, это число сгенерированных имен, чтоб можно было высчитывать относительны процент.
Надеюсь поймете мысль
Спасибо!
PS: возможно это было бы проще реализовать с использованием БД, но в них я ноль, хотя вещь полезная. Но меня у меня фобия того, что из-за незнания БД могут ломануть SQL инъекцией или чем-то подобным.
|
|
|
|
С нами с 22.05.04
Сообщения: 268
Рейтинг: 251
|
Добавлено: 16/12/16 в 01:50 |
1. определись как с конечным результатом, так и с оптимальным алгоритмом того что ты хочешь реализовать. пока что тут слегка каша
2. если нужно много и часто и с хранением результатов - заранее посмотри в сторону redis/memcached
ну и про цепи маркова почитай, по ним уже много много лет существуют готовые алгоритмы - например для генерации текста древних дорвеев
|
|
Нестандартные задачи. Кастом программинг на ПХП. Оптимизация стороннего кода. Недорого, недешево.
|
7
|
|
|
Люблю то, что делаю!
С нами с 22.10.06
Сообщения: 5053
Рейтинг: 4418
|
Добавлено: 16/12/16 в 19:36 |
Вот по сути рабочий вариант, написан на основе имеющихся знаний, я не волшебник, я только учусь .
Код: [развернуть] |
<?php
function frequencyOfUse($pathToFileDump){
if (!is_writable($pathToFileDump)) {
exit();
}
$pathToTmpFileDump = $pathToFileDump.".tmp";
file_put_contents($pathToTmpFileDump, "");
if (!is_writable($pathToTmpFileDump)) {
exit();
}
$db = file($pathToFileDump, FILE_IGNORE_NEW_LINES);
shuffle($db);
foreach ($db as $keyStr => $strDb) {
$strDb = trim($strDb);
list($name, $pctFreqConst, $pctFreqRelat, $numbOfUses, $sumOfAllUses) = explode("|", $strDb);
if (empty($pctFreqRelat)) {
$pctFreqRelat = 0;
}
if ($pctFreqConst >= $pctFreqRelat) {
if (empty($numbOfUses)) {
$numbOfUses = 1;
}else{
$numbOfUses = $numbOfUses + 1;
}
if (empty($sumOfAllUses)) {
$sumOfAllUses = 1;
}else{
$sumOfAllUses = $sumOfAllUses + 1;
}
$pctFreqRelat = $numbOfUses * 100 / $sumOfAllUses;
$pctFreqRelat = floor($pctFreqRelat);
$result = $name;
break;
}else{
continue;
}
}
// Корректировка данных
foreach ($db as $keyStrCorr => $strDbCorr) {
list($nameCorr, $pctFreqConstCorr, $pctFreqRelatCorr, $numbOfUsesCorr, $sumOfAllUsesCorr) = explode("|", $strDbCorr);
$sumOfAllUsesCorr = $sumOfAllUses;
if ($keyStrCorr == $keyStr) {
$pctFreqRelatCorr = $pctFreqRelat;
$numbOfUsesCorr = $numbOfUses;
}else{
$pctFreqRelatCorr = $numbOfUsesCorr * 100 / $sumOfAllUses;
$pctFreqRelatCorr = floor($pctFreqRelatCorr);
}
$strDump = $nameCorr."|".$pctFreqConstCorr."|".$pctFreqRelatCorr."|".$numbOfUsesCorr."|".$sumOfAllUsesCorr;
file_put_contents($pathToTmpFileDump, $strDump."\n", FILE_APPEND);
}
if (copy($pathToTmpFileDump, $pathToFileDump)){
unlink($pathToTmpFileDump);
}
// Проверка результата
if (!isset($result) AND empty($result)) {
$result = NULL;
}
return $result;
}
echo frequencyOfUse("dbFrequencyOfUse.dat");
?>
|
dbFrequencyOfUse.dat
Код: [развернуть] | X|1|1|3|220
J|4|3|7|220
P|2|1|4|220
T|1|1|4|220
C|9|7|17|220
A|10|10|22|220
Q|2|1|4|220
O|2|2|5|220
E|8|7|16|220
F|7|5|13|220
D|9|7|17|220
Z|1|0|2|220
G|6|6|14|220
N|2|2|5|220
L|3|2|6|220
V|1|1|3|220
U|1|1|4|220
I|4|5|11|220
M|3|3|8|220
K|3|3|8|220
B|10|9|21|220
S|2|1|4|220
Y|1|0|2|220
H|5|5|11|220
R|2|2|5|220
W|1|1|4|220
|
Всё работает. Но есть один момент. Если тупо зажать F5, т.е. исполняться код будет очень быстро, в конечном итоге данные в dbFrequencyOfUse.dat херятся и получается пустой файл.
В чем может быть причина?
|
|
|
|
📈sflash.biz
С нами с 03.11.12
Сообщения: 3913
Рейтинг: 4447
|
Добавлено: 16/12/16 в 19:57 |
Lexikon писал: | В чем может быть причина? |
Не в даваясь в подробности, скорее всего в парадигме. Что у тебя к файлу, который на какой-то момент производится запись появляется необходимость чтения или ещё одна запись в тот же файл. Если я попробую угадать, то в тестах у тебя всё хорошо, а в продакшене на сервере, в момент нагрузки - плохо, верно?
|
|
|
|
Люблю то, что делаю!
С нами с 22.10.06
Сообщения: 5053
Рейтинг: 4418
|
Добавлено: 16/12/16 в 20:22 |
S_Flash писал: | Если я попробую угадать, то в тестах у тебя всё хорошо, а в продакшене на сервере, в момент нагрузки - плохо, верно? |
Нагрузку я создавал искусственно, без нагрузки, да, всё нормально. У меня тоже было такое предположение, что из за чтения и записи вот такая ня получается, ты как раз подтвердил мое предположение. Конечно если учесть, что данный скрипт будет дергаться по крону и не чаще чем 1 раз в минуту, всё это должно работать нормально. Но всё же, стало интересно, как то можно организовать это так, чтоб оно работало и на нагрузке?
|
|
|
|
📈sflash.biz
С нами с 03.11.12
Сообщения: 3913
Рейтинг: 4447
|
Добавлено: 16/12/16 в 22:25 |
Lexikon писал: | Но всё же, стало интересно, как то можно организовать это так, чтоб оно работало и на нагрузке? |
- Ну либо юзать вместо file_xxx_contents - fopen() в сочетании с flock() по старинке,
- либо посмотреть внимательнее мануал по file_put_contents, там вроде есть имитация лока в виде LOCK_EX.
Но это скорее спасёт от одновременной записи в один файл. Попробуй ещё опискать, нет ли в твоём коде такого сотояния, когда файл просто обнуляется хотябы на долисекунды для перезаписи и пофикси это. Короче, если у тебя чтение и запись с одного файла, то лучше раздели на 2 отдельных и копируй обновлённый, только когда тот готов и читай уже с него.
|
|
|
|
www.phpdevs.com
С нами с 24.10.02
Сообщения: 16633
Рейтинг: 16105
|
Добавлено: 17/12/16 в 01:08 |
Дались вам эти файлы. PDO->sqlite и куча проблем будет решена. Вон что хром, что фаерфокс - все куки, сессии, логины и т.п. пишут именно в sqlite.
|
|
Пишу на php/mysql/django за вменяемые деньги.
Обращаться в личку.
|
10
|
|
|
С нами с 18.10.02
Сообщения: 4165
Рейтинг: 3365
|
Добавлено: 17/12/16 в 01:17 |
Lexikon:
Что по-твоему делает вот эта строчка?
Код: [развернуть] | if (copy($pathToTmpFileDump, $pathToFileDump)){ |
Stek писал: | PDO->sqlite и куча проблем будет решена. |
И появится куча других, если основ не понимать.
|
|
|
|
www.phpdevs.com
С нами с 24.10.02
Сообщения: 16633
Рейтинг: 16105
|
Добавлено: 17/12/16 в 03:03 |
Mika писал: | И появится куча других |
Каких именно ?
|
|
Пишу на php/mysql/django за вменяемые деньги.
Обращаться в личку.
|
2
|
|
|
Люблю то, что делаю!
С нами с 22.10.06
Сообщения: 5053
Рейтинг: 4418
|
Добавлено: 17/12/16 в 06:55 |
Вот этот вопрос мне адресован?
Mika писал: | Lexikon:
Что по-твоему делает вот эта строчка?
Код: [свернуть]
if (copy($pathToTmpFileDump, $pathToFileDump)){
|
Или это к:
S_Flash писал: | то лучше раздели на 2 отдельных и копируй обновлённый, только когда тот готов и читай уже с него. |
Stek писал: | Дались вам эти файлы. PDO->sqlite и куча проблем будет решена. Вон что хром, что фаерфокс - все куки, сессии, логины и т.п. пишут именно в sqlite.
|
Изучу, что это такое. Спасибо.
|
|
|
|
📈sflash.biz
С нами с 03.11.12
Сообщения: 3913
Рейтинг: 4447
|
Добавлено: 17/12/16 в 10:19 |
Кстати, кто-то знает file_put_contents - атомарна по отношению к чтению из этого же файла или можно поймать запись на середине заполнения файла и прочитать только тот кусок, что учпел записаться на данный момент?
|
|
|
|
💀💀💀
С нами с 31.05.10
Сообщения: 4689
Рейтинг: 728
|
Добавлено: 17/12/16 в 10:50 |
|
|
|
|
📈sflash.biz
С нами с 03.11.12
Сообщения: 3913
Рейтинг: 4447
|
Добавлено: 17/12/16 в 11:02 |
тогда хуййознает, как читатать только "готовый файл" в многозадачных системах и стоит ли юзать тут именно файловую систему.
|
|
|
|
💀💀💀
С нами с 31.05.10
Сообщения: 4689
Рейтинг: 728
|
Добавлено: 17/12/16 в 11:20 |
Для таких целей обычно семафоры используют. (сам не юзал, тока теорию читал =))
|
|
|
|
💀💀💀
С нами с 31.05.10
Сообщения: 4689
Рейтинг: 728
|
Добавлено: 17/12/16 в 11:27 |
или как вариант юзать бдшные транзации и всякие лок тейблы для хранения.
У редиса также все операции атомарны, т.к. работают в 1 потоке + есть транзакции. Тож можно юзать.
|
|
|
|
С нами с 13.01.03
Сообщения: 1032
Рейтинг: 1146
|
Добавлено: 18/12/16 в 19:19 |
помимо всего вышесказанного, такие обнуления могут быть (по крайней мере было у меня) из-за постоянной высокой нагрузки на серверный диск... посмотри, нет ли перманентно забитой очереди на запись... ну и процент использования диска тож глянь...
|
|
|
|
Люблю то, что делаю!
С нами с 22.10.06
Сообщения: 5053
Рейтинг: 4418
|
Добавлено: 19/12/16 в 19:35 |
Скрипт который обращается к файлу запускается по крону и во время работы скрипта его больше ни кто не беспокоит.
Проблема в принципе раскрыта в этом топике, множественные обращение, которые так же происходят во время записи и перезаписи файла, соответственно в какой то момент получается, что одно перекрывается другим, и в конечном итоге всё херится.
Проблему решил достаточно просто:
Код: |
$pathToStatusFile = "status.dat";
if (!is_writable($pathToFileDump)) {
exit();
}
if (!is_writable($pathToStatusFile) OR file_get_contents($pathToStatusFile) == 1) {
exit();
}else{
file_put_contents($pathToStatusFile, 1);
# тут основной код
file_put_contents($pathToStatusFile, 0);
}
return $result;
|
Смысл в том, что пока выполняется скрипт, в дополнительном файле status.dat ставим метку, в данном случае это 0, типа ЗАНЯТО! и при попытке обратиться во время исполнения скрипта вторым запросом, получаем выход из скрипта exit() и всё. Статус же меняется по окончанию выполнения и после этого уже можно обращаться. Пока писал этот пост, подумал, что примерно так же можно вместо exit() запускать цикл, но он скорее всего будет полезен только том случае, если не нужно выходить из скрипта.
|
|
|
|
💀💀💀
С нами с 31.05.10
Сообщения: 4689
Рейтинг: 728
|
Добавлено: 19/12/16 в 20:10 |
вместо метки можно работать с файлом в режиме лока на запись.
Т.е. пока какой-то скрипт работает на запись, никто другой к нему не лезет.
http://php.net/manual/ru/function.flock.php
Код: |
if (is_file($pathToFileDump) && !is_writable($pathToFileDump)) {
exit();
}
|
Этого должно быть достаточно, и убрать файловый семафор ;D
П.С.
Хотя там в примерах есть годные функции по работе с залоченым файлом без искусственных проверок на запись.
|
|
|
|
С нами с 09.08.12
Сообщения: 185
Рейтинг: 378
|
Добавлено: 20/12/16 в 16:15 |
Stek писал: | PDO->sqlite и куча проблем будет решена |
лучше mysql - он есть на всех хостингах. а sqlite - не всегда доступен.
|
|
|
|
С нами с 09.08.12
Сообщения: 185
Рейтинг: 378
|
Добавлено: 20/12/16 в 16:17 |
|
|
|
|
Люблю то, что делаю!
С нами с 22.10.06
Сообщения: 5053
Рейтинг: 4418
|
Добавлено: 20/12/16 в 18:37 |
rickdeckard писал: | лучше mysql - он есть на всех хостингах. а sqlite - не всегда доступен. |
Вчера в качестве вечернего просмотра организовал себе просмотр видоса по sqlite, как я понял sqlite идет в PHP 5. У меня WAMP установлен, там тоже есть
|
|
|
|
Люблю то, что делаю!
С нами с 22.10.06
Сообщения: 5053
Рейтинг: 4418
|
Добавлено: 20/12/16 в 18:44 |
Благодарю!
Это да, но вот всё же, меня не покидает мысль, что как-то относительно просто ломают базы, х.з. может всё так изначально криво пишут, чтоб специально ломать. Знаю существуют большие базы с SQL запросами инъекций и ими хуярят различные форумы и сайты. Разве те, кто писал код сайта, не в курсе что да как? Может я что-то не понимаю, касаемо этого.
Вот уже наверное года 3-4 использую ПХП, но всё организовывал на файлах, наверное всё таки фобия
|
|
|
|
💀💀💀
С нами с 31.05.10
Сообщения: 4689
Рейтинг: 728
|
Добавлено: 20/12/16 в 19:27 |
Движки форумов и сайтов ооочень древние, никто не апгрейдит их и не переписывает. Ибо нахуя? Работает - не трожь. =)
Вот. А еще в сети мегатонны старых манов, где все примерны на старых мускульных функциях, и всякие новички пишут по ним свои велосипеды. А потом удивляются как это все ломается весело и задорно.
Вот к примеру яркий пример: https://toster.ru/q/381480
Просто первый попавшийся кликнул на тематику пхп+мускул =)
Может и не сильно будет понятно с первого раза, но когда въедешь во всю эту кухню, поймешь какой это пездец. Если в краце, то у чувака вообще никаких проверок и экранирования, уже молчу про использование prepareStatement.
|
|
|
|
Люблю то, что делаю!
С нами с 22.10.06
Сообщения: 5053
Рейтинг: 4418
|
Добавлено: 20/12/16 в 19:56 |
Ailk писал: | Движки форумов и сайтов ооочень древние, никто не апгрейдит их и не переписывает. Ибо нахуя? Работает - не трожь. =)
Вот. А еще в сети мегатонны старых манов, где все примерны на старых мускульных функциях, и всякие новички пишут по ним свои велосипеды. А потом удивляются как это все ломается весело и задорно.
Вот к примеру яркий пример: https://toster.ru/q/381480
Просто первый попавшийся кликнул на тематику пхп+мускул =)
Может и не сильно будет понятно с первого раза, но когда въедешь во всю эту кухню, поймешь какой это пездец. Если в краце, то у чувака вообще никаких проверок и экранирования, уже молчу про использование prepareStatement. |
Ясно. Благодарю!
|
|
|
|
Люблю то, что делаю!
С нами с 22.10.06
Сообщения: 5053
Рейтинг: 4418
|
Добавлено: 20/12/16 в 20:05 |
Кстати, тут задался таким вопросом, а как правильно проверить существование файла, встречал варианты проверок: is_file() и file_exists(), но и опять же, бывает такой вариант, что файл то существует, но вот для чтения и записи не доступен, т.е. тут нужны функции is_readable(), is_writable().
Как правило для создания и чтения файлов использую file_put_contents() и file_get_contents().
|
|
|
|