解决缓存问题无Redis可行方案(不用redis怎么做缓存)
Web应用中,最常用的缓存方案就是使用Redis,但是有时候Redis可能不太合适,例如部署成本太高、代码写起来很麻烦等等。对于这些问题,还有另外几种方式可以解决缓存问题。
两级缓存是一种常用的解决缓存问题的方式,其两个层次分别是本地缓存和远程缓存,针对定时任务可以使用该方案。一级缓存可以为本地散列,二级缓存可以为远程数据库,引擎可以按照一致性原则进行触发,有利于性能提升,而散列的优势更显著,因此可以采用散列的方式存储本地数据,具体代码如下:
// 一级缓存:本地散列
var hashTable = {};
// 二级缓存:远程数据库var remoteDB = {};
// 判断一级缓存里是否存在,如果存在则从缓存中获取function get(key) {
if (hashTable[key] !== undefined) { return hashTable[key];
} // 一级缓存不存在,则从二级缓存中获取
else { var val = remoteDB.get(key);
if (val !== undefined) { // 二级缓存存在,则将值保存到一级缓存里
hashTable[key] = val; }
return val; }
}
另一种解决缓存问题的方案是LRU( Least Recently Used)策略,即最近最少使用策略,在处理缓存淘汰时,先去掉最近最少使用的。LRU策略也可以称为近期最少使用( RecentlyLeast Used)算法,也是一种最常用的缓存淘汰算法。具体实现也很简单,可以使用双向链表来维护缓存,分别按照顺序存放最近使用的元素到头部,最久使用的元素到尾部,当有缓存放入,则会放在头部,当缓存放满,则替换掉尾部的数据,具体实现如下:
// 使用双向链表维护缓存
class DLinkedNode { constructor(key = null, value = null) {
this.key = key; this.value = value;
this.pre = null; this.next = null;
}}
class LRUCache { constructor(capacity) {
this.capacity = capacity; this.map = {};
this.head = new DLinkedNode(); this.tl = new DLinkedNode();
this.head.next = this.tl; this.tl.pre = this.head;
}
get(key) { let node = this.map[key];
// 不存在 if (!node) {
return -1; }
// 把节点放在头部 this._moveToHead(node);
return node.value; }
put(key, value) {
let node = this.map[key]; // 添加
if (!node) { let newNode = new DLinkedNode(key, value);
this.map[key] = newNode; this._addToHead(newNode);
this.capacity--; // 删除最后一个
if (this.capacity this._removeTl();
} }
// 更新 else {
node.value = value; this._moveToHead(node);
} }
_removeTl() {
let tlNode = this.tl.pre; this._removeNode(tlNode);
delete this.map[tlNode.key]; this.capacity++;
}
_removeNode(node) { let preNode = node.pre;
let nextNode = node.next; preNode.next = nextNode;
nextNode.pre = preNode; }
_addToHead(node) {
let preHead = this.head; let afterHead = preHead.next;
preHead.next = node; afterHead.pre = node;
node.next = afterHead; node.pre = preHead;
}
_moveToHead(node) { this._removeNode(node);
this._addToHead(node); }
}
以上两种方法无需使用Redis就可以实现缓存,能够解决部署成本高等问题,因此在不能使用Redis的情况下,也可以考虑采用以上方案。