等待无状态操作的Lock()



问题:

前端页面发出x个并行请求(我们称之为第一组(,下一组(x请求(将在5秒后,(第一组的(第一个请求从DB设置缓存。其他x-1请求得到了空数组,而不是等待第一个请求完成他的工作。第二组和接下来的所有请求都从缓存中获得了正确的数据。

在无状态机制中,锁定其他线程直到第一次完成(或失败(的最佳实践是什么?

编辑:

缓存模块允许使用set-chache的触发器,但由于它是无状态机制,所以不起作用。

const GetDataFromDB= async (req, res, next) => {
var cachedTableName = undefined;
//  "lockFlag" uses to prevent parallel request to get into  critical section (because its  take time to set cache from db)
//  to prevent that we uses "lockFlag" that is short-initiation to cache.
//
if ( !myCache.has( "lockFlag" ) && !myCache.has( "dbtable" ) ){
// here  arrive first req from first group only
// the other x-1 of first group went to the nest condition
// here i would build mechanism to wait 'till first req come back from DB (init cache)
myCache.set( "lockFlag", "1" )  
const connection1 = await odbc.connect(connectionConfig); 
const cachedTableName = await connection1.query(`select * from ${tableName}`);

if(cachedTableName.length){
const success = myCache.set([
{key: "dbtable", val: cachedTableName, ttl: 180},
])
if(success)
{
cachedTableName = myCache.get( "dbtable" );
}
}
myCache.take("lockFlag");
connection1.close();
return res.status(200).json(cachedTableName ); // uses for first response.
}
// here comes x-1 of first group went to the nest condition and got nothing, bacause the cache not set yet
// 
if ( myCache.has( "dbtable" ) ){
cachedTableName = myCache.get( "dbtable" );
}
return res.status(200).json(cachedTableName );
}

您可以尝试这里给出的方法,并进行一些小的修改以将其应用于您的案例。

  • 为了简洁起见,我删除了注释并缩短了变量名

代码,然后解释:

const EventEmitter = require('events');
const bus = new EventEmitter();
const getDataFromDB = async (req, res, next) => {
var table = undefined;
if (myCache.has("lockFlag")) { 
await new Promise(resolve => bus.once("unlocked", resolve));
}
if (myCache.has("dbtable")) {
table = myCache.get("dbtable");
}
else {
myCache.set("lockFlag", "1");  
const connection = await odbc.connect(connectionConfig); 
table = await connection.query(`select * from ${tableName}`);
connection.close();
if (table.length) {
const success = myCache.set([
{ key: "dbtable", val: table, ttl: 180 },
]);
}
myCache.take("lockFlag");
bus.emit("unlocked");
}
return res.status(200).json(table);
}

这就是它应该如何工作:

  • 起初,lockFlag不存在
  • 然后,一些代码调用getDataFromDB。该代码将第一个if块求值为false,因此它继续:它将lockFlag设置为true("1"(,然后继续从数据库检索表数据。同时:
  • 其他一些代码调用getDataFromDB。然而,该代码将第一个if块求值为true,因此它等待promise,直到发出unlocked事件
  • 回到第一个调用代码:它完成逻辑,缓存表数据,将lockFlag设置回false,发出unlocked事件,然后返回
  • 另一个代码现在可以继续执行:它将第二个if求值为true,因此它从缓存中获取表并返回

作为解决方法,我添加了"最后";第一次启动后从缓存中删除锁定密钥的范围,这是:

while(myCache.has( "lockFlag" )){
await wait(1500);
}

而";等待";功能:

function wait(milleseconds) {
return new Promise(resolve => setTimeout(resolve, milleseconds))
}

(来源(

这是有效的,但可能还有一段时间(<1500毫秒(存在缓存并且线程不知道。

我很乐意提供面糊溶液。

相关内容

  • 没有找到相关文章

最新更新