我的应用程序进行大约 50 个 redis.get
调用来服务单个 http 请求,它每天服务数百万个请求,并且应用程序在大约 30 个 pod 上运行。
当监视 newrelic 时,我的平均 redis.get
时间为 200MS,为了优化这一点,我在 Nodejs 中编写了一个简单的管道系统,它只是 redis.get
的包装器> 它将所有请求推送到队列中,然后使用 redis.mget
执行队列(批量获取所有键)。
以下是代码片段:
class RedisBulk {
constructor() {
this.queue = [];
this.processingQueue = {};
this.intervalId = setInterval(() => {
this._processQueue();
}, 5);
}
clear() {
clearInterval(this.intervalId);
}
get(key, cb) {
this.queue.push({cb, key});
}
_processQueue() {
if (this.queue.length > 0) {
let queueLength = this.queue.length;
logger.debug('Processing Queue of length', queueLength);
let time = (new Date).getTime();
this.processingQueue[time] = this.queue;
this.queue = []; //empty the queue
let keys = [];
this.processingQueue[time].forEach((item)=> {
keys.push(item.key);
});
global.redisClient.mget(keys, (err, replies)=> {
if (err) {
captureException(err);
console.error(err);
} else {
this.processingQueue[time].forEach((item, index)=> {
item.cb(err, replies[index]);
});
}
delete this.processingQueue[time];
});
}
}
}
let redis_bulk = new RedisBulk();
redis_bulk.get('a');
redis_bulk.get('b');
redis_bulk.get('c');
redis_bulk.get('d');
我的问题是:这是一个好方法吗?它对优化redis获取时间有帮助吗?对于上述问题还有其他解决方案吗?
谢谢
最佳答案
我不是 Redis 专家,但从文档来看;
MGET 的时间复杂度为
O(N) where N is the number of keys to retrieve.
并且GET的时间复杂度为
O(1)
这使得两种场景在时间复杂度方面达到相同的最终结果。使用 MGET 进行批量请求可以为 IO 带来一些改进,但除此之外,您似乎还面临着相同的瓶颈。
理想情况下,我会将数据分割成 block ,通过异步方式通过多个 http 请求进行响应(如果可以的话)。
或者,您可以尝试使用 promise.all()
调用 GET 来并行运行 GET 请求,以满足您需要的所有 GET 调用。
类似于;
const asyncRedis = require("async-redis");
const client = asyncRedis.createClient();
function bulk() {
const keys = [];
return Promise.all(keys.map(client.get))
}
关于node.js - 将redis.get分组2ms,然后通过mget执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58747784/