Nodejs基于LRU算法实现的缓存处理操作示例


Posted in NodeJs onMarch 17, 2017

本文实例讲述了Nodejs基于LRU算法实现的缓存处理操作。分享给大家供大家参考,具体如下:

LRU是Least Recently Used的缩写,即最近最少使用页面置换算法,是为虚拟页式存储管理服务的,是根据页面调入内存后的使用情况进行决策了。由于无法预测各页面将来的使用情况,只能利用“最近的过去”作为“最近的将来”的近似,因此,LRU算法就是将最近最久未使用的页面予以淘汰。

可以用一个特殊的栈来保存当前正在使用的各个页面的页面号。当一个新的进程访问某页面时,便将该页面号压入栈顶,其他的页面号往栈底移,如果内存不够,则将栈底的页面号移除。这样,栈顶始终是最新被访问的页面的编号,而栈底则是最近最久未访问的页面的页面号。

如输入以下序列时:4,7,0,7,1,0,1,2,1,2,6

结果为:

4
4        7
4        7        0
4        0        7
4        0        7        1
4        7        1        0
4        7        0        1
4        7        0        1        2
4        7        0        2        1
4        7        0        1        2
7        0        1        2        6

适用于Node.js的一个LRU缓存,capacity为缓存容量,为0时构造一般缓存。

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缓存信息
LRU原理:对所有缓存数据的key构建hash链表,当对某一数据进行get或put操作时,将其key提到链表前端(最新)。当进行put数据超出容量时,删除链表尾端(最旧)的缓存数据。
hash链表操作可直接定位key,无需历遍整个hash对象,故读写极快。缓存容量不再影响读写速度。
*/
  this.capacity = capacity || Number.MAX_VALUE;
  this.data = {};
  this.hash = {};
  this.linkedList = {
    length: 0,
    head: null,
    end: null
  }
  if (capacity <= 0) this.capacity = Number.MAX_VALUE;
};
CacheLRU.prototype.get = function(key) {
  key = '_' + key;
  var lruEntry = this.hash[key];
  if (!lruEntry) return;
  refresh(this.linkedList, lruEntry);
  return JSON.parse(this.data[key].toString());
};
CacheLRU.prototype.put = function(key, value) {
  key = '_' + key;
  var lruEntry = this.hash[key];
  if (value === undefined) return this;
  if (!lruEntry) {
    this.hash[key] = {key: key};
    this.linkedList.length += 1;
    lruEntry = this.hash[key];
  }
  refresh(this.linkedList, lruEntry);
  this.data[key] = new Buffer(JSON.stringify(value));
  if (this.linkedList.length > this.capacity) this.remove(this.linkedList.end.key.slice(1));
  return this;
};
CacheLRU.prototype.remove = function(key) {
  key = '_' + key;
  var lruEntry = this.hash[key];
  if (!lruEntry) return this;
  if (lruEntry === this.linkedList.head) this.linkedList.head = lruEntry.p;
  if (lruEntry === this.linkedList.end) this.linkedList.end = lruEntry.n;
  link(lruEntry.n, lruEntry.p);
  delete this.hash[key];
  delete this.data[key];
  this.linkedList.length -= 1;
  return this;
};
CacheLRU.prototype.removeAll = function() {
  this.data = {};
  this.hash = {};
  this.linkedList = {
    length: 0,
    head: null,
    end: null
  }
  return this;
};
CacheLRU.prototype.info = function() {
  var size = 0,
    data = this.linkedList.head;
  while (data){
    size += this.data[data.key].length;
    data = data.p;
  }
  return {
    capacity: this.capacity,
    length: this.linkedList.length,
    size: size
  };
};
// 更新链表,把get或put方法操作的key提到链表head,即表示最新
function refresh(linkedList, entry) {
  if (entry != linkedList.head) {
    if (!linkedList.end) {
      linkedList.end = entry;
    } else if (linkedList.end == entry) {
      linkedList.end = entry.n;
    }
    link(entry.n, entry.p);
    link(entry, linkedList.head);
    linkedList.head = entry;
    linkedList.head.n = null;
  }
}
// 对两个链表对象建立链接,形成一条链
function link(nextEntry, prevEntry) {
  if (nextEntry != prevEntry) {
    if (nextEntry) nextEntry.p = prevEntry;
    if (prevEntry) prevEntry.n = nextEntry;
  }
}
module.exports = CacheLRU;
// test:
/*var user = new CacheLRU(5);
user.put('user1', {name:'admin', age: 30});
user.put('user2', {name:'user', age: 31});
user.put('user3', {name:'guest', age: 32});
user.put('user4', {name:'guest', age: 34});
user.put('user5', {name:'guest', age: 35});
console.log(user.get('user1'));
console.log(user.get('user2'));
console.log(user.get('user3'));
user.put('user6', {name:'guest', age: 36});
console.log(user.info());*/

LRU算法也可以用于一些实际的应用中,如你要做一个浏览器,或类似于淘宝客户端的应用的就要用到这个原理。大家都知道浏览器在浏览网页的时候会把下载的图片临时保存在本机的一个文件夹里,下次再访问时就会,直接从本机临时文件夹里读取。但保存图片的临时文件夹是有一定容量限制的,如果你浏览的网页太多,就会一些你最不常使用的图像删除掉,只保留最近最久使用的一些图片。这时就可以用到LRU算法 了,这时上面算法里的这个特殊的栈就不是保存页面的序号了,而是每个图片的序号或大小;所以上面这个栈的元素都用Object类来表示,这样的话这个栈就可以保存的对像了。

希望本文所述对大家nodejs程序设计有所帮助。

NodeJs 相关文章推荐
Nodejs极简入门教程(一):模块机制
Oct 25 NodeJs
详解nodejs 文本操作模块-fs模块(三)
Dec 22 NodeJs
nodejs进阶(6)—连接MySQL数据库示例
Jan 07 NodeJs
图片上传之FileAPI与NodeJs
Jan 24 NodeJs
利用nodejs监控文件变化并使用sftp上传到服务器
Feb 18 NodeJs
用Nodejs搭建服务器访问html、css、JS等静态资源文件
Apr 28 NodeJs
详解redis在nodejs中的应用
May 02 NodeJs
NodeJs搭建本地服务器之使用手机访问的实例讲解
May 12 NodeJs
nodejs中用npm初始化来创建package.json的实例讲解
Oct 10 NodeJs
NodeJS 文件夹拷贝以及删除功能
Sep 03 NodeJs
Nodejs实现图片上传、压缩预览、定时删除功能
Oct 25 NodeJs
基于NodeJS开发钉钉回调接口实现AES-CBC加解密
Aug 20 NodeJs
用nodeJS搭建本地文件服务器的几种方法小结
Mar 16 #NodeJs
nodejs+express实现文件上传下载管理网站
Mar 15 #NodeJs
nodejs搭建本地http服务器教程
Mar 13 #NodeJs
搭建简单的nodejs http服务器详解
Mar 09 #NodeJs
nodejs读写json文件的简单方法(必看)
Mar 09 #NodeJs
Nodejs 获取时间加手机标识的32位标识实现代码
Mar 07 #NodeJs
nodejs中全局变量的实例解析
Mar 07 #NodeJs
You might like
PHP管理内存函数 memory_get_usage()使用介绍
2012/09/23 PHP
php获取mysql字段名称和其它信息的例子
2014/04/14 PHP
Yii2压缩PHP中模板代码的输出问题
2018/08/28 PHP
PHP实现的策略模式示例
2019/03/20 PHP
Laravel框架实现调用百度翻译API功能示例
2019/05/30 PHP
js下用层来实现select的title提示属性
2010/02/23 Javascript
JQuery1.6 使用方法三
2011/11/23 Javascript
jquery中的事件处理详细介绍
2013/06/24 Javascript
jquery控制页面部分刷新的方法
2015/06/24 Javascript
javascript数组排序汇总
2015/07/07 Javascript
基于jQuery实现滚动切换效果
2016/12/02 Javascript
浅谈js中的变量名和函数名重名
2017/02/13 Javascript
JS操作input标签属性checkbox全选的实现代码
2017/03/02 Javascript
详细分析单线程JS执行问题
2017/11/22 Javascript
用React-Native+Mobx做一个迷你水果商城APP(附源码)
2017/12/25 Javascript
vue2.0+koa2+mongodb实现注册登录
2018/04/10 Javascript
基于ionic实现下拉刷新功能
2018/05/10 Javascript
深入学习TypeScript 、React、 Redux和Ant-Design的最佳实践
2019/06/17 Javascript
python3音乐播放器简单实现代码
2020/04/20 Python
利用Python如何生成便签图片详解
2018/07/09 Python
解决pycharm py文件运行后停止按钮变成了灰色的问题
2018/11/29 Python
python登录WeChat 实现自动回复实例详解
2019/05/28 Python
200行python代码实现2048游戏
2019/07/17 Python
浅谈CSS3动画的回调处理
2016/07/21 HTML / CSS
浅谈CSS3鼠标移入图片动态提示效果(transform)
2017/11/06 HTML / CSS
高中毕业自我鉴定范文
2013/10/02 职场文书
理货员的岗位职责
2013/11/23 职场文书
医校毕业生自我鉴定
2014/01/25 职场文书
护士见习期自我鉴定
2014/02/08 职场文书
2014年作风建设工作总结
2014/10/29 职场文书
教师节慰问信
2015/02/15 职场文书
小学新课改心得体会
2016/01/22 职场文书
带你彻底理解JavaScript中的原型对象
2021/04/14 Javascript
vue+spring boot实现校验码功能
2021/05/27 Vue.js
Java后台生成图片的完整步骤
2021/08/04 Java/Android
唤醒紫霞仙子,携手再游三界!大话手游X《大话西游》电影合作专属剧情任务
2022/04/03 其他游戏