2012-06-15 1 views
0

Я пытаюсь найти решение для предотвращения условий гонки в моей логике приложений (особенно при обновлении токена доступа OAuth), а моя база данных - это mongodb.Решение MongoDB `GET_LOCK` в PHP

Исходя из фона MySQL, я привык использовать GET_LOCK и связанные с ним функции для обработки блокировки в PHP. Есть ли у Монго какой-либо аналог функции MySQL GET_LOCK, или мне придется использовать блокировку файлов PHP или что-то подобное?

Действительно ли flock() является хорошим (или надлежащим образом) альтернативой для этой ситуации или предназначен для использования только при чтении и записи в файлы?

Edit:

Расы состояние Я пытаюсь предотвратить следующий:

  1. Экземпляр замечает OAuth маркеров доступа истечения приближающейся

  2. Instance B замечает доступа OAuth маркер истечения срока действия приближается

  3. Экземпляр A запрашивает обновленный токен доступа OAuth с удаленного сервера и получает o пе

  4. Instance B запрашивает маркер обновилась доступа OAuth с того же сервера и отвергается (сервер потенциально аннулирует маркер доступа с шага 3 в качестве меры предосторожности)

  5. Экземпляр сохраняет результат обратно в базу данных

  6. Instance B сохраняет результат обратно в базу данных

+0

Состояние гонки на PHP? О чем ты говоришь? – Shoe

+0

Зачем что-то блокировать?Блокирование базы данных плохо, транзакции хорошие. MongoDB поддерживает атомарные действия: http://www.mongodb.org/display/DOCS/Atomic+Operations#AtomicOperations-ApplyingtoMultipleObjectsAtOnce – sinni800

+0

Извините, я должен уточнить ... Я хочу заблокировать доступ к документу, содержащему токен доступа OAuth, в то время как токен обновляется, а затем разрешает доступ к нему после ввода нового токена доступа. Состояние гонки, на которое я пытаюсь исправить, включается, когда два процесса отмечают токен с истекшим или почти истекшим доступом и пытаются обновить токен с помощью нового ... один из токенов будет действителен и один будет недействительным. Кроме того, сервер oauth может сделать недействительным и думать, что происходит атака (незаконный пользователь oauth, пытающийся использовать уже использованный токен обновления) – mikegreiling

ответ

3

Если вы хотите, чтобы имитировать именованный мьютекс или блокировку с помощью MongoDB, я предложил бы использовать findAndModify по CREA Для этого вам понадобится специальная коллекция и документ, вы даже можете назвать его db.my_lock.

db.my_lock.save({"IMREFRESHINGAUTHTOKEN":false}); 

Теперь между шагами 2 и 3 добавить findAndModify, чтобы захватить «замок»:

db.my_lock.findAndModify(
     query: {"IMREFRESHINGAUTHTOKEN":false}, 
     update: {$set: {"IMREFRESHINGAUTHTOKEN": true}, ...} 
); 

Если вы получите «замок» во-первых, вы получите обратно этот объект (и вы будет установлено, что первое поле имеет значение true - я рекомендую установить второе поле с отметкой времени или номером соединения или идентификатором процесса или другим идентификатором, который позволит очистить после аварийного процесса, чтобы он не удерживал блокировку навсегда).

Если вы «проиграете» гонку, вы не получите ничего, что соответствует «IMREFRESHINGAUTHTOKEN»: ложно, и вы узнаете, что потеряли гонку и сдались (или отметьте отметку времени замка и, возможно, попытаетесь выяснить, старый и устаревший).

Это описание отдельной отдельной блокировки для всей «коллекции» - вы можете реализовать это как дополнительное поле на хранящемся маркете OAuth и иметь как можно больше обновлений, поскольку есть заметки о потоках они истекают.

Надеюсь, это поможет.

+0

Спасибо, это именно то, что я искал. – mikegreiling

+0

Что делать, если клиент сработает и удерживает блокировку навсегда? – aitchnyu

+0

- это причина установки временной метки при «взятии» блокировки и периодической проверки того, что блокировка не удерживается дольше, чем ожидаемый период, или установить время и pid того, кто у вас есть, чтобы можно было проверить, сохраняется ли процесс. –