
隨著前端越來越重,已經不是當年的一個頁面配幾個第三方js庫實作一些花俏的效果,而是出現了各種各樣的框架解決方案.
當我們專案實作前后端分離時,甚至一些邏輯處理也會放到前端來處理.
所以隨隨便便打開一個頁面上百k應該也是正常,甚至更大的頁面在考驗的前端.
但是伴隨成長的后端,尤其數存盤方面貌似發展緩慢,總有跟不上的趕腳!
想當年我們使用關系型資料庫,當達到一個瓶頸時,解決起來是不計后果的,讀寫分離,拆表拆庫,做service中間件,然后給中間件負載均衡等等來減輕前端并發造成的后端資料壓力.
如今的mongodb 做一個分布式貌似輕輕松松, redis 做一層快取讓你有飛一樣的感覺.我們終于談到了快取.
快取應用場景很多,空間換時間的原理,會占用一點點記憶體,但是給你的web服務提升明顯的性能.
并不是所有的資料都要放到快取.不長更新的,沒有實時性的資料可以暫時用快取來處理.比如我的博客首頁大概一天更新一次,變化并不是很大.
就可以把首頁資料放到快取來處理.
雖然我的資料庫用的LevelDB ,號稱也是處理海量資料的本地資料庫,關于高性能LevelDB使用,請點擊查看另外一篇博文
就算性能再高也是走IO,畢竟不如直接命中記憶體來的簡單粗暴.
需求:
我只快取首頁,所以一定要輕量級,默認快取一天,當發布新博客時,清楚快取即可.
解決方案:
node-cache
官方地址:https://github.com/ptarjan/node-cache
絕對夠小巧,還滿足我簡單的需求.
node-cache API 使用請移步到github 查看.
原始碼如下:
'use strict';
var cache = Object.create(null);
var debug = false;
var hitCount = 0;
var missCount = 0;
var size = 0;
exports.put = function(key, value, time, timeoutCallback) {
if (debug) {
console.log('caching: %s = %j (@%s)', key, value, time);
}
var oldRecord = cache[key];
if (oldRecord) {
clearTimeout(oldRecord.timeout);
} else {
size++;
}
var expire = time + Date.now();
var record = {
value: value,
expire: expire
};
if (!isNaN(expire)) {
var timeout = setTimeout(function() {
exports.del(key);
if (typeof timeoutCallback === 'function') {
timeoutCallback(key);
}
}, time);
record.timeout = timeout;
}
cache[key] = record;
};
exports.del = function(key) {
var canDelete = true;
var oldRecord = cache[key];
if (oldRecord) {
clearTimeout(oldRecord.timeout);
if (!isNaN(oldRecord.expire) && oldRecord.expire < Date.now()) {
canDelete = false;
}
} else {
canDelete = false;
}
if (canDelete) {
size--;
delete cache[key];
}
return canDelete;
};
exports.clear = function() {
for (var key in cache) {
var oldRecord = cache[key];
if (oldRecord) {
clearTimeout(oldRecord.timeout);
}
}
size = 0;
cache = Object.create(null);
if (debug) {
hitCount = 0;
missCount = 0;
}
};
exports.get = function(key) {
var data = cache[key];
if (typeof data != "undefined") {
if (isNaN(data.expire) || data.expire >= Date.now()) {
if (debug) hitCount++;
return data.value;
} else {
// free some space
if (debug) missCount++;
size--;
delete cache[key];
}
} else if (debug) {
missCount++;
}
return null;
};
exports.size = function() {
return size;
};
exports.memsize = function() {
var size = 0,
key;
for (key in cache) {
size++;
}
return size;
};
exports.debug = function(bool) {
debug = bool;
};
exports.hits = function() {
return hitCount;
};
exports.misses = function() {
return missCount;
};
exports.keys = function() {
return Object.keys(cache);
};
var cache = Object.create(null);
加載此模塊時,初始化 cache 物件,
從上到下 首先來看一下 put api
exports.put = function(key, value, time, timeoutCallback) {
if (debug) {
console.log('caching: %s = %j (@%s)', key, value, time);
}
var oldRecord = cache[key];
if (oldRecord) {
clearTimeout(oldRecord.timeout);
} else {
size++;
}
var expire = time + Date.now();
var record = {
value: value,
expire: expire
};
if (!isNaN(expire)) {
var timeout = setTimeout(function() {
exports.del(key);
if (typeof timeoutCallback === 'function') {
timeoutCallback(key);
}
}, time);
record.timeout = timeout;
}
cache[key] = record;
};
接受4個引數 ,key,value,time(過期時間) , timeoutCallback (到期時回呼函式)
var oldRecord=cache[key];
if(oldRecord)
如果此快取已經存在:
clearTimeout(oldRecord.timeout);
這個方法大家應該明白, 清楚 setTimeout 定時任務的.(這里的作用就是,如果此快取已經存在,接著你有呼叫了put 函式,說明你要更新此快取,那么就把之前的定時器清除掉)
esle
size ++;
這里的 size 是維護當前快取個數的一個變數,如果從來沒有快取過此物件,說明是新加的快取,size 也相應加一.
var expire=time+Date.now();
過期時間=我們傳入的時間間隔+當前時間.
var record 此物件包含了快取 value 和 過期時間.
接著
if(!isNaN(expire)){
//如果設定了快取時間,創建一個定時器(當定時器過期失效時,清楚此快取)
var timeout=setTimeout(function(){
//呼叫 del() 函式清楚快取
},time);
//record 物件上添加了一個屬性 timeout
record.timeout=timeout;
}
//cache 物件添加了一個屬性 key ,和 value ( record )
cache[key]=record;
看完這個大概就明白了.這個模塊其實維護了一個物件 cache={};
添加一個 key='index_page' value=[a,b,c,d,e,f,g]; 的快取時.
相當于
cache={
'index_page':
[a,b,c,d,e,f,g]
}
接著我添加一個帶過期時間的快取: 3000毫秒后過期 key='list' value=[1,2,3,4,5];
相當于
cache={
'index_page':[a,b,c,d,e,f,g],
'list':{
timeout:當前時間+3000,
value:[1,2,3,4,5]
}
}
洗掉一個快取,其實就是在 cache 物件上洗掉一個屬性為 key 的欄位.
如 : 洗掉 'index_page' 快取
delete cache.index_page
如果我要更新 list 快取:
首先要清楚 list 定義的定時器
clearTimeout(cache.list.timeout); //此timeout 就是定時器ID,根據ID可以直接清除掉定時器
接著判斷新更新的快取有沒有設定過期時間
如果有,繼續設定一個新的定時器.
如果沒有,直接用最新的value 覆寫之前的 value 即可達到更新快取效果.
原文鏈接:https://yijiebuyi.com/blog/c37a444faab98617a98098f7a29e09db.html
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/258926.html
標籤:其他
上一篇:Mysql原理決議 - 基本架構
