使用缓存须要了解几个缓存问题,缓存击穿、缓存穿透以及缓存雪崩,须要了解它们产生的缘由以及怎么避免,尤为是当你打算设计本身的缓存框架的时候须要考虑如何处理这些问题。git
通常的缓存系统,都是按照 key 去缓存查询,若是不存在对应的 value ,就应该去后端系统查找(好比数据库)。若是 key 对应的 value 是必定不存在的,而且对该 key 并发请求量很大,就会对后端系统就会形成很大的压力。github
在高并发下,多线程同时查询同一个资源,若是缓存中没有这个资源,那么这些线程都会去后端服务或数据库查找,对数据库形成极大压力,缓存也就失去存在的意义。算法
缓存击穿解决方案数据库
致使缓存击穿的问题在于高并发多线程情景下,许多请求一会儿都到后端服务和数据库,致使后端服务与数据库的压力骤增。后端
处理这个问题,在多线程请求同一个 key 的时候,进行排队,这样第一次请求后端服务和数据库以后更新缓存的值,下一个请求从缓存中取数据的时候就会拿到缓存数据,不会再请求后端服务和数据库。缓存
缓存穿透是指用户查询数据,在数据库没有,天然在缓存中也不会有。这样就致使用户查询的时候,在缓存中找不到,每次都要去数据库中查询,从而失去了缓存的意义并且相比直接查询数据库还增长了每次都去查缓存。服务器
缓存穿透解决方案数据结构
致使问题出现的缘由在于请求一个不存在的数据从而使得缓存始终不存在进而致使后端系统(主要是数据库)要承受很大的压力,因此想要解决这个问题,就势必就在缓存这里拦截住大量的请求,使得最终走到后端系统,查询数据库的请求尽量的少。多线程
通常处理这个问题,缓存不存在的时候会在缓存中设置一个时间较短的内容为空的缓存,从而减小实际请求到后端和进行数据库查询的次数。
复杂一些的解决方案有 布隆过滤器,基本原理是设置一个 list,查询缓存的时候从 list 里进行判断,这里不作多介绍。
布隆过滤器(Bloom Filter)是1970年由布隆提出的。它其实是一个很长的二进制向量和一系列随机映射函数。布隆过滤器能够用于检索一个元素是否在一个集合中。它的优势是空间效率和查询时间都远远超过通常的算法,缺点是有必定的误识别率和删除困难
若是想要判断一个元素是否是在一个集合里,通常想到的是将全部元素保存起来,而后经过比较肯定。链表,树等等数据结构都是这种思路. 可是随着集合中元素的增长,咱们须要的存储空间愈来愈大,检索速度也愈来愈慢(O(n),O(logn))。不过世界上还有一种叫做散列表(又叫哈希表,Hash table)的数据结构。它能够经过一个Hash函数将一个元素映射成一个位阵列(Bit array)中的一个点。这样一来,咱们只要看看这个点是否是1就能够知道集合中有没有它了。这就是布隆过滤器的基本思想。
当缓存服务器重启或者大量缓存集中在某一个时间失效,这样在失效的时候,也会给后端系统和数据库带来很大压力.
缓存雪崩解决方案
致使出现缓存雪崩的根本缘由在于缓存大量失效,从而致使大量请求没有命中缓存,大量请求走到后端服务和数据库,形成压力。
若是系统启动就依赖不少缓存,那能够经过其它服务进行缓存预热,提早把须要的数据放到缓存中,避免系统启动大量请求直接请求到后端服务和数据库。
既然是因为同一时间缓存大量失效,咱们也能够着手从缓存的失效时间上,作一些优化,让缓存不要在同一时间点失效。
具体的实施办法,你能够在设置失效时间的时候随机加几秒过时时间,避免同一时间点缓存大量失效。
Contact me: weihanli@outlook.com