背景
在使⽤word⽂档时,word如何判断某个单词是否拼写正确?
⽹络爬⾍程序,怎么让它不去爬相同的url⻚⾯?
垃圾邮件(短信)过滤算法如何设计?
公安办案时,如何判断某嫌疑⼈是否在⽹逃名单中?
缓存穿透问题如何解决?
先来看一个场景,假如我们的数据库使用的是 mysql,缓存使用 redis。
server
redis
mysql
数据读取步骤是这样的:
先访问 redis ,如果数据存在直接返回;如果不存在则进行步骤 2;
访问 mysql ,如果数据不存在,直接返回;如果存在则进行步骤 3;
将 mysql 中存在的 key 写回 redis;
出现的问题: 如果 redis 和 mysql 中都没有相应的数据,此时又有大量的该数据的请求(伪造数据攻击),最终的压力还是会全部涌向 mysql。这就是所谓的 缓存穿透。
解决方案:
在 redis 端设置 键值对,以避免访问 mysql。当然缺点是如果 过多时会占用过多的内存。我们可以给 key 设置过期时间,比如 exoire key 600ms, 停止攻击后最终由 redis 自动清除这些无用的 key ;
在 server 端设置一个布隆过滤器,将 mysql 中包含的 key 放入布隆过滤器中;布隆过滤器能过滤一定不存在的数据。
布隆过滤器
假设我么你现在提出一个需求:从海量数据中查询某字符串是否存在。
在 c++ 中我们首先想到的应该是使用 STL 中的 set 或者 map。
set 和 map
c++ 标准库(STL)中的 set 和 map 结构都是采⽤红⿊树实现的,它增删改查的时间复杂度是:
o
(
l
o
g
2
n
)
o(log_{2}n)o(log2n)
对于严格平衡⼆叉搜索树(AVL),100w 条数据组成的红⿊树,只需要⽐较20次就能找到该值;对于10亿条数据只需要⽐较30次就能找到该数据;也就是查找次数跟树的⾼度是⼀致的;