汕头做网站优化的公司织梦源码模板下载商城网站模板 整站带栏目高端大气上档次含数据
汕头做网站优化的公司,织梦源码模板下载商城网站模板 整站带栏目高端大气上档次含数据,saas建站和开源建站的区别,做非法集资资讯的网站缓存淘汰机制LRU和LFU的区别
在高并发#xff0c;高访问量的电商平台中#xff0c;缓存是提升性能的的保障用户体验的关键#xff1b;然而#xff0c;受限于物理内存#xff0c;缓存空间总是有限的#xff1b;因此必须采用合适的淘汰#xff08;替换#xff09;策略高访问量的电商平台中缓存是提升性能的的保障用户体验的关键然而受限于物理内存缓存空间总是有限的因此必须采用合适的淘汰替换策略保证最有价值的数据能长时间驻留缓存。LRU与LFU的基本原理LRU最少最近使用思路优先淘汰最近一段时间最久没有被访问的数据实现常用哈希表双向链表每当访问或者新增数据即把该数据节点移到链表头部淘汰是直接移除链表尾部优点实现简单适应访问热点快速变换的场景。当我们连续插入DBCA时此时内存以及满了那么当我们再插入一个M的时候此时内存存放最久的数据D淘汰掉当我们从外部读取数据M的时候此时M就会提到头部这时候M就是最晚被淘汰掉的。LFU最不经常使用思路优先淘汰一段时间内访问次数频率最低的数据实现需要维护每个数据节点的访问频率多用哈希表加频率链表组合。淘汰最低频率中的最旧节点。优点能够更好保持长期高频访问的数据适合长期热门但访问分布分散的场景。当我们插入ABC之后其会以CBA的形式存储于双向链表中当我们再插入ABDE后BA会到频率为2处ED会到频率为1处当再次插入AMD之后内存会满如果此时我们再插入一个Q会先淘汰频率为1处最先插入的C。实现方法和复杂性LRULFU原理淘汰最久未被访问的数据淘汰访问次数最少的数据复杂度O1O1合理实现时优点实现简单时间开销小保护长期高频数据减少冷数据回流缺点容易误杀最近高配数据实现较复杂突发热点响应慢电商场景下如何选择电商常见的数据访问模式秒杀大促首页推荐短时间部分商品或页面极度火爆热点变换块长期商品个性化推荐部分数据长期有较低频率访问。选择建议若面向热点商品突变频繁场景如秒杀活动页–优先选择LRU。因为持续被访问的热点商品会留在缓存前端发生访问突变事能够快速适用变化防止缓存穿透若需要保护常青商品或内容库如个性化长期售卖页面–可选择LFU。能够留存虽然访问不集中的长期高配数据防止配LRU “误杀”实际项目中采用分区或者多级缓存针对不如业务分别设计缓存策略如活动页LRU推荐页LFU。结论LRU和LFU的根本区别一个重新近性一个重访问频率电商访问模式以热点突变为主推荐优先使用LRU缓存机制综合业务需求时可以混合使用LRU/LFU或者采用2QLRU-K等改进型算法结合流量特征和数据重要性灵活选型。代码实现LRU缓存基于双向链表哈希表/** * LRU缓存基于双向链表哈希表 */publicclassLRUK,V{privatefinalintcapacity;privatefinalMapK,NodeK,Vmap;privatefinalNodeK,Vhead,tail;staticclassNodeK,V{Kkey;Vvalue;NodeK,Vprev,next;Node(){}Node(Kkey,Vvalue){this.keykey;this.valuevalue;}}publicLRU(intcapacity){this.capacitycapacity;this.mapnewHashMap();headnewNode();tailnewNode();head.nexttail;tail.prevhead;}publicVget(Kkey){NodeK,Vnodemap.get(key);if(nodenull){returnnull;}moveToHead(node);returnnode.value;}publicvoidput(Kkey,Vvalue){NodeK,Vnodemap.get(key);if(nodenull){nodenewNode(key,value);map.put(key,node);addToHead(node);if(map.size()capacity){NodeK,VtailremoveTail();map.remove(tail.key);}else{node.valuevalue;addToHead(node);}}}/** * 添加节点 * param node */privatevoidaddToHead(NodeK,Vnode){node.prevhead;node.nexthead.next;head.next.prevnode;head.nextnode;}/** * 删除节点 * param node */privatevoidremoveNode(NodeK,Vnode){node.prev.nextnode.next;node.next.prevnode.prev;}/** * 移动节点到头部 * param node */privatevoidmoveToHead(NodeK,Vnode){node.prev.nextnode.next;node.next.prevnode.prev;addToHead(node);}/** * 删除尾部节点 * return */privateNodeK,VremoveTail(){NodeK,Vnodetail.prev;node.prev.nexttail;tail.prevnode.prev;returnnode;}}LFU缓存基于HashMap频率链表/** * LFU缓存基于HashMap频率链表 */publicclassLFUK,V{privateintcapacity;privateintminFreq;privatefinalMapK,NodeK,VnodeMap;privatefinalMapInteger,LinkedHashSetNodeK,VfreqMap;staticclassNodeK,V{Kkey;Vvalue;intfreq;Node(Kkey,Vvalue){this.keykey;this.valuevalue;this.freq1;}}publicLFU(intcapacity){this.capacitycapacity;this.minFreq0;this.nodeMapnewHashMap();this.freqMapnewHashMap();}publicVget(Kkey){NodeK,VnodenodeMap.get(key);if(nodenull)returnnull;increaseFreq(node);returnnode.value;}publicvoidput(Kkey,Vvalue){if(capacity0)return;if(nodeMap.containsKey(key)){NodeK,VnodenodeMap.get(key);node.valuevalue;increaseFreq(node);return;}if(nodeMap.size()capacity){// 淘汰访问频率最低且最久的节点LinkedHashSetNodeK,VsetfreqMap.get(minFreq);NodeK,VtoRemoveset.iterator().next();set.remove(toRemove);nodeMap.remove(toRemove.key);}NodeK,VnewNodenewNode(key,value);nodeMap.put(key,newNode);freqMap.computeIfAbsent(1,k-newLinkedHashSet()).add(newNode);minFreq1;}privatevoidincreaseFreq(NodeK,Vnode){intfreqnode.freq;LinkedHashSetNodeK,VsetfreqMap.get(freq);set.remove(node);if(freqminFreqset.isEmpty()){minFreq;}node.freq;freqMap.computeIfAbsent(node.freq,k-newLinkedHashSet()).add(node);}}测试案例publicclassCacheTest{publicstaticvoidmain(String[]args){// 测试LRU缓存LRUInteger,StringlruCachenewLRU(2);lruCache.put(1,A);lruCache.put(2,B);System.out.println(lruCache.get(1));// 输出: AlruCache.put(3,C);System.out.println(lruCache.get(2));// 输出: null (2被淘汰)// 测试LFU缓存LFUInteger,StringlfuCachenewLFU(2);lfuCache.put(1,A);lfuCache.put(2,B);System.out.println(lfuCache.get(1));// 输出: AlfuCache.put(3,C);System.out.println(lfuCache.get(2));// 输出: null (2被淘汰因1 频率高)}}