面对海量请求,缓存设计还应该考虑哪些问题?(搬运)

78 阅读2分钟

缓存穿透是指查询一个一定不存在的数据,因为这个数据不存在,所以永远不会被缓存,所以每次请求都会去请求数据库。

例如我们请求一个 UserID 为 -1 的用户数据,因为该用户不存在,所以该请求每次都会去读取数据库。在这种情况下,如果某些心怀不轨的人利用这个存在的漏洞去伪造大量的请求,那么很可能导致DB承受不了那么大的流量就挂掉了。

对于缓存穿透,有几种解决方案,一种是事前预防,一种是事后预防。

事前预防。 其实就是对所有请求都进行参数校验,把绝大多数非法的请求抵挡在最外层。在我们举的这个例子中,那么就是做参数校验,对于 UserID 小于 0 的请求全部拒绝。但即使我们做了全面的参数校验,还是可能存在漏网之鱼,会出现一些我们没想到的情况。

例如我们的 UserID 是递增的,那么如果有人请求一个 UserID 很大的用户信息(例如:1000000),而我们的 UserID 最大也就 10000。这个时候,你不可能限制 UserID 大于 1 万的就是非法的,或者说大于 10 万就是非法的,所以该用户ID肯定可以通过参数校验。但该用户确实不存在,所以每次请求都会去请求数据库。

其实上面只是我所能想到的一种情况,我们没想到的情况肯定还有很多。对于这些情况,我们能做的就是时候预防。

事后预防。 事后预防说的就是当查询到一个空的结果时,我们仍然将这个空的结果进行缓存,但是设置一个很短的过期时间(例如一分钟)。在这里我们可以看到,其实我们并没有完全预防非法请求,只不过是将非法请求的风险让承受能力更强的redis去承担,让承受能力稍弱的数据库更安全。

通过上面这两种处理方式,我们基本可以解决缓存穿透的问题。事前预防解决80%的非法请求,剩下的20%非法请求则使用Redis转移风险。