高并发系统设计:缓存穿透

定义

  • 缓存穿透是指从缓存中没有查到数据,而不得不从后端系统(比如数据库)中查询的情况。
  • 少量的缓存穿透不可避免,对系统也是没有损害的,主要有几点原因:
  • 缓存系统在容量上是有限的,不可能存储系统所有的数据;80%是非热点数据,不会被经常访问,可以放弃缓存。
  • 大量的穿透请求超过了后端系统的承受范围造成了后端系统的崩溃,这种情况就是我们应该避免的了。

回种空值

  • 例如:读取一个用户表中未注册的用户,采用 Cache Aside 策略,会先读缓存再穿透读数据库。由于用户并不存在,所以缓存和数据库中都没有查询到数据,因此也就不会向缓存中回种数据(也就是向缓存中设置值的意思),这样当再次请求这个用户数据的时候还是会再次穿透到数据库
  • 因为空值并不是准确的业务数据,并且会占用缓存的空间,所以我们会给这个空值加一个比较短的过期时间
  • 回种空值虽然能够阻挡大量穿透的请求,但如果有大量获取未注册用户信息的请求,缓存内就会有有大量的空值缓存,也就会浪费缓存的存储空间,如果缓存空间被占满了,还会剔除掉一些已经被缓存的用户信息反而会造成缓存命中率的下降。
  • 这个方案,建议在使用的时候评估一下缓存容量是否能够支撑。

布隆过滤器

  • 把集合中的每一个值按照提供的 Hash 算法(可能是多个算法)算出对应的 Hash 值,然后将 Hash 值对数组长度取模后得到需要计入数组的索引值,并且将数组这个位置的值从 0 改成 1。
  • 在判断一个元素是否存在于这个集合中时,只需要将这个元素按照相同的算法计算出索引值,如果这个位置的值为 1 就认为这个元素在集合中,否则则认为不在集合中。
    在这里插入图片描述
  • 布隆过滤器拥有极高的性能,无论是写入操作还是读取操作,时间复杂度都是 O(1) 是常量值。
  • 在空间上,相对于其他数据结构它也有很大的优势,比如,20 亿的数组需要 2000000000/8/1024/1024 = 238M 的空间,而如果使用数组来存储,假设每个用户 ID 占用 4 个字节的空间,那么存储 20 亿用户需要 2000000000 * 4 / 1024 / 1024 = 7600M 的空间,是布隆过滤器的 32 倍。
  • 主要有两个缺陷:判断元素是否在集合中时是有一定错误几率的,比如它会把不是集合中的元素判断为处在集合中;不支持删除元素
  • 这两个问题主要都和hash碰撞相关:第一个问题可以使用多个hash算法,算出多个位置,多个位置值都置为1来解决;第二个问题可以让位置中的值不在为0或1,而是一个计数。当然这样会带来存储空间的增大

“dog-pile effect”(狗桩效应)

  • 定义:当有一个极热点的缓存项,它一旦失效会有大量请求穿透到数据库,这会对数据库造成瞬时极大的压力
  • 在代码中控制在某一个热点缓存项失效之后启动一个后台线程,穿透到数据库,将数据加载到缓存中,在缓存未加载之前,所有访问这个缓存的请求都不再穿透而直接返回。
  • 通过设置分布式锁,只有获取到锁的请求才能够穿透到数据库。分布式锁的方式也比较简单,比方说 ID 为 1 的用户是一个热点用户,当他的用户信息缓存失效后,需要从数据库中重新加载数据时,先向 redis 中写入一个 Key 为"lock.1"的缓存项,然后去数据库里面加载数据,当数据加载完成后再把这个 Key 删掉。这时,如果另外一个线程也要请求这个用户的数据,它发现缓存中有 Key 为“lock.1”的缓存,就认为目前已经有线程在加载数据库中的值到缓存中了,它就可以重新去缓存中查询数据,不再穿透数据库了。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值