面试题答案
一键面试思路一:在写入缓存时设置 TTL
- 原理:当向缓存中写入数据时,同时设置该数据的 TTL。缓存系统会在内部维护一个数据结构,记录每个数据项的过期时间。在每次读取数据时,先检查数据是否过期,如果过期则从缓存中删除,并返回空值或重新从数据源获取数据。
- 示例:在 Redis 中,可以使用
SET key value EX seconds
命令来设置键值对并指定过期时间(以秒为单位)。例如:
SET user:1 "John Doe" EX 3600 # 设置键 user:1 的值为 "John Doe",并在 3600 秒(1 小时)后过期
当执行 GET user:1
时,Redis 会检查该键是否过期,如果未过期则返回值;若已过期,返回空值,应用程序可以据此从数据库等数据源重新获取数据并更新缓存。
思路二:定期扫描缓存
- 原理:启动一个后台线程或定时任务,定期扫描缓存中的所有数据项,检查它们的过期时间。对于已过期的数据,从缓存中删除。这种方式不需要在每次读取数据时都检查过期时间,但可能会导致缓存中有少量过期数据在扫描周期内仍然存在。
- 示例:假设使用一个简单的 Python 字典模拟缓存,并使用
threading.Timer
来实现定期扫描。
import threading
import time
cache = {}
def set_cache(key, value, ttl):
cache[key] = (value, time.time() + ttl)
def get_cache(key):
if key in cache:
value, expire_time = cache[key]
if time.time() < expire_time:
return value
else:
del cache[key]
return None
def clean_cache():
while True:
current_time = time.time()
keys_to_delete = []
for key, (_, expire_time) in cache.items():
if current_time > expire_time:
keys_to_delete.append(key)
for key in keys_to_delete:
del cache[key]
time.sleep(60) # 每 60 秒扫描一次
# 启动清理线程
clean_thread = threading.Thread(target=clean_cache)
clean_thread.daemon = True
clean_thread.start()
# 设置缓存示例
set_cache('test_key', 'test_value', 30) # 设置一个 30 秒过期的缓存