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调用cmd命令实现复制目录
May 04 NodeJs
NodeJS创建基础应用并应用模板引擎
Apr 12 NodeJs
Nodejs中解决cluster模块的多进程如何共享数据问题
Nov 10 NodeJs
详解nodejs 文本操作模块-fs模块(四)
Dec 22 NodeJs
利用nodejs监控文件变化并使用sftp上传到服务器
Feb 18 NodeJs
详解nodeJS中读写文件方法的区别
Mar 06 NodeJs
详解nodejs微信公众号开发——4.自动回复各种消息
Apr 11 NodeJs
nodejs 简单实现动态html的方法
May 12 NodeJs
Nodejs模块的调用操作实例分析
Dec 25 NodeJs
通过Nodejs搭建网站简单实现注册登录流程
Jun 14 NodeJs
nodejs对项目下所有空文件夹创建gitkeep的方法
Aug 02 NodeJs
Nodejs实现WebSocket代码实例
May 19 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中simplexml_load_file函数用法实例
2014/11/12 PHP
PHP使用array_multisort对多个数组或多维数组进行排序
2014/12/16 PHP
PHP实现的json类实例
2015/07/28 PHP
php版阿里大于(阿里大鱼)短信发送实例详解
2016/11/30 PHP
laravel5.2实现区分前后台用户登录的方法
2017/01/11 PHP
thinkPHP5.0框架事务处理操作简单示例
2018/09/07 PHP
ExtJS 2.0实用简明教程 之Border区域布局
2009/04/29 Javascript
DOM 中的事件处理介绍
2012/01/18 Javascript
javascript中的=等号个数问题两个跟三个有什么区别
2013/10/23 Javascript
jQuery中$this和$(this)的区别介绍(一看就懂)
2015/07/06 Javascript
node.js express中app.param的用法详解
2017/07/16 Javascript
JS随机排序数组实现方法分析
2017/10/11 Javascript
vue实现学生录入系统之添加删除功能
2018/07/11 Javascript
vue实现点击隐藏与显示实例分享
2019/02/13 Javascript
解决ie11 SCRIPT5011:不能执行已释放Script的代码问题
2019/05/05 Javascript
js仿京东放大镜效果
2020/08/09 Javascript
如何运行Python程序的方法
2013/04/21 Python
python求斐波那契数列示例分享
2014/02/14 Python
Python的Flask框架中集成CKeditor富文本编辑器的教程
2016/06/13 Python
Python中文分词工具之结巴分词用法实例总结【经典案例】
2017/04/15 Python
一条命令解决mac版本python IDLE不能输入中文问题
2018/05/15 Python
pandas.DataFrame.drop_duplicates 用法介绍
2020/07/06 Python
分享一个python的aes加密代码
2020/12/22 Python
详解如何使用CSS3中的结构伪类选择器和伪元素选择器
2020/01/06 HTML / CSS
递归计算如下递归函数的值(斐波拉契)
2012/02/04 面试题
linux面试相关问题
2012/08/11 面试题
How TDD works
2012/09/30 面试题
毕业生个人求职的自我评价
2013/10/28 职场文书
小学科学教学反思
2014/01/26 职场文书
小学生开学第一课活动方案
2014/03/27 职场文书
物流管理专业推荐信
2014/09/06 职场文书
财务科长个人对照检查材料
2014/09/18 职场文书
施工安全协议书
2016/03/22 职场文书
健身房被搭讪?用python写了个小米计时器助人为乐
2021/06/08 Python
Python基础之变量的相关知识总结
2021/06/23 Python
HTML CSS 一个标签实现带动画的抖音LOGO
2022/04/26 HTML / CSS