Nodejs里怎样对付缓存

Nodejs里怎样对付缓存

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

15 回复

在Node.js中,缓存管理是一个重要的方面,特别是在处理频繁访问的数据时。缓存可以显著提高应用程序的性能,减少对数据库或外部API的调用次数。在Node.js中,缓存可以存储在内存中或磁盘上,每种方法都有其优缺点。

内存缓存

内存缓存是最常见的缓存方式,因为它速度快且易于实现。Node.js提供了多种库来帮助你管理内存中的缓存,例如node-cachelru-cache等。

示例代码(使用node-cache

const NodeCache = require('node-cache');
const myCache = new NodeCache();

// 存储缓存数据
myCache.set("key", "value", 100); // 缓存有效期为100秒

// 获取缓存数据
const value = myCache.get("key");
console.log(value); // 输出: value

// 删除缓存数据
myCache.del("key");

// 检查缓存是否存在
const hasKey = myCache.has("key");
console.log(hasKey); // 输出: false

磁盘缓存

磁盘缓存适用于需要持久化的场景,即使应用程序重启,缓存数据也不会丢失。常用的库包括fs模块(Node.js内置)或第三方库如lowdb

示例代码(使用fs模块)

const fs = require('fs');

// 存储缓存数据到文件
const data = { key: 'value' };
fs.writeFile('cache.json', JSON.stringify(data), (err) => {
    if (err) throw err;
    console.log('Data written to file');
});

// 从文件读取缓存数据
fs.readFile('cache.json', 'utf8', (err, data) => {
    if (err) throw err;
    const parsedData = JSON.parse(data);
    console.log(parsedData); // 输出: { key: 'value' }
});

性能考量

  • 内存缓存:访问速度快,但数据不会持久化,服务器重启后缓存将丢失。
  • 磁盘缓存:数据持久化,但读写速度相对较慢,适合需要长期保存数据的场景。

选择哪种缓存方式取决于你的具体需求。对于频繁访问且不经常变化的数据,内存缓存是更好的选择;而对于需要长期保存的数据,则应考虑使用磁盘缓存。


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

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

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

用 Buffer 是怎么做?

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

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

这样的缓存有必要么, 集群呢, 就算不集群, 那么worker之间内存无法共享, 用处太弱了, 还是memcache或者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

在Node.js中处理缓存通常有两种方式:内存缓存和磁盘缓存。内存缓存速度更快,但重启后数据会丢失;磁盘缓存持久化,但读写操作相对较慢。

示例代码

内存缓存

使用memory-cache库来实现内存缓存:

  1. 安装依赖:

    npm install memory-cache
    
  2. 使用内存缓存:

    const cache = require('memory-cache');
    
    function getFromCache(key) {
      return cache.get(key);
    }
    
    function setToCache(key, value, duration) {
      cache.put(key, value, duration);
    }
    
    // 示例用法
    setToCache('data', 'Some data', 60 * 1000); // 缓存1分钟
    console.log(getFromCache('data')); // 输出 'Some data'
    

磁盘缓存

使用fs模块来实现磁盘缓存:

const fs = require('fs');
const path = require('path');

function getFromDiskCache(filePath) {
  try {
    const data = fs.readFileSync(filePath, 'utf-8');
    return JSON.parse(data);
  } catch (error) {
    return null;
  }
}

function setToDiskCache(filePath, data, duration) {
  setTimeout(() => {
    fs.unlinkSync(filePath);
  }, duration);

  fs.writeFileSync(filePath, JSON.stringify(data));
}

// 示例用法
const filePath = path.join(__dirname, 'cache.json');
setToDiskCache(filePath, { key: 'value' }, 60 * 1000); // 缓存1分钟
console.log(getFromDiskCache(filePath)); // 输出 { key: 'value' }

性能考虑

  • 内存缓存:适合频繁读取且不经常变化的数据。优点是速度快,缺点是重启后数据会丢失。
  • 磁盘缓存:适合需要持久化的数据。优点是数据持久化,缺点是读写速度较慢。

选择哪种方式取决于你的具体需求。如果数据变化不大且需要快速访问,建议使用内存缓存;如果数据需要持久化存储,可以选择磁盘缓存。

回到顶部