主要包含两个场景:使用场景 其他面试题
其中使用场景包含:缓存,分布式锁,计数器,保存token,消息队列,延迟队列。
其他面试题:集训相关内容,事务,redis为社么那么快‘
使用场景有十个面试题,其他面试题有八个,需要记忆。
(结合简历当中的内容回答)
问题目的:验证项目场景真实性,作为深入发问的切入点
常见切入点:1缓存穿透,2缓存击穿,3雪崩
一般情况下出现这种问题的原因是因为有人恶意通过你的请求路径,制造假id或比较大的值来冲击你的数据库,导致你的数据库被击垮宕。
可能缓存内容数据不一致,当key=1的值被攻击赋予空值后,下一次正常key=1的数据想进来是无法被赋值的,导致缓存内容数据不一致。
优点:简单。 缺点:可能出现缓存内容数据不一致问题,占用内存太多
作用:布隆过滤器可以用于检测一个元素是否在一个集合中,用于拦截不存在的数据
前提:在缓存预热的时候需要预热布隆过滤器
详细实现原理:
依赖 bitmap(位图):相当于是一个以bit为单位的数组,数组中的每个单元只能存储二进制数0或1。当存储数据的时候,会把这个数据通过多个哈希函数来获取哈希值,更具哈希计算书组对应的位置改为1,然后把这些数据都存储在这张位图中。
0 | 1 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
存储数据:id为1的数据,通过多个hash函数获取hash值,根据hashi计算数组对应的位置更改为1
如上图,id1就是由hash1(1)=1,hash2(1)=3,hash3(1)=7构成
查询数据:使用相同的hash函数获取hash值,判断对应位置是否都为1,都是则这个数存在。
所以会存在问题,假设id1占据了137,id2占据了589,假设id3占据的是389,那该怎么办呢?
误判率:数组越小,误判率越大,数组越大,误判率越小,同时带来更多的内存消耗。
在具体的实现方案中(例入redission或Guava中)都可以设置这个误判率的可允许大小。
private static void initData(RBloomFilter bloomFilter, int size){
//第一个参数:布隆过滤器存储的元素个数:第一个参数:误判率
bloomFilter.tryInt(size,0.05);
//在布隆过滤器初始化数据‘
for(int i=0;i
一般项目的误判率都在百分之五左右
优点:内存占用较少,没有多余的key,缺点:实现复杂,存在误判。
流程:
线程1
1,先查询缓存,没查到数据。2,添加互斥锁。3,查询数据库,重建缓存数据。4,写入缓存。5,释放锁。
线程2
1,查询缓存未命中。2,想获取锁,但是线程一正在使用互斥锁重建缓存数据,获取互斥锁失败。3,休眠一会在充实获取互斥锁。4,不断重试,直到线程一重建缓存,线程二直接从缓存获取数据。
特点:强一致性(和钱相关),性能差
流程
线程一
1,查询缓存,发现缓存已过期。2,获取互斥锁成功。3,开启新线程线程2,线程二重建缓存写入缓存释放锁。4,线程一返回过期数据。
线程3(线程2重建缓存之前)
1,查询缓存发现过期。2,获取锁失败。3,返回过期数据
线程4(线程2重建缓存之后)
1,命中缓存,且没有过期
特点:高可用性(注重用户体验),性能优秀
解决方案1(key同时失效):给不同的key的TTL添加随机值
解决方案2(redis服务器宕机):利用redis集群提高服务的可用性,哨兵模式,集群模式
解决方案3:给缓存业务添加降级限流策略:nginx或者微服务网关(gateway)上添加降级限流策略。我使用的是sentinel,可以给业务添加熔断,限流等具体的限制。
解决方案4:给业务添加多级缓存:用Guava或者Caffeine作为一级缓存,redis作为二级缓存
与缓存穿透的区别就是,一个是只有一个key失效,一个是大量key'同时失效。这redis三兄弟其实都可以用限流来做保底的解决方法。