Буду писать завуалированно. Есть список строк. Список большой - 500 000 и более. Есть "задания". В каждом задании участвует определенное количество строк. Задание для увеличения скорости выполняется в несколько потоков через AJAX (штук 100 потоков). Нужно, чтобы скрипт чётко знал, участвовала ли уже строка в задании, или нет. Сначала думал сделать так: сохраняем исходные строки в файл1, а отработанные в задании строки - в файл2. Затем через array_diff палим, какие ещё не отработали. Но при 500 000 строках скрипт завалился на бок. Не подскажите, как лучше сделать?
лучше через БД - не будет блокировок и лишней загруженности файла хранить в отдельной таблице номер использованой строки (или саму строку - зависит от ситуации). при обращении проверять по номеру/строке была ли строка уже использована.
а ассоциативный массив не катит? "string" => 0 отработала, берем несколько строк на задание, и ставим им "string" => 1
есть список ключей. их много. Они уникальные. строки в md5 Создаётся задание: эти ключи нужно курлом отправить по одному на специально сформированный адрес. Мультикурлом не получится, так как там ещё систему авторизации проходить, потому делал так: на JS создавал огромный массив ключей, через AJAX создаю 100 запросов на обработчик, в переменных запроса указывал ID потока и часть массива (в масиве ключи помечал как "отправленные".) Как поток возвращает результат - заряжал его снова с новыми данными. Но сейчас нельзя, чтобы ключи были видны пользователю, потому надо на PHP реализовать. Представим, что ключи хранятся в таблице. Тогда обработчик может посылать одни и те же ключи. В этом и состоит проблема. Как именно указать обрботчику, что какие-то ключи уже посылались, а какие-то нет.
PHP: <?php $arrKeys=array(); $errKeys=array(); $db->select("select key from keys where send is null limit 100"); while ($row=$db->fetchAssoc()){ try{ $curlSender->send($row); $arrKeys[]=$row['key']; }catch(Exception $e){ $loger->logException($e); $errKeys[]=$row['key']; } } $keys="(".implode(',', $arrKeys).")"; $errKeys="(".implode(',', $errKeys).")"; $db->update("update keys set send=1 where key in $keys"); $db->update("update keys set send=2 where key in $errKeys"); Это если обработчик один.
PHP: <?php $arrKeys=array(); $errKeys=array(); //Этот блок может генерировать исключение, которое скорее всего надо ловить вызывающим блоком. $db->lockTable("keys"); //Блокировку таблицы можно заменить соответствующим уровенем изолированности транзакций $arrSelect=$db->getColumn("select key from keys where send='N' is null limit 100"); //N - Not send $keys="(".implode(',', $arrSelect).")"; $db->update("update keys set send='W' where key in $keys"); //W - Work $db->unLockTable("keys"); foreach($arrSelect as $key){ try{ $curlSender->send($key); $arrKeys[]=$key; }catch(Exception $e){ $loger->logException($e); $errKeys[]=$key; } } $keys="(".implode(',', $arrKeys).")"; $errKeys="(".implode(',', $errKeys).")"; $db->update("update keys set send='O' where key in $keys"); // O - OK $db->update("update keys set send='E' where key in $errKeys"); // E - Error Теоретически это должно сработать при множестве обработчиков.
И что это меняет? Кстати, еще идея: PHP: <?php $db->update("update keys set send='W' idSender='".$curlSender->getId()."' where send='N' limit 100"); $arrKeys=$db->getColumn("select key from keys where send='W' and idSender='".$curlSender->getId()."'");
Ensiferum Только что выдуманные. =)) $db - класс работы с базой данных. $curlSender - собственно тот объект который выполняет основную работу. Что он делает - тебе виднее. $loger - логирует сообщения. Вызовы методов вполне можно заменить процедурами.