Nodejs中一个cache的设计

Nodejs中一个cache的设计

var cache = {};
function getCache(key, dep) {

if (cache[key] == undefined) {

    dep.call(null,function(err, list) {

        cache[key] = list;

    });
    return cache[key];
} else {

    return cache[key];
}

}

var data = getCache(“aa”, function(cb) { BlogModel.find({}, cb);

});

console.log(data);

本来是根据key去cache中查找,如果找不到,就执行BlogModel查数据然后放在cache中,因为异步的原因返回是undefined,但如果在cb写在getCache调用的代码里,嵌套就太深了,而且代码都一样,看有没有更好的办法</code></pre>

7 回复

在Node.js中设计一个缓存(Cache)机制时,需要考虑几个关键点:缓存的存储结构、缓存的更新策略、以及如何处理异步操作。你提供的代码已经是一个不错的起点,但是它存在一些问题,比如回调地狱(Callback Hell)和返回值的问题。

为了改进这一点,我们可以使用Promises或async/await来更好地管理异步操作,并且确保缓存逻辑更清晰和易于维护。以下是一个改进后的示例:

// 引入必要的模块
const util = require('util');
const BlogModel = require('./models/BlogModel'); // 假设你有一个BlogModel模型

// 将回调函数转换为Promise
const findAsync = util.promisify(BlogModel.find.bind(BlogModel));

// 缓存对象
const cache = {};

// 获取缓存的函数
async function getCache(key, fetchFn) {
    if (!cache[key]) {
        try {
            cache[key] = await fetchFn();
        } catch (err) {
            console.error(`Error fetching data for key ${key}:`, err);
            throw err;
        }
    }
    return cache[key];
}

// 示例使用
(async () => {
    const fetchData = async () => {
        const result = await findAsync({});
        return result;
    };

    try {
        const data = await getCache('aa', fetchData);
        console.log(data);
    } catch (err) {
        console.error('Failed to retrieve data:', err);
    }
})();

解释:

  1. Promisification:我们使用util.promisifyBlogModel.find方法转换为返回Promise的形式。这使得我们可以更容易地处理异步操作。
  2. 异步函数getCache函数被定义为async,这样可以使用await关键字来等待异步操作完成。
  3. 缓存逻辑:在getCache函数中,我们检查缓存中是否已经存在指定键的数据。如果不存在,则调用fetchFn函数获取数据并将其存储到缓存中。
  4. 错误处理:我们使用try...catch块来捕获并处理可能发生的错误。

这种方法不仅避免了回调地狱的问题,还使得代码更加清晰和易于理解。


var cache = {};
function getCache(key, dep, callback) {
  if (!cache.hasOwnProperty(key)) {
    dep.call(null,function(err, list) {
      cache[key] = list;
      callback(null, list);
    });
  } else {
    callback(null, cache[key]);
  }
}

getCache("aa", function (cb) {
  BlogModel.find({}, cb);
}, function (err, data) {
  console.log(data);
});

学习了,改装一下 就可以弄成redis缓存的那种样子。

我的页面上有多块缓存的数据,依次读出来一起render一个模板,如果写成回调的话, 两部分数据没法写个一个回调里面render一个模板的

不行的,object 的key 一多,性能马上就下去了。玩玩还可以,实际千万别这么搞。

var redis = require('redis');
var client = redis.createClient();


var cache = {}

cache.getKey = function(key, callback){
  client.get(key, callback);
};

cache.setKey = function(key, val, callback){
	client.set(key, val, function(err){
		callback(err, val);
	});
}

var getCache = function(key, dep, callback){
	cache.getKey(key, function(err, replies){
		if(err) return callback(err);

		if(!replies) {
			dep.call(null, function(err, val){
				if(err) return callback(err);
				cache.setKey(key, val, callback);
			});
		} else {
			return callback(err, replies);
		}
	});
}

getCache('aa', function(cb){
	cb(null, '123')

},function(err, data){
	console.log(data);
});

redis缓存版本

在Node.js中设计一个缓存机制时,通常需要考虑缓存的更新、过期以及并发访问等问题。你当前的实现存在一些问题,例如异步回调导致的返回值问题。下面是一种改进方案,使用Promise来解决异步回调地狱(callback hell)的问题,并且更好地处理缓存逻辑。

示例代码

const LRU = require('lru-cache');

const cache = new LRU({ max: 500, maxAge: 1000 * 60 * 60 }); // 设置最大缓存数量和最大存活时间

function getCache(key, fetcher) {
    return new Promise((resolve, reject) => {
        if (cache.has(key)) {
            resolve(cache.get(key));
        } else {
            fetcher()
                .then(result => {
                    cache.set(key, result);
                    resolve(result);
                })
                .catch(reject);
        }
    });
}

// 使用示例
getCache("aa", () => {
    return new Promise((resolve, reject) => {
        BlogModel.find({}, (err, list) => {
            if (err) reject(err);
            else resolve(list);
        });
    });
}).then(data => {
    console.log(data);
}).catch(err => {
    console.error(err);
});

解释

  1. 引入LRU缓存库LRU是一个高效的缓存库,可以方便地管理缓存大小和过期时间。
  2. 定义getCache函数:该函数接受一个键名和一个获取数据的函数作为参数。如果缓存中有对应的数据,则直接返回;否则,调用获取数据的函数并将结果存储在缓存中。
  3. 使用Promise:通过返回Promise,我们避免了回调地狱,使代码更易于阅读和维护。
  4. 示例使用:在调用getCache时,传入一个返回Promise的函数,这样可以在异步操作完成后正确地处理结果。

这种方法不仅解决了异步回调的问题,还使得缓存的管理和更新更加清晰和高效。

回到顶部