性能是最重要的一个指标需要评估在开发一个web服务.
缓存是一个战略旨在解决主要的存储问题,这意味着:存储越大,越慢,反之亦然。缓存是一个组件,最近访问的数据存储在一个更快的存储系统。每次请求数据,(有一些概率)可以从内存越快。
传统上我们的 后台服务就是接收前端过来的 request请求,进入对应的 controller ,执行一系列方法,查库。。。
module.exports.findBookByTitle = function (db, title, callback) {
db.collection('text').findOne({
title: title
}, function (err, doc) {
if (err || !doc) callback(null);
else callback(doc.text);
});
};
但是有些频繁的查库 可能会成为,server的性能负担。因此 引入了 redis把经常访问的数据存入内存,以后访问的时候直接从内存获取,这样会减少数据库的负担。
引入缓存机制
缓存在server中扮演的角色(来源:https://www.sitepoint.com/caching-a-mongodb-database-with-redis/)
nodejs 引入redis很简单 可以在 npm上搜索,有简单的api教程。
下来我们看看 引入缓存 之后 的查询代码:
module.exports.findBookByTitleCached = function (db, redis, title, callback) {
redis.get(title, function (err, reply) {
if (err) callback(null);
else if (reply) //Book exists in cache
callback(JSON.parse(reply));
else {
//Book doesn't exist in cache - we need to query the main database
db.collection('text').findOne({
title: title
}, function (err, doc) {
if (err || !doc) callback(null);
else {\\Book found in database, save to cache and
return to client
redis.set(title, JSON.stringify(doc), function () {
callback(doc);
});
}
});
}
});
};
看一下 路由:
app.get('/book/:title', function (req, res) {
if (!req.param('title')) res.status(400).send("Please send a proper title");
else {
access.findBookByTitleCached(db, redis, req.param('title'), function (book) {
if (!text) res.status(500).send("Server error");
else res.status(200).send(book);
});
}
});
请求进入路由后,会判断 缓存中时候有请求的数据,如果有就从换从中直接拿来主义,否则查库,并将数据存入缓存中。
当然,redis缓存如果只是这么简单的用,这样结果会成为负担,缓存的数据越来越越多。内存被占用,服务器性能就会下降,对于优秀的redis作为缓存来说,怎么可能会这么low,reis带有缓存策略,对缓存进行管理。
由于内存限制,我们必须删除缓存中的某些产品和只保留其中的一些。理想情况下,我们要保持这些的几率最高的再次阅读。选择我们要删除的项目,我们必须建立一种缓存策略。删除随机项可能是一个有效的政策,但它显然不会是非常有效的。我们将使用一个最受欢迎的政策:LRU
LRU:
置换策略
当Redis内存使用达到maxmemory
时,需要选择设置好的maxmemory-policy
进行对老数据的置换。
下面是可以选择的置换策略:
noeviction
: 不进行置换,表示即使内存达到上限也不进行置换,所有能引起内存增加的命令都会返回errorallkeys-lru
: 优先删除掉最近最不经常使用的key,用以保存新数据volatile-lru
: 只从设置失效(expire set)的key中选择最近最不经常使用的key进行删除,用以保存新数据allkeys-random
: 随机从all-keys中选择一些key进行删除,用以保存新数据volatile-random
: 只从设置失效(expire set)的key中,选择一些key进行删除,用以保存新数据volatile-ttl
: 只从设置失效(expire set)的key中,选出存活时间(TTL)最短的key进行删除,用以保存新数据
要合理的运用管理缓存,这样才能为我们的server插上“”翅膀“”
保持更新缓存。
module.exports.access.updateBookByTitle = function (db, redis, title, newText, callback) {
db.collection("text").findAndModify({
title: title
}, {
$set: {
text: text
}
}, function (err, doc) { //Update the main database
if (err) callback(err);
else if (!doc) callback('Missing book');
else {
//Save new book version to cache
redis.set(title, JSON.stringify(doc), function (err) {
if (err) callback(err);
else callback(null);
});
}
});
};
app.put('/book/:title', function (req, res) {
if (!req.param("title")) res.status(400).send("Please send the book title");
else if (!req.param("text")) res.status(400).send("Please send the new text");
else {
access.updateBookByTitle(db, redis, req.param("title"), req.param("text"), function (err) {
if (err == "Missing book") res.status(404).send("Book not found");
else if (err) res.status(500).send("Server error");
else res.status(200).send("Updated");
});
}
});
最近在考虑缓存的使用场景,例如复杂查询,访问度较高的数据,等