面试八股之redis篇(day1)

redis:后端最常见的缓存中间件。需要重点关照

主要包含两个场景:使用场景    其他面试题

其中使用场景包含:缓存,分布式锁,计数器,保存token,消息队列,延迟队列。

其他面试题:集训相关内容,事务,redis为社么那么快‘

使用场景有十个面试题,其他面试题有八个,需要记忆。

redis使用场景面试题

  1,我看你做的项目中都用到了redis,你最近在项目的哪些场景中使用了redis呢?

(结合简历当中的内容回答)

问题目的:验证项目场景真实性,作为深入发问的切入点

常见切入点:1缓存穿透,2缓存击穿,3雪崩

1.缓存穿透:查询一个不存在的数据,MySQL查询不到数据也不会直接写入缓存,就会导致每次请求都查询数据库。

面试八股之redis篇(day1)_第1张图片

    一般情况下出现这种问题的原因是因为有人恶意通过你的请求路径,制造假id或比较大的值来冲击你的数据库,导致你的数据库被击垮宕。

解决方案1:缓存空数据,查询返回的数据为空,把这个空结果进行缓存

可能缓存内容数据不一致,当key=1的值被攻击赋予空值后,下一次正常key=1的数据想进来是无法被赋值的,导致缓存内容数据不一致。

优点:简单。  缺点:可能出现缓存内容数据不一致问题,占用内存太多

解决方案2:布隆过滤器

作用:布隆过滤器可以用于检测一个元素是否在一个集合中,用于拦截不存在的数据

前提:在缓存预热的时候需要预热布隆过滤器

详细实现原理:

依赖 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,缺点:实现复杂,存在误判。

2.缓存击穿:给某一个key设置了过期时间,当key过期的时候,恰好这个时间点对这个key有大量的并发请求过来,这些并发请求可能会瞬间把DB压垮

解决方案1:互斥锁

面试八股之redis篇(day1)_第2张图片

流程:

线程1

1,先查询缓存,没查到数据。2,添加互斥锁。3,查询数据库,重建缓存数据。4,写入缓存。5,释放锁。

线程2

1,查询缓存未命中。2,想获取锁,但是线程一正在使用互斥锁重建缓存数据,获取互斥锁失败。3,休眠一会在充实获取互斥锁。4,不断重试,直到线程一重建缓存,线程二直接从缓存获取数据。

特点:强一致性(和钱相关),性能差

解决方案2:逻辑过期

流程

线程一 

1,查询缓存,发现缓存已过期。2,获取互斥锁成功。3,开启新线程线程2,线程二重建缓存写入缓存释放锁。4,线程一返回过期数据。

线程3(线程2重建缓存之前)

1,查询缓存发现过期。2,获取锁失败。3,返回过期数据

线程4(线程2重建缓存之后)

1,命中缓存,且没有过期

特点:高可用性(注重用户体验),性能优秀

3.缓存雪崩:在同一时间段大量的key同时失效或者redis服务器宕机,导致大量请求到达数据库,带来巨大压力。

解决方案1(key同时失效):给不同的key的TTL添加随机值

解决方案2(redis服务器宕机):利用redis集群提高服务的可用性,哨兵模式,集群模式

解决方案3:给缓存业务添加降级限流策略:nginx或者微服务网关(gateway)上添加降级限流策略。我使用的是sentinel,可以给业务添加熔断,限流等具体的限制。

解决方案4:给业务添加多级缓存:用Guava或者Caffeine作为一级缓存,redis作为二级缓存

与缓存穿透的区别就是,一个是只有一个key失效,一个是大量key'同时失效。这redis三兄弟其实都可以用限流来做保底的解决方法。

你可能感兴趣的:(java面试八股,学习,redis,数据库)