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与Mysql的交互示例代码
Aug 18 NodeJs
轻松创建nodejs服务器(3):代码模块化
Dec 18 NodeJs
NodeJS学习笔记之FS文件模块
Jan 13 NodeJs
nodejs中实现sleep功能实例
Mar 24 NodeJs
NodeJS创建基础应用并应用模板引擎
Apr 12 NodeJs
在windows上用nodejs搭建静态文件服务器的简单方法
Aug 11 NodeJs
nodejs连接mongodb数据库实现增删改查
Dec 01 NodeJs
NodeJS实现自定义流的方法
Aug 01 NodeJs
NodeJS搭建HTTP服务器的实现步骤
Oct 12 NodeJs
NodeJS 将文件夹按照存放路径变成一个对应的JSON的方法
Oct 17 NodeJs
nodejs一个简单的文件服务器的创建方法
Sep 13 NodeJs
NodeJS开发人员常见五个错误理解
Oct 14 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将数据导入到Foxmail
2006/10/09 PHP
php session 预定义数组
2009/03/16 PHP
PHP使用SOAP调用.net的WebService数据
2013/11/12 PHP
Thinkphp中Create方法深入探究
2014/06/16 PHP
完善CodeIgniter在IDE中代码提示功能的方法
2014/07/19 PHP
php实现四舍五入的方法小结
2015/03/03 PHP
PHP之预定义接口详解
2015/07/29 PHP
详解php的socket通信
2015/08/11 PHP
php基础设计模式大全(注册树模式、工厂模式、单列模式)
2015/08/31 PHP
PHP简单获取及判断提交来源的方法
2016/04/22 PHP
利用PHP_XLSXWriter代替PHPExcel的方法示例
2017/07/16 PHP
PHP解析url并得到url参数方法总结
2018/10/11 PHP
json 实例详细说明教程
2009/10/31 Javascript
javascript 广告后加载,加载完页面再加载广告
2010/11/25 Javascript
一个简单的全屏图片上下打开显示网页效果示例
2014/07/08 Javascript
JavaScript使用setTimeout实现延迟弹出警告框的方法
2015/04/07 Javascript
javascript中JSON对象与JSON字符串相互转换实例
2015/07/11 Javascript
javascript文件加载管理简单实现方法
2015/07/25 Javascript
开启Javascript中apply、call、bind的用法之旅模式
2015/10/28 Javascript
基于JavaScript实现自动更新倒计时效果
2016/12/19 Javascript
js 调用百度分享功能
2017/02/27 Javascript
JavaScript仿微信打飞机游戏
2020/07/05 Javascript
Vue render渲染时间戳转时间,时间转时间戳及渲染进度条效果
2018/07/27 Javascript
layer弹出层取消遮罩的方法
2019/09/25 Javascript
python抓取豆瓣图片并自动保存示例学习
2014/01/10 Python
Django处理文件上传File Uploads的实例
2018/05/28 Python
在Python中获取两数相除的商和余数方法
2018/11/10 Python
python批量获取html内body内容的实例
2019/01/02 Python
详解Python中pyautogui库的最全使用方法
2020/04/01 Python
python torch.utils.data.DataLoader使用方法
2020/04/02 Python
X/HTML5 和 XHTML2
2008/10/17 HTML / CSS
HTML5和CSS3实例教程总结(推荐)
2016/07/18 HTML / CSS
马德里运动鞋商店:Nigra Mercato
2020/02/16 全球购物
解释i节点在文件系统中的作用
2013/11/26 面试题
董事长秘书工作职责
2014/06/10 职场文书
详解SpringBoot异常处理流程及原理
2021/06/21 Java/Android