46 | 缓存系统:如何通过哈希表和队列实现高效访问?
该思维导图由 AI 生成,仅供参考
什么是缓存系统?
- 深入了解
- 翻译
- 解释
- 总结
缓存系统在计算机领域扮演着重要角色,通过高效的访问方式提升系统速度。本文介绍了缓存系统的概念和设计考量因素。首先,缓存被定义为数据交换的缓冲区,其读取速度远高于普通存储介质,能够帮助系统更快地运行。硬件性能、命中率和更新周期是缓存设计的主要考量因素。命中率的提升可以通过缓存淘汰算法实现,如LFU和LRU策略。另外,及时更新数据对于变化速度快的数据至关重要,以避免用户读取到过时内容。通过深入了解这些因素之间的关系,读者可以更好地理解缓存系统的工作流程和重要性。 在设计缓存系统时,哈希表和队列是关键的数据结构。哈希表能够快速存储和更新被缓存的内容,而队列则负责管理最近被访问的状态,并告知系统哪些数据需要被淘汰并从哈希表中移除。通过结合哈希表和队列,可以实现基于LRU淘汰策略的缓存设计方案。这种设计思想能够帮助读者快速了解如何利用哈希表和队列来设计高效的缓存系统,提升系统性能。 总的来说,缓存在计算机系统中扮演着重要角色,而基于哈希表和队列的设计思想能够帮助实现高效的缓存系统,提升系统性能。读者可以通过本文了解到缓存系统的重要性以及如何利用哈希表和队列来设计缓存系统,从而加深对缓存系统工作原理的理解。
《程序员的数学基础课》,新⼈⾸单¥68
全部留言(11)
- 最新
- 精选
- 铁丑-王立丰查找数据是否在队列这个成本也不小啊
作者回复: 这是个好问题,正常的情况下,我们假设哈希表和队列里的数据一致,除非发生了异常。 如果是这样,我们可以利用链表来实现队列,然后使用哈希表存储每个被缓存结果所对应的队列结点,这样我们可以快速访问队列的结点,并使用链表结点的移动来实现队列内结点的移动。
2019-04-036 - 铁丑-王立丰嗯嗯,我下午也在想,这个队列应该是一个双向链表,而且新加的哈希表可能还要解决队列节点的冲突问题。设计的再复杂一点这个结构应该能够和原有的那张缓存哈希表融合。这样还能节省内存。
作者回复: 融合的概念很新颖,代码可读性会弱一点,但是效率很高👍
2019-04-045 - 小灰老师请教一下,(1+7+5)/10^6=13 这个是怎么计算的
作者回复: 由于排版的关系,应该是(1+7+5)%10^6,其中10^6表示10的6次方,计算优先级最高,所以是13%1000000,而%表示求余,求余为13
2021-10-281 - qinggeouye# collections 的 OrderedDict() class LRUCache: def __init__(self, capacity): self.capacity = capacity self.queue = collections.OrderedDict() def get(self, key): if key not in self.queue: return -1 # 要找的数据不在缓存中则返回 -1 value = self.queue.pop(key) # 将命中缓存的数据移除 self.queue[key] = value # 将命中缓存的数据重新添加到头部 return self.queue[key] def put(self, key, value): if key in self.queue: # 如果已经存在缓存中,则先移除老的数据 self.queue.pop(key) elif len(self.queue.items()) == self.capacity: self.queue.popitem(last=False) # 如果不存在缓存并且达到最大容量 则把最后的数据淘汰 self.queue[key] = value # 将新数据添加到头部
作者回复: 这部分实现主要侧重于queue实现LRU策略,依赖于Python queue的查找机制,如果Python的queue也有类似哈希表的查询效率,那么也是一种更简洁的实现方式。
2019-04-091 - 失火的夏天class LRUCache { private Node head;// 最近最少使用,类似列队的头,出队 private Node tail;// 最近最多使用,类似队列的尾,入队 private Map<Integer,Node> cache; private int capacity; public LRUCache(int capacity) { this.cache = new HashMap<>(); this.capacity = capacity; } public int get(int key) { Node node = cache.get(key); if(node == null){ return -1; }else{ moveNode(node); return node.value; } } public void put(int key, int value) { Node node = cache.get(key); if (node != null){ node.value = value; moveNode(node); }else { removeHead(); node = new Node(key,value); addNode(node); } cache.put(key,node); } private void removeHead(){ if (cache.size() == capacity){ Node tempNode = head; cache.remove(head.key); head = head.next; tempNode.next = null; if (head != null){ head.prev = null; } } } /** * 链表加入节点 * @param node */ private void addNode(Node node){ if (head == null){ head = node; tail = node; }else { addNodeToTail(node); } } private void addNodeToTail(Node node){ node.prev = tail; tail.next = node; tail = node; } private void moveNode(Node node){ if(head == node && node != tail){ head = node.next; head.prev = null; node.next = null; addNodeToTail(node); }else if (tail == node){ // 不做任何操作 }else { // 普遍情况,node节点移除链表,加入到尾节点后面,tail指针指向node node.prev.next = node.next; node.next.prev = node.prev; node.next = null; addNodeToTail(node); } } }
作者回复: 实现的很仔细👍
2019-04-011 - 失火的夏天因为篇幅不够,分段截出来了,这里先声明一个内部类,表示为队列(链表)的节点,接下来的Node节点是这个内部类 private class Node{ private Node prev; private Node next; private int key; private int value; Node(int key,int value){ this.key = key; this.value = value; } }2019-04-013
- Paul Shan缓存意味着数据源有两个,而且这两个数据源访问成本和数据完备度不同。访问成本低的数据不完备,数据完备的访问成本高。要结合这两个数据源来设计访问成本尽可能低,同时数据又是完备的系统。基于队列和哈希表实现的LRU算法是经典算法之一。队列维护缓存大小,满的时候淘汰最近没用到的数据。哈希表提升查询效率。每次访问,先查哈希表,如果数据存在,将该数据放到队列尾部,让其远离被淘汰的位置,然后返回数据。如果数据不存在,就从完备的数据源中取得数据,将数据放入队列,如果队列已满,则淘汰掉最近最少用的数据,然后得到最新返回的数据。队列要面临频繁的插入和改位置操作,选用基于双向链表的队列较为高效。2019-10-142
- 013923使用哈希表和队列可以实现高效访问;2022-09-23归属地:上海1
- 013923Cache 是计算机OS的基本元件2022-09-15归属地:上海1
- 013923学习了Cache缓存系统;计算机基础课程2022-09-15归属地:上海1