node.js - 有什么方法可以减少在 nodejs 中获取数据和缓存的并发请求量?

标签 node.js caching express concurrency redis

我有一个 Express 应用程序,它需要非常低的响应率 ~<200 毫秒。现在我们只能得到这个数字,但这是一个单独的话题。

我们计划从数据库中获取一段数据,如果在 Redis 中找到,则返回数据,如果没有,则触发请求并将其保存到 Redis,以便下一个请求可以从 Redis 中获取它。

我正在运行一些测试,想知道是否有办法减少数据库获取请求的数量?

例如,目前我们的应用程序每个盒子有 300req/s。我们有六个盒子在 AWS 上运行。如果那条数据第一次在 Redis 中不可用,可能会有大约 500 个请求试图从数据库中获取数据并将其缓存在 Redis 中。我们正在努力减少这个数字。不确定 Node.js 或 Redis 中是否有处理该问题的方法。

这是我正在测试的代码。

client.getAsync('key').then(function (data) {
  if(data) {
    console.log(data); // Return this data if found
    res.send(data);
  } else {
    // I'm trying to reduce the number of calls for concurrent requests in this block.
    console.log('not found');
    var dataFromDb = // fetch data from DB
    client.set('key', dataFromDb); // Fire and forget 
    res.send('not found'); // Return not found right away
  }
});

然后我使用 ab

测试调用
ab -n 20 -c 10 http://localhost:8081/redis

这是我得到的结果

not found
not found
not found
not found
not found
not found
something
not found
something
something
something
something
something
something
something
something
something
something

在这个例子中,有 7 个请求试图获取具有相同数据的数据库并保存到 Redis。

我的问题是,无论如何我可以减少请求的数量吗?因为目前获取 DB 非常慢 ~900ms(我们正在尝试优化它)

最佳答案

是的。我做了同样的事情。我将在这里只描述逻辑。 fetchCache 的方法应该返回一个 promise 。您还保留 { cacheKey, promise } 数组。每次发送请求时,您都会向该数组添加键。下次你需要获取缓存时 - 你首先检查数组,如果那里有关键,则捕获这个 promise 。否则调用 fetchCache。

这是我的代码。它有效,但可能难以阅读。应该让您有一个基本的了解。

class DictTranslatableRepo {

    constructor(model) {
        var self = this;
        self.title = model + "s Repo";

        self.model = models[model];
        self.running = {};
        self.curItems = {};
    }


    *start() {
        var self = this;
        var curItems = yield self.model.findAll();
        _.forEach(curItems, function(row) {
            self.curItems[row.key] = row.value;
        });
    };


    *map(from) {
        var self = this;

        if (from == "") return "";

        if (!_.isUndefined(self.curItems[from])) return self.curItems[from];

        if (_.isUndefined(self.running[from])) {
            self.running[from] = [];
            return new Promise(function(resolve, reject) {
                self.running[from].push(resolve);

                self.job(from, function(err, to) {       // Main job
                    var callbackArr = self.running[from];
                    delete self.running[from];
                    _.forEach(callbackArr, function(callback) {
                        callback(to);
                    });
                });
            });
        } else {
            return new Promise(function(resolve, reject) {
                self.running[from].push(resolve);
            });
        }
    };


    job(from, callback) {
        var self = this;
        var to = "as shown";
        co(function*() {
            try {
                to = yield translator.translate(from);
                yield self.model.add({key: from, value: to});
                self.curItems[from] = to;
                callback(null, to);
            } catch (err) {
                callback(err);
                //logger.error("Cant translate entity: " + from);
            }
        }).catch(function(err) {
            // Unhandled Error
            callback(new Error(err));
        });
    };

}

我的 map 方法是您的 fetchCache 方法。

关于node.js - 有什么方法可以减少在 nodejs 中获取数据和缓存的并发请求量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35950293/

相关文章:

javascript - 使用 Express PUT 路由后未执行代码

javascript - Firebase 云函数使用 fetch() 反复循环

Javascript Service Worker 在网络超时后使用缓存

azure - 在 Azure Function 中编译模板时,RazorEngine 抛出 NotSupportedException

javascript - 在 express 中调用函数 - 未定义

javascript - 检查数组中是否存在对象元素

node.js - Node 应用程序为实时网站创建生产版本 - 静态文件(网络主机上没有运行 Node )

vb.net - 禁用页面缓存以使用浏览器后退按钮强制页面加载

javascript - 升级到 Node 0.10 后的问题

javascript - 格式化从 PostgreSql 数据库检索的 JSON 数据