# Cache 空值与缓存穿透 当查询一个不存在的数据时,会得到一个空值。如果缓存层不缓存这个空值,那么查询就会穿透到 数据库,给数据库带来查询压力。当一个爬虫大量抓取不存在的数据时,这个问题尤为明显。 缓存穿透使得缓存层失去了保护后端存储的能力,如果后端存储层关联业务比较多的情况下,甚至可能引起雪崩。 但是缓存空值也会带来新问题: - 其一, 浪费缓存存储空间。比起不缓存空值,会缓存更多的数据。但我们认为以空间换时间是值得的,对于 这类数据我们也会缓存更短的时间(在5 分钟,和正常过期时间的十分之一两者间去最小值) - 其二, 业务层新增数据可能不能被正常取到。当缓存了一条不存在的数据后,在缓存过期前这条数据可能刚好 被创建了出来,这时就造成了一定时间内的数据不一致。业务层需要注意到这点,如果在新建数据后就立刻访问, 你需要 refresh 一下来刷新缓存。 对于访问量比较小的业务,可以直接禁掉缓存空值。`Tache.cached` 方法中提供一个 `should_cache_fn` 的参数, 接受一个 function, 传入被装饰函数执行的结果,返回一个布尔值来决定是否可以缓存。 ``` @cache.cached(should_cache_fn=lambda value: value is not None) def incr(by): ... ``` 这个例子中的 `should_cache_fn` 接受的函数就表示,除了 `None` 外都缓存。 也可以很方便的禁用缓存,以便在开发阶段排除是否是缓存引起的 bug ``` @cache.cached(should_cache_fn=lambda _: False) def incr(by): ... ``` `Tache.batch` 不支持此用法。