gpt4 book ai didi

javascript - Node js 中的信号量等效,变量在并发请求中被修改?

转载 作者:搜寻专家 更新时间:2023-10-31 23:34:26 25 4
gpt4 key购买 nike

过去 1 周我一直面临这个问题,我只是对此感到困惑。保持简短,简单地解释问题。

我们有一个内存模型,它存储预算等值。现在,当调用 API 时,它有一个与之关联的花费。

然后我们检查内存模型并将支出添加到现有支出中,然后检查预算,如果超出预算,我们将不再接受该模型的任何点击。对于每次调用,我们还更新了数据库,但这是一个异步操作。

一个简短的例子

api.get('/clk/:spent/:id', function(req, res) {
checkbudget(spent, id);
}

checkbudget(spent, id){
var obj = in memory model[id]
obj.spent+= spent;
obj.spent > obj.budjet // if greater.
obj.status = 11 // 11 is the stopped status
update db and rebuild model.
}

这过去工作正常,但现在对于并发请求,我们得到错误的支出,支出增加超过预算,一段时间后停止。我们用j表模拟调用,发现了这个。

据我们所知, Node 是异步的,因此当状态更新为 11 时,许多线程已经更新了事件的花费。

如何为 Node.js 提供信号量类型的逻辑,以便可变预算与模型同步

更新

 db.addSpend(campaignId, spent, function(err, data) {
campaign.spent += spent;
var totalSpent = (+camp.spent) + (+camp.cpb);
if (totalSpent > camp.budget) {
logger.info('Stopping it..');
camp.status = 11; // in-memory stop
var History = [];
History.push(some data);
db.stopCamp(campId, function(err, data) {
if (err) {
logger.error('Error while stopping );
}
model.campMAP = buildCatMap(model);
model.campKeyMap = buildKeyMap(model);
db.campEventHistory(cpcHistory, false, function(err) {
if (err) {
logger.error(Error);
}
})
});
}
});

代码的 GIST 现在任何人都可以帮忙

最佳答案

问: NodeJs 中是否有semaphore 或等价物?

答: 没有。

问:那么 NodeJs 用户如何处理竞争条件?

答:理论上您不必这样做,因为javascript 中没有thread

在深入研究我提出的解决方案之前,我认为了解 NodeJs 的工作原理对您来说很重要。

对于 NodeJs,它由基于事件的架构驱动。这意味着在 Node 进程中有一个包含所有“待办”事件的事件队列。

当一个事件从队列中得到pop时,node将执行所有所需的代码,直到它完成了。在运行期间进行的任何 async 调用都作为其他 events 产生,并且它们在 event queue 中排队,直到听到响应是时候再次运行它们了。

问:那么我该怎么做才能确保一次只有 1 个请求可以对数据库执行更新

答:我相信有很多方法可以实现这一点,但其中一种更简单的方法是使用 set_timeout API。

示例:

api.get('/clk/:spent/:id', function(req, res) {
var data = {
id: id
spending: spent
}
canProceed(data, /*functions to exec after canProceed=*/ checkbudget);
}

var canProceed = function(data, next) {
var model = in memory model[id];

if (model.is_updating) {
set_timeout(isUpdating(data, next), /*try again in=*/1000/*milliseconds*/);
}
else {
// lock is released. Proceed.
next(data.spending, data.id)
}
}


checkbudget(spent, id){
var obj = in memory model[id]

obj.is_updating = true; // Lock this model

obj.spent+= spent;
obj.spent > obj.budjet // if greater.
obj.status = 11 // 11 is the stopped status
update db and rebuild model.
obj.is_updating = false; // Unlock the model
}

注意:我在这里得到的也是伪代码,因此您可能需要稍微调整一下。

这里的想法是在您的模型中有一个标志来指示 HTTP 请求 是否可以继续执行关键代码路径。在这种情况下,您的 checkbudget 功能及其他功能。

当收到请求时,它会检查 is_updating 标志以查看它是否可以继续。如果它是 true 然后它安排一个事件,在一秒钟后被触发,这个“setTimeout”基本上变成一个事件并被放入 node 的事件队列中后期处理

当此事件稍后被触发时,再次检查。这种情况会发生,直到 is_update 标志变为 false 然后请求继续执行它的操作并且 is_update 在所有关键代码时再次设置为 false完成了。

这不是最有效的方法,但它可以完成工作,当性能出现问题时,您可以随时重新访问解决方案。

关于javascript - Node js 中的信号量等效,变量在并发请求中被修改?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45755484/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com