Я запускаю графический файловый менеджер, похожий на OneDrive, OpenCloud или что-то в этом роде. Файлы, папки, учетные записи и основные настройки сервера хранятся в базе данных как объекты в кодировке JSON (да, я избавился от столбцов в пользу json). Проблема заключается в том, что несколько запросов используют один и тот же объект одновременно, поэтому часто сохраняются неверные данные, поскольку запросы, очевидно, не могут передавать изменения друг другу.
Например, когда кто-то начинает загрузку, он загружает объект учетной записи владельца этого файла, увеличивает его счетчик пропускной способности, а затем кодирует / сохраняет его обратно в БД в конце загрузки. Но, скажем, если у меня будет 3 загрузки одного и того же файла одновременно, они все загрузят один и тот же объект учетной записи, изменят данные по своему усмотрению и сохранят свои данные без учета других, которые перекрываются. В этом случае 3 загрузки будут показаны как 1.
Помимо того, что загрузка и пропускная способность не учитываются, у меня также есть проблема, когда я пытаюсь создать функцию обслуживания, которая загружает объект сервера и не сохраняет его в течение потенциально нескольких минут — это, очевидно, не будет работать, пока Тем временем происходит загрузка и манипулирование объектом сервера, потому что все это будет просто перезаписано старыми данными после завершения функции обслуживания.
По сути, это проблема с многопоточностью. Я изучил PHP APC в надежде, что смогу сохранить объекты глобально между потоками, но это не работает, поскольку он просто сериализует / десериализует данные для каждого запроса, а не фактически указывает на то, что каждый запрос указывает на объект в памяти.
Я абсолютно не представляю, как это исправить, не спроектировав совершенно новую систему, которая будет совершенно другой … это отстой.
Любые идеи о том, как я должен поступить об этом, были бы великолепны.
Спасибо!
Это не проблема потоков. Ваша база данных не соответствует ни одному из стандартов построения баз данных, включая даже первую нормальную форму: каждая ячейка должна содержать только одно значение. Когда вы храните данные JSON в БД, вы не можете написать запрос SQL, чтобы сделать эту транзакцию атомарной. Так что да, ты необходимость положить этот код в мусорное ведро.
Если вам действительно нужно, чтобы этот код работал, вы можете использовать некоторые мьютексы для синхронизации запуска PHP-скриптов. Наиболее распространенная реализация в PHP файловый мьютекс.
Вы можете попробовать использовать flock, я думаю, у вас уже есть идентификатор пользователя до получения JSON из БД.
$lockfile = "/tmp/userlocks/$userid.txt";
$fp = fopen($lockfile, "w+");
if (flock($fp, LOCK_EX)) {
//Do your JSON update
flock($fp, LOCK_UN); //unlock
}else{
// lock exist
}
Вам нужно выяснить, что делать при блокировке, возможно, подождите 0,5 секунды и попытаться снова получить блокировку, или отправьте сообщение «Одновременно разрешена только одна загрузка» или …