TTL、纠错、遗忘与隐私
正在读取学习记录…
保存记忆以后,还需要决定何时更正、何时停止使用、怎样删除。TTL是存活时间,例如一条临时偏好保存10分钟,超过这个时长便失效。纠错把错误记录替换成新版本;遗忘移除以后不再使用的信息;隐私管理决定哪些内容可以保存、谁能读取以及用户怎样要求删除。
像更新通讯录:新号码替换旧号码,临时通行信息到期作废,客户要求删除时还要清理留在快捷查询里的副本。只删主记录,缓存仍可能读到旧内容。
观察一条偏好怎样失效与更正
固定时间用整数表示,便于精确观察边界。u1的中文偏好在时刻0写入、版本为v1、存期10,到时刻10失效。随后在时刻20重新写入中文,版本递增为v2;时刻22纠正为英文v3,确认缓存跟随更新。最后执行用户删除,当前记录和缓存一并移除。
缓存是为了快速读取保存的副本。版本让副本能够识别更新;删除版本继续保留递增的编号,避免同一键重新写入时撞上旧缓存编号。
跟着固定样本运行
先在 PowerShell 创建并进入学习目录:
mkdir "F:\学习\l5-forgetting" -Force
cd "F:\学习\l5-forgetting"保存下面的文件后,在这个终端运行 dir 核对文件名,再执行本节给出的运行命令。
新建 F:\学习\l5-forgetting,将下面完整代码保存为 forgetting_demo.py。
先在 PowerShell 创建并进入学习目录:
mkdir "F:\学习\l5-forgetting" -Force
cd "F:\学习\l5-forgetting"保存下面的文件后,在这个终端运行 dir 核对文件名,再执行本节给出的运行命令。
"""检查到期、纠错版本与用户删除后的缓存状态。"""
from dataclasses import dataclass
@dataclass(frozen=True)
class Entry:
value: str
version: int
expires_at: int
class MemoryStore:
def __init__(self):
self.rows = {}
self.versions = {}
self.cache = {}
def put(self, user, value, now, ttl):
if ttl <= 0:
raise ValueError("存期必须为正")
# 版本号独立于当前记录保存,删除后重建也继续递增。
version = self.versions.get(user, 0) + 1
self.versions[user] = version
self.rows[user] = Entry(value, version, now + ttl)
self.cache.pop(user, None)
return version
def get(self, user, now):
row = self.rows.get(user)
if row is None:
return None
if now >= row.expires_at:
self.delete(user)
return None
# 缓存带版本,读取前和当前记录核对。
cached = self.cache.get(user)
if cached is None or cached.version != row.version:
self.cache[user] = row
return self.cache[user].value
def delete(self, user):
# 主记录与快捷读取副本同时删除;这里只保留无内容的版本计数。
self.rows.pop(user, None)
self.cache.pop(user, None)
if __name__ == "__main__":
store = MemoryStore()
store.put("u1", "中文", now=0, ttl=10)
print("到期前:" + str(store.get("u1", 9)))
print("到期时:" + str(store.get("u1", 10)))
first = store.put("u1", "中文", now=20, ttl=10)
store.get("u1", 21)
updated = store.put("u1", "英文", now=22, ttl=10)
print(f"纠错:v{first} → v{updated},读取={store.get('u1', 23)}")
store.delete("u1")
print(f"用户删除:读取={store.get('u1', 24)},缓存条数={len(store.cache)}")在 PowerShell 中进入保存目录并运行:
cd "F:\学习\l5-forgetting"
ls
python -X utf8 forgetting_demo.py输出为:
到期前:中文
到期时:None
纠错:v2 → v3,读取=英文
用户删除:读取=None,缓存条数=0时刻9还能读取中文,时刻10返回None,并清理已到期的记录和缓存。再次写入得到v2,因为最早那次写入已经使用v1;更正英文得到v3。编号没有随删除归零。
最后一行显示读取为空、缓存条数为0。当前程序在读取时检查到期,只有被访问的过期记录才会立即清理;没有访问的条目还留在字典里,直到执行清理或删除。
失效与真正移除怎样配合
存期决定何时不再给调用方返回记录。程序可在每次读取时检查失效,也可以用定时清理移除无人访问的过期条目。大型存储常将两者配合:读取及时阻断,后台回收空间。保留时间应根据用途选择,短期会话状态和稳定偏好不必使用相同时长。
纠错时增加版本并清缓存,使下一次读取取得新值。分布式缓存可能在多个服务节点保留副本,需要广播失效、版本核对或短存期策略。数据库中的旧版本、搜索索引、摘要与向量索引也属于可能残留的副本。
用户要求删除时,沿哪些位置找
先按身份确认要删除的记录,再移除主存储、缓存和相关索引;如果保留历史修订,也需要处理对应历史内容。日志中尽量保存操作编号与结果,避免再次记录被删除的原文。备份和审计材料有不同保留策略,需要向用户说明实际覆盖范围和恢复限制。
示例删除的是进程里的记录与缓存,并留下无偏好内容的版本计数。正式系统的用户级彻底删除还应处理这个关联标识,以及外部存储、备份与日志。TTL清理提供时间控制,删除请求提供用户控制,两者可以同时存在。
将存期从10改成20
只把主程序第一次写入的 ttl=10 改为 ttl=20,运行 python -X utf8 forgetting_demo.py。“到期时”一行会显示中文,因为时刻10还没到新期限。该标签描述的是原来的观察点;改成“时刻10”更适合保留这个对照。后续纠错和用户删除仍按原步骤执行。恢复存期10和原标签后重跑,时刻10再次读到None。
| 现象 | 检查位置 |
|---|---|
| 刚到期限仍能读到值 | 是否使用now大于等于失效时刻 |
| 更正后仍显示旧偏好 | 缓存版本与失效通知 |
| 删除后又读到内容 | 索引、缓存、历史版本和备份 |
| 无人读取的过期数据堆积 | 后台清理任务 |
检查实现中的六种情况
在同一目录将下面测试保存为 test_forgetting_demo.py。测试覆盖正文中的正常路径与边界条件。
测试代码:test_forgetting_demo.py
"""检查存期边界、更新、删除与重新写入。"""
import unittest
from forgetting_demo import MemoryStore
class ForgettingTests(unittest.TestCase):
def setUp(self):
self.store = MemoryStore()
self.store.put("u1", "中文", 0, 10)
def test_before_expiry(self):
self.assertEqual(self.store.get("u1", 9), "中文")
def test_expiry_boundary(self):
self.store.get("u1", 9)
self.assertIsNone(self.store.get("u1", 10))
self.assertNotIn("u1", self.store.cache)
def test_correction_invalidates_cache(self):
self.store.get("u1", 1)
self.assertEqual(self.store.put("u1", "英文", 2, 10), 2)
self.assertEqual(self.store.get("u1", 3), "英文")
def test_delete_clears_cache(self):
self.store.get("u1", 1)
self.store.delete("u1")
self.assertNotIn("u1", self.store.rows)
self.assertNotIn("u1", self.store.cache)
def test_recreate_keeps_increasing_version(self):
self.store.delete("u1")
self.assertEqual(self.store.put("u1", "英文", 2, 10), 2)
def test_user_isolation_and_ttl_validation(self):
self.assertIsNone(self.store.get("u2", 1))
with self.assertRaises(ValueError):
self.store.put("u1", "中文", 2, 0)
if __name__ == "__main__":
unittest.main()cd "F:\学习\l5-forgetting"
python -X utf8 -m unittest -v test_forgetting_demo应显示6项通过。将主程序恢复到上面的固定输入后,可以再次对照完整输出。
课后练习展开习题收起习题
正在读取本地记录…
不调用模型,不执行代码。简答、代码和场景题仅保存答案并展示自查标准,不生成评分、徽章或认证。输入内容不会自动保存,请点击提交;不要填写个人信息或密钥。
选择题 · 先判断边界
关于“TTL、纠错、遗忘与隐私”,哪种做法更稳妥?
对应知识点:L5-forgetting
简答题 · 解释失败
写出一个失败输入并说明记录字段。
对应知识点:L5-forgetting
代码题 · 边界测试
补充正常、边界、失败三组输入和预期结果。
对应知识点:L5-forgetting
场景题 · 结果未知
证据不足时如何设计状态和人工接管?
对应知识点:L5-forgetting
描述会发送给本站维护者,用于修订文章,保存90天。请只填写文章问题,省略个人信息、密钥和内部资料。