Node 里怎样对付缓存
发布于 2年前 作者 jiyinyiyong 1408 次浏览

数据基本上很长时间不做改变的站点… 想起来 PHP 有缓存. 比如频繁访问的数据卸载文件… 在 Node 里缓存是怎么处理的? 缓存是放在磁盘里做文件, 还是直接在内存里用一个变量存储, 这在性能上怎么考虑?

20 回复

看情况了,我一般直接一个变量存储,大一点的用Buffer

放在磁盘中肯定不够放在内存中快了,但是放在磁盘中容量可以很大。

如果内存足够,一般都会优先选择放在内存中吧。还有,放在内存中万一程序重启了,之前的缓存就木有了。

用 Buffer 是怎么做?

是啊是啊, 还是内存最快了.

@jiyinyiyong var str = JSON.decode({"key":"value"}); 降对象变成json字符串之后,再变成buffer对象 var buffer = new Buffer(str); 反之亦然

@jiyinyiyong Buffer对象是不归V8管理的,所以,不受V8的内存限制

@151263 原来是这样. 只是 Buffer 访问不会有 JSON 那么方便的吧, 这应该如何解决?

@jiyinyiyong 自己封装成一个函数嘛,比如:

var cache = {};

exports.set = function (n, v) {
  cache[n] = new Buffer(JSON.stringify(v));
};

exports.get = function (n) {
  return JSON.parse(cache[n].toString());
};

我的做法是从档案读取,然后每隔一段时间将内存的数据储存 储存时我还使用了lzw算法来压缩文件

@leizongmin 哦, 我还以为纯粹用 Buffter. 用 JSON 存储 key, 用 Buffer 存储 value, 这样就清晰了 Buffer 的速度这么说是接近内存, 又比磁盘快很多的?

这样的缓存有必要么, 集群呢, 就算不集群, 那么worker之间内存无法共享, 用处太弱了, 还是memcache或者redis之类的

小型应用就对象,大型应用redis。

是不说直接用模块了… 搜到个时间比较久的… https://github.com/mape/node-caching

刚接触到这个问题… 的确是超小型的应用…

function CacheLRU(capacity) {
/*  利用Buffer写的一个LRU缓存,capacity为缓存容量,为0时构造一般缓存。
    myCache = new CacheLRU(capacity); //构造缓存
    myCache.get(key); //读取名为key的缓存值
    myCache.put(key, value); //写入名为key的缓存值
    myCache.remove(key); //删除名为key的缓存值
    myCache.removeAll(); //删除所有缓存值
    myCache.info(); //返回myCache缓存信息,包括:
    {capacity: 缓存容量,
            length: 当前已使用容量,
            size: 缓存数据大小bytes,
            ratio: 缓存命中率,
            keys: 当前已缓存的数据名称(key)数组
    }
*/
    this.capacity = capacity || 0;
    this.cache = {};
    this.hash = {};
    this.miss = 0;
    if(capacity < 0) this.capacity = 0;
};
//为了提高取值效率,get方法只有取值和取值计数操作,key为string类型。
CacheLRU.prototype.get = function(key) {
    key = '_' + key;
    if(this.hash[key]) this.hash[key] += 1;
    else this.miss += 1;
    return JSON.parse(this.cache[key].toString());
};
//LRU cache由存值put方法实现
CacheLRU.prototype.put = function(key, value) {
    key = '_' + key;
    if(this.capacity === 0) {
        this.cache[key] = new Buffer(JSON.stringify(value));
        this.hash[key] = 1;
    } else {
        var r = Object.keys(this.hash);
        if(r.length < this.capacity) {
            this.cache[key] = new Buffer(JSON.stringify(value));
            this.hash[key] = 1;
        } else {
            that = this;
            r.sort(function(a, b) {
                return that.hash[a] - that.hash[b];
            });
            delete this.cache[r[0]];
            delete this.hash[r[0]];
            this.cache[key] = new Buffer(JSON.stringify(value));
            this.hash[key] = 1;
        }
    }
    return this;
};
CacheLRU.prototype.info = function() {
    var keys = Object.keys(this.hash);
    var hit = 0, size = 0;
    keys.forEach(function(key, i) {
        if(this.hash[key]) hit += this.hash[key];
        size += this.cache[key].length;
        keys[i] = key.slice(1);
    }, this);
    return {
        capacity: this.capacity,
        length: keys.length,
        size: size,
        ratio: hit / (this.miss + hit),
        keys: keys
    };
};
CacheLRU.prototype.remove = function(key) {
    key = '_' + key;
    delete this.cache[key];
    delete this.hash[key];
    return this;
};
CacheLRU.prototype.removeAll = function() {
    this.cache = {};
    this.hash = {};
    return this;
};

module.exports = CacheLRU;

// test:
/*var user = new CacheLRU(10);
user.put('user1', {name:'admin', age: 30});
user.put('user2', {name:'user', age: 31});
user.put('user3', {name:'guest', age: 32});
console.log(user.get('user1'));
console.log(user.get('user2'));
console.log(user.get('user3'));
console.log(user.info());*/

还有一个直接使用内存对象缓存(存在V8引擎内)的版本,见 https://github.com/zensh/jsgen/blob/dev/lib/tools.js

经测试,使用Buffer构建的读写都要快一点,容量也不受V8限制,只是不适合在客户端浏览器使用

上面get方法还有一个bug,如果值不存在,会抛出错误,更新后的版本在 https://gist.github.com/zensh/5069881

回到顶部