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开发cli项目实例
Jun 03 NodeJs
使用Angular和Nodejs、socket.io搭建聊天室及多人聊天室
Aug 21 NodeJs
Nodejs爬虫进阶教程之异步并发控制
Feb 15 NodeJs
图片上传之FileAPI与NodeJs
Jan 24 NodeJs
详谈Angular路由与Nodejs路由的区别
Mar 05 NodeJs
NodeJS学习笔记之Module的简介
Mar 24 NodeJs
深入理解Nodejs Global 模块
Jun 03 NodeJs
NodeJS实现图片上传代码(Express)
Jun 30 NodeJs
nodejs创建简易web服务器与文件读写的实例
Sep 07 NodeJs
Nodejs处理异常操作示例
Dec 25 NodeJs
Nodejs文件上传、监听上传进度的代码
Mar 27 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中一个完整表单处理实现代码
2011/11/10 PHP
php实现监听事件
2013/11/06 PHP
PHP上传图片进行等比缩放可增加水印功能
2014/01/13 PHP
启用Csrf后POST数据时出现的400错误
2015/07/05 PHP
php生成酷炫的四个字符验证码
2016/04/22 PHP
PHP实现求连续子数组最大和问题2种解决方法
2017/12/26 PHP
解决php extension 加载顺序问题
2019/08/16 PHP
javascript中length属性的探索
2011/07/31 Javascript
70+漂亮且极具亲和力的导航菜单设计国外网站推荐
2011/09/20 Javascript
一个简单的实现下拉框多选的插件可移植性比较好
2014/05/05 Javascript
jquery遍历函数siblings()用法实例
2015/12/24 Javascript
JavaScript 数组- Array的方法总结(推荐)
2016/07/21 Javascript
清除浏览器缓存的几种方法总结(必看)
2016/12/09 Javascript
BootStrap组件之进度条的基本用法
2017/01/19 Javascript
BootStrap selectpicker后台动态绑定数据的方法
2017/07/28 Javascript
如何开发出更好的JavaScript模块
2017/12/22 Javascript
JS与CSS3实现图片响应鼠标移动放大效果示例
2018/05/04 Javascript
微信小程序网络请求封装示例
2018/07/24 Javascript
webpack之引入图片的实现及问题
2018/10/08 Javascript
vue实现抽屉弹窗效果
2020/11/15 Javascript
[01:35]辉夜杯战队访谈宣传片—LGD
2015/12/25 DOTA
详解Python3中字符串中的数字提取方法
2017/01/14 Python
python实现图书管理系统
2018/03/12 Python
Pycharm+Scrapy安装并且初始化项目的方法
2019/01/15 Python
python实战串口助手_解决8串口多个发送的问题
2019/06/12 Python
python中tkinter的应用:修改字体的实例讲解
2019/07/17 Python
python函数修饰符@的使用方法解析
2019/09/02 Python
Python-Flask:动态创建表的示例详解
2019/11/22 Python
django之导入并执行自定义的函数模块图解
2020/04/01 Python
基于Python实现下载网易音乐代码实例
2020/08/10 Python
HTML5不支持frameset的两种解决方法
2016/11/14 HTML / CSS
YOINS官网:时尚女装网上购物
2017/03/17 全球购物
超市中秋节促销方案
2014/03/21 职场文书
黑暗中的舞者观后感
2015/06/18 职场文书
《女娲补天》教学反思
2016/02/20 职场文书
行政后勤人员工作计划应该怎么写?
2019/08/16 职场文书