0

我正在尝试找到一种解决方案来防止我的应用程序逻辑中出现竞争条件(特别是在更新 OAuth 访问令牌时),而我的后端数据库恰好是 mongodb。

来自 MySQL 背景,我习惯使用GET_LOCK它的相关函数来处理 PHP 中的阻塞。Mongo 是否有任何类似于 MySQL 的GET_LOCK功能,或者我是否必须使用 PHP 的文件锁定或类似的东西?

对于这种情况是flock()一个好的(或适当的)替代方案,还是仅在读取和写入文件时使用?

编辑:

我试图防止的竞争条件如下:

  1. 实例 A 通知 OAuth 访问令牌即将到期

  2. 实例 B 注意到 OAuth 访问令牌即将到期

  3. 实例 A 从远程服务器请求刷新的 OAuth 访问令牌并获得一个

  4. 实例 B 从同一服务器请求刷新的 OAuth 访问令牌并被拒绝(作为安全预防措施,服务器可能会使步骤 3 中的访问令牌无效)

  5. 实例 A 将结果保存回数据库

  6. 实例 B 将结果保存回数据库

4

1 回答 1

3

如果您想使用 MongoDB 模拟命名互斥锁或锁,我建议通过为其创建一个特殊集合并拥有一个文档来使用findAndModify,您甚至可以将其命名为 db.my_lock。

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

现在,在第 2 步和第 3 步之间添加一个 findAndModify 来获取“锁”:

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

如果您首先获得“锁定”,您将取回该对象(并且您可以将第一个字段设置为 true - 我建议使用时间戳或连接号或进程 ID 或其他允许的标识符设置第二个字段在进程崩溃后进行清理,这样它就不会永远持有锁)。

如果你“输掉”比赛,你将不会得到任何匹配 "IMREFRESHINGAUTHTOKEN":false 的东西,你会知道你输掉比赛并放弃(或检查锁的时间戳,也许尝试看看它是否过时) .

这描述了对整个“集合”的独立单一锁定 - 当然,您可以将其作为存储的 OAuth 令牌上的一个额外字段来实现,并且一次刷新它们中的多个,因为有线程注意到它们即将到期。

希望这可以帮助。

于 2012-06-17T07:18:44.230 回答