本文大致上是基于 caching-in-python 这篇文章的翻译
缓存操作主要有两种类型。缓存如浏览器缓存,服务器缓存,代理缓存,硬件缓存工作原理的读写缓存。当处理缓存时,我们总是有大量的内存需要花费大量的时间来读写数据库、硬盘。 缓存则能帮我们加快这些任务。
每次客户端向存储请求数据时,请求都会先去访问与存储相关联的缓存。
顾名思义,写缓存支持快速写操作。设想一个写入量很大的系统,我们都知道向 DB 写入代价很高。而缓存很方便,可以处理 DB 写加载,这些加载稍后会批量更新到 DB。需要注意的是,DB 和缓存之间的数据应该始终保持同步。有3种方法可以实现写缓存。
客户端先写缓存,缓存再写到 DB ,DB 返回结果给客户端。对缓存要求强一致性可以用这种方式。
客户端先写到 DB ,DB 直接返回结果给客户端。之后 DB 定时将数据同步到缓存,下一次客户端读数据时先请求缓存。
客户端直接将数据写入 DB,只有在读数据的时候,才从 DB 中加载数据到缓存。
缓存使读写速度更快。那么,只有从缓存中读取和写入所有数据才有意义,而不是使用 DB。但是,只是因为缓存很小所以速度快。缓存越大,搜索时间越长。
所以我们对空间进行优化是很重要的。一旦缓存满了,我们只能通过删除已经在缓存中的数据来为新数据腾出空间。同样,这不能是一个猜谜游戏,我们需要最大化的利用率来优化输出。
以下有几种缓存回收策略:
顾名思义,当缓存空间不足时,删除最近使用最少的元素。它简单易于实现,听起来很公平,但是对于缓存使用频率来说,比上次访问时有更大的权重,这就引出了下一个算法。
LFU 同时考虑数据的年龄和频率。但是这里的问题是经常使用的数据会长时间滞留在缓存中
究竟为什么有人在讨论了使用频率之后还要使用 MRU 算法呢?我们不是总是重读刚读过的数据吗?不一定。想象图片库应用程序,相册的图片缓存和加载时,你向右滑动。回到上一张照片怎么样?是的,这种情况发生的可能性要小一些。
当缓存开始像队列一样工作时,您将拥有一个 FIFO 缓存。这非常适合涉及顺序读取和处理数据管道的情况。
缓存基本上是一个散列表。每个数据进入它是散列和存储使它可以访问在 o(1)。
现在我们如何剔除最近使用次数最少的项目,到目前为止我们只有一个散列函数和它的数据。我们需要以某种方式存储访问顺序。
我们可以使用一个数组,当元素被访问时,我们在这个数组中输入元素。但是在这种方法中元素入栈出栈的时间复杂度将会大大增加。
双向链表可能符合这个目的。每次访问链接列表时添加一个项,并维护它作为哈希表中的引用,使我们访问他的时间复杂度为O(1)。
使用一个双端队列实现 LRU 机制,真实的数据存在一个字典当中。
from collections import deque
from typing import Any
class LRUCache:
def __init__(self, cache_size: int):
"""
:param cache_size: LRU 队列的大小,超过当前大小时,最近最不常使用的元素将过期
"""
self.cache_size = cache_size
self.queue = deque()
self.hash_map = dict()
def is_queue_full(self):
return len(self.queue) == self.cache_size
def set(self, key: str, value: Any):
if key not in self.hash_map:
if self.is_queue_full():
pop_key = self.queue.pop()
self.hash_map.pop(pop_key)
self.queue.appendleft(key)
self.hash_map[key] = value
else:
self.queue.appendleft(key)
self.hash_map[key] = value
def get(self, key: str):
if key not in self.hash_map:
return -1
else:
self.queue.remove(key)
self.queue.appendleft(key)
return self.hash_map[key]
functools
中的lru_cache
from flask import jsonify
from functools import lru_cache
@app.route(“/user/<uid>“)
@lru_cache()
def get_user(uid):
try:
return jsonify(read_user(db, uid))
except KeyError as e:
return jsonify({"Status": "Error", "message": str(e)})
本文系外文翻译,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文系外文翻译,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。