1.缓存淘汰机制
1.1 FIFO(First In First Out)
数据结构: 队列
先进先出。这种算法认为最早进入缓存的数据也是最早应该被淘汰的。它像一个队列一样工作,新数据项被添加到队列的一端,而当需要移除数据项时,从另一端开始移除最老的数据项。
优点是实现简单,缺点就是我们使用频率很高的数据,也会被移除,导致这个热点数据频繁的被添加又被淘汰,导致命中率降低。
1.2 LFU(Least Frequently Used)
数据结构: 哈希表 + 最小堆 或者 计数器数组
最少使用,也就是淘汰缓存中访问频率最低的记录。LFU 认为,如果数据过去被访问多次,那么将来被访问的频率也更高。
LFU 的实现就是维护一个按照访问次数排序的队列,每次访问的时候,访问次数加1,然后将队列重新排序,淘汰时选择访问次数最少的。
LFU 算法的命中率是比较高的,但缺点也非常明显,维护每个记录的访问次数,对内存的消耗是很高的;还有就是,如果有一个数据历史上访问次数特别高,但是在后来很少被访问,又因为它的历史访问次数很高,导致迟迟不能被淘汰,就一直占用我们的内存资源。
1.3 LRU(Least Recently Used)
数据结构: 双向链表 + 哈希表
最近最少使用,相对于仅考虑时间因素的 FIFO 和仅考虑访问频率的 LFU,LRU 算法可以认为是相对平衡的一种淘汰算法。
LRU 认为,如果数据最近被访问过,那么将来被访问的概率也会更高。所以他会优先淘汰长时间未被访问的数据。
LRU 算法的实现,使用双向链表和哈希表来记录数据的使用情况。每次访问一个数据项时,将其移到链表的前端;当需要淘汰数据项时,则从链表尾部开始移除。
优点就是他是一种相对平衡的淘汰算法,但是维护双向链表和哈希表增加了一定的开销,实现起来也比较复杂。
区别:
●替换策略:FIFO依据进入时间,LRU依据最后访问时间,LFU依据访问频率。
●实现复杂度:FIFO < LRU < LFU,其中LFU最为复杂,尤其是在处理频率相同或需要动态调整频率的情况下。
●性能表现:通常情况下,LRU优于FIFO,而LFU在特定场景下可能优于LRU,但其实现成本更高。
2.分布式缓存,线性缓存。线性哈希跟一致性哈希的区别,一致性哈希的哈希环倾斜的问题怎么办
传统哈希:在分布式系统中假设有n个节点,使用key%n来进行数据和节点之间的映射关系。一旦增加或删除一个节点,映射关系就变为了key%(n+或-1),绝大多数的映射关系都会失效。如果是在缓存场景里,就会出现缓存雪崩。
一致性哈希:将key值映射到2^32的空间里,这个空间是个环状的结构,我们计算节点的哈希值以后把它放在环上,然后顺时针找到的第一个节点就是它应选取的节点。如果说新增一个机器,那么他只会影响部分节点的映射关系,其余的映射关系不会改变。也就是说在新增或者删除节点时,只需要重新定位该节点附近的一小部分数据,不需要重新定位所有的节点,就能避免传统哈希带来的问题。
哈希环倾斜问题:如果说节点过少,导致他的节点分布在环的上半部分,而下半部分是空的。那么映射在下半部分的节点就会向上半节点的头节点倾斜,导致负载不均衡。这就会导致出现哈希环倾斜的问题。
解决办法:引入了虚拟节点,一个真实节点对应多个虚拟节点。这样就能增加节点的数量,解决了节点少导致的倾斜问题。
评论