【备战秋招冲击大厂】Java面试题系列—Redis,2024年最新java面试题全集

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024b (备注Java)
img

正文

更多Java学习资料、面试真题获得,请【点击此处

14. Java使用redis

  • 连接:Jedis jedis = new Jedis(“127.0.0.1”,6379);

  • 插入:jedis.set(“k1”,”v1”);

  • 事务:

Transaction transaction = jedis.multi();

transaction.set(“k2”,”v2”);

transaction.set(“k3”,”v3”);

transaction.exec();

  • 加锁:

public class TestTransaction {

public boolean transMethod() {

Jedis jedis = new Jedis(“127.0.0.1”, 6379);

int balance;// 可用余额

int debt;// 欠额

int amtToSubtract = 10;// 实刷额度

jedis.watch(“balance”);

//jedis.set(“balance”,“5”);//此句不该出现。模拟其他程序已经修改了该条目

balance = Integer.parseInt(jedis.get(“balance”));

if (balance < amtToSubtract) {

jedis.unwatch();

System.out.println(“modify”);

return false;

} else {

System.out.println(“***********transaction”);

Transaction transaction = jedis.multi();

transaction.decrBy(“balance”, amtToSubtract);

transaction.incrBy(“debt”, amtToSubtract);

transaction.exec();

balance = Integer.parseInt(jedis.get(“balance”));

debt = Integer.parseInt(jedis.get(“debt”));

System.out.println(“*******” + balance);

System.out.println(“*******” + debt);

return true;

}

}

/**

  • 通俗点讲,watch命令就是标记一个键,如果标记了一个键, 在提交事务前如果该键被别人修改过,那事务就会失败,这种情况通常可以在程序中重新再尝试一次。

  • 首先标记了键balance,然后检查余额是否足够,不足就取消标记,并不做扣减; 足够的话,就启动事务进行更新操作,

  • 如果在此期间键balance被其它人修改, 那在提交事务(执行exec)时就会报错, 程序中通常可以捕获这类错误再重新执行一次,直到成功。

*/

public static void main(String[] args) {

TestTransaction test = new TestTransaction();

boolean retValue = test.transMethod();

System.out.println("main retValue-------: " + retValue);

}

}

  • 主从复制

  • 配置从库:Jedis jedis_s = new Jedis(“127.0.0.1”,6380);

  • Jedis_s.slaveof(“127.0.0.1”,6379);

  • JedisPool

JedisPoolConfig poolConfig = new JedisPoolConfig( );

poolConfig.setMaxActive ( 1000);

poolconfig.setMaxIdle ( 32);

poolconfig. setMaxwait (100*1000);poolconfig.setTestOnBorrow(true);

jedisPool = new JedisPool(poolConfig, “127.0.0.1”,6379);

  • maxActive:控制一个pool可分配多少个jedis实例,通过pool.getResource()来获取;如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted。

  • maxIdle:控制一个pool最多有多少个状态为idle(空闲)的jedis实例;

  • whenExhaustedAction:表示当pool中的jedis实例都被allocated完时,pool要采取的操作:默认有三种。

  • WHEN_EXHAUSTED_FAIL -->表示无jedis实例时,直接抛出NoSuchElementException;

  • WHEN_EXHAUSTED_BLOCK -->则表示阻塞住,或者达到maxWait时抛出JedisConnectionException;

  • WHEN_EXHAUSTED_GRoW -->则表示新建一个jedis实例,也就说设置的maxActive无用;

  • maxWait:表示当borrow一个jedis实例时,最大的等待时间,如果超过等待时间,则直接抛JedisConnectionException;

  • testOnBorrow:获得一个jedis实例的时候是否检查连接可用性(ping());如果为true,则得到的jedis实例均是可用的:

15. 解决session存储问题

  • 方案一:存在cookie里

  • 不安全

  • 网络负担效率低

  • 方案二:存在文件服务器或数据库里

  • 大量的IO效率问题

  • 方案三:session复制

  • Session数据冗余

  • 节点越多浪费越大

  • 方案四:缓存数据库

  • 完全存在内存中,速度快数据结构简单

16. 单线程+多路IO复用

多路复用是指用一个线程来检查多个文件描述符(socket)的就绪状态,比如调用select、poll、epoll函数进行监视,传入多个文件描述符,如果有一个文件描述符就绪,则返回,否则阻塞直到超时。得到就绪状态后进行真正的操作可以在同一个线程里执行,也可以启动线程执行(比如使用线程池)。

多路I/O复用模型是利用 select、poll、epoll 可以同时监察多个流的 I/O 事件的能力,在空闲的时候,会把当前线程阻塞掉,当有一个或多个流有 I/O 事件时,就从阻塞态中唤醒,于是程序就会轮询一遍所有的流(epoll 是只轮询那些真正发出了事件的流),并且只依次顺序的处理就绪的流,这种做法就避免了大量的无用操作。这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程。

  • Select:每一个请求都进行询问,最多1024个

  • Poll:每一个请求都进行询问不限制数量

  • Epoll:监视请求时为每个请求设置标识符,不需要一一询问

17. Select、poll、epoll

  • select的几大缺点:

1)每次调用select,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大

2)同时每次调用select都需要在内核遍历传递进来的所有fd,这个开销在fd很多时也很大

3)select支持的文件描述符数量太小了,默认是1024

  • 为什么epoll比select和poll更高效?

1)减少了用户态和内核态之间文件描述符的拷贝

2)减少了对就绪文件描述符的遍历

3)select和poll只支持LT模式,而epoll支持高效的ET模式,并且epoll还支持EPOLLONESHOT事件。

  • 无论哪种情况下,epoll都比select和poll高效吗?

  • epoll适用于连接较多,活动数量较少的情况。

1)epoll为了实现返回就绪的文件描述符,维护了一个红黑树和好多个等待队列,内核开销很大。如果此时监听了很少的文件描述符,底层的开销会得不偿失;

2)epoll中注册了回调函数,当有事件发生时,服务器设备驱动调用回调函数将就绪的fd挂在rdllist上,如果有很多的活动,同一时间需要调用的回调函数数量太多,服务器压力太大。

  • select和poll适用于连接较少的情况。

1)当select和poll上监听的fd数量较少,内核通知用户现在有就绪事件发生,应用程序判断当前是哪个fd就绪所消耗的时间复杂度就会大大减小。

18. REDIS缓存穿透,缓存击穿,缓存雪崩原因+解决方案

  • 缓存穿透:key对应的数据在数据库和缓存并不存在,每次针对此key的请求从缓存获取不到,请求都会到数据库,从而可能压垮数据库。比如用一个不存在的用户id获取用户信息,不论缓存还是数据库都没有,若黑客利用此漏洞进行攻击可能压垮数据库。

  • 解决方案:

1)最常见的则是采用布隆过滤器,在写入数据库时,将数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。

2)简单粗暴的方法:如果一个查询返回的数据为空(不管是数据不存在,还是系统故障),我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。

  • 缓存击穿:是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。

  • 解决方案

1)使用互斥锁:就是在缓存失效的时候(判断拿出来的值为空),不是立即去load db,而是先使用缓存工具的某些带成功操作返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一个mutex key,当操作返回成功时,再进行load db的操作并回设缓存;否则,就重试整个get缓存的方法。

2)设置永不过期

  • 缓存雪崩:当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,也会给后端系统(比如DB)带来很大压力。

  • 大量数据同时过期解决方案

1)用加锁或者队列的方式保证来保证不会有大量的线程对数据库一次性进行读写,从而避免失效时大量的并发请求落到底层存储系统上。加锁排队只是为了减轻数据库的压力,并没有提高系统吞吐量。

2)将缓存失效时间分散开,比如我们可以在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。

3)双key策略,主key设置过期时间,备key设置永久,主key过期时,返回备key内容

4)后台缓存更新,定时更新、消息队列通知更新

服务器宕机解决方案

1)服务熔断:在分布式系统中,我们往往需要依赖下游服务,不管是内部系统还是第三方服务,如果下游出现问题,我们不在盲目地去请求,在一个周期内失败达到一定次数,不在请求,及时失败。过一段时间,在逐步放开请求,这样既能防止不断的调用,使下游服务更坏,保护了下游方,还能降低自己的执行成本,快速的响应,减少延迟,增加吞吐量。

2)服务降级:降级就是为了解决资源不足和访问量增加的矛盾,在有限的资源情况下,为了能抗住大量的请求,就需要对系统做出一些牺牲,有点“弃卒保帅”的意思。放弃一些功能,保证整个系统能平稳运行。比如:抢购可以占时限流评论,将流量让给秒杀业务

3)请求限流:通过对并发访问进行限速。最简单的方式,把多余的请求直接拒绝掉,可以根据一定的用户规则进行拒绝策略

4)构建redis高可靠集群

19. 布隆过滤器

布隆过滤器由「初始值都为 0 的位图数组」和「 N 个哈希函数」两部分组成。当我们在写入数据库数据时,在布隆过滤器里做个标记,这样下次查询数据是否在数据库时,只需要查询布隆过滤器,如果查询到数据没有被标记,说明不在数据库中。

布隆过滤器会通过 3 个操作完成标记:

  • 第一步,使用 N 个哈希函数分别对数据做哈希计算,得到 N 个哈希值;

  • 第二步,将第一步得到的 N 个哈希值对位图数组的长度取模,得到每个哈希值在位图数组的对应位置。

  • 第三步,将每个哈希值在位图数组的对应位置的值设置为 1;

举个例子,假设有一个位图数组长度为 8,哈希函数 3 个的布隆过滤器。

在数据库写入数据 x 后,把数据 x 标记在布隆过滤器时,数据 x 会被 3 个哈希函数分别计算出 3 个哈希值,然后在对这 3 个哈希值对 8 取模,假设取模的结果为 1、4、6,然后把位图数组的第 1、4、6 位置的值设置为 1。当应用要查询数据 x 是否数据库时,通过布隆过滤器只要查到位图数组的第 1、4、6 位置的值是否全为 1,只要有一个为 0,就认为数据 x 不在数据库中。

布隆过滤器由于是基于哈希函数实现查找的,高效查找的同时存在哈希冲突的可能性,比如数据 x 和数据 y 可能都落在第 1、4、6 位置,而事实上,可能数据库中并不存在数据 y,存在误判的情况。

所以,查询布隆过滤器说数据存在,并不一定证明数据库中存在这个数据,但是查询到数据不存在,数据库中一定就不存在这个数据。

20. 为什么要用redis而不用map做缓存?

  • Redis 可以用几十 G 内存来做缓存,Map 不行,一般 JVM 也就分几个 G 数据就够大了

  • Redis 的缓存可以持久化,Map 是内存对象,程序一重启数据就没了

  • Redis 可以实现分布式的缓存,Map 只能存在创建它的程序里

  • Redis 可以处理每秒百万级的并发,是专业的缓存服务,Map 只是一个普通的对象

  • Redis 缓存有过期机制,Map 本身无此功能

  • Redis 有丰富的 API,Map 就简单太多了

21. 如何保持缓存和数据库的一致性?

  • 淘汰缓存还是更新缓存?

选择淘汰缓存,原因:数据可能为简单数据,也可能为较复杂的数据,复杂数据进行缓存的更新操作,成本较高,因此一般推荐淘汰缓存

  • 先淘汰缓存还是先更新数据库?

选择先淘汰缓存,再更新数据库,原因:假如先更新数据库,再淘汰缓存,如果缓存淘汰失败,那么后面的请求都会得到脏数据,直至缓存过期。假如先淘汰缓存再更新数据库,如果数据库更新失败,只会产生一次缓存miss,相比较而言,后者对业务影响更小一点。

  • 延时双删策略:解决数据库读写分离

public void write(String key,Object data){

redisUtils.del(key);

db.update(data);

Thread.Sleep(100);

redisUtils.del(key);

}

22. Redis分布式锁的实现

  • 加锁:使用setnx key value命令,如果key不存在,设置value(加锁成功)。如果已经存在lock(也就是有客户端持有锁了),则设置失败(加锁失败)。

  • 解锁:使用del命令,通过删除键值释放锁。释放锁之后,其他客户端可以通过setnx命令进行加锁。

23. Redis集群

  • Redis集群解决内存压力,实现了对redis的水平扩容,即启动N个redis节点,将整个数据库分布在N个节点中,每个节点存储数据的1/N。

  • Redis集群通过分区来提供一定程度的可用性,即使集群中有一部分节点失效或者无法进行通讯,集群也可以基础处理命令请求。

24.Redis部署模型

  • 模式一:单实例

  • 模式二:一主一从

  • 模式三:一主多从

  • 模式四:多主多从

  • 模式五:集群

25.Redis缓存预热

缓存预热的思路

(1) 提前给redis中嵌入部分数据,再提供服务,肯定不可能将所有数据都写入redis,因为数据量太大了,第一耗费的时间太长了,第二redis根本就容纳不下所有的数据

(2) 需要更具当天的具体访问情况,试试统计出频率较高的热数据

(3) 然后将访问频率较高的热数据写入到redis,肯定是热数据也比较多,我们也得多个服务并行的读取数据去写,并行的分布式的缓存预热

(4) 然后将嵌入的热数据的redis对外提供服务,这样就不至于冷启动,直接让数据库奔溃了

具体的实时方案:

(1) nginx+lua将访问量上报到kafka中要统计出来当前最新的实时的热数据是哪些,我们就得将商品详情页访问的请求对应的流量,日志,实时上报到kafka中,

(2) storm从kafka中消费数据,实时统计出每个商品的访问次数,访问次数基于LRU内存数据结构的存储方案。

总结

在清楚了各个大厂的面试重点之后,就能很好的提高你刷题以及面试准备的效率,接下来小编也为大家准备了最新的互联网大厂资料。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
统计出每个商品的访问次数,访问次数基于LRU内存数据结构的存储方案。

总结

在清楚了各个大厂的面试重点之后,就能很好的提高你刷题以及面试准备的效率,接下来小编也为大家准备了最新的互联网大厂资料。

[外链图片转存中…(img-FA4xjgDU-1713439334187)]

[外链图片转存中…(img-F0Q2CWeo-1713439334187)]

[外链图片转存中…(img-gPStczQu-1713439334188)]

[外链图片转存中…(img-pysOgy7H-1713439334189)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-26YL1qWA-1713439334189)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 28
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
关于JavaRedis面试题,你可以参考以下资源: 1. "Java基础教程(入门篇)"这本书中可能包含与JavaRedis相关的基础知识点,例如如何连接和操作Redis以及在Java中使用Redis的常见场景。 2. "java面试大集合"这本书中可能包含JavaRedis面试题,涵盖了Java技术栈以及与Redis相关的问题。你可以浏览这本书中的相关章节以寻找你感兴趣的JavaRedis面试题。 3. "Java基础教程(进阶篇)"这本书可能包含更深入的JavaRedis面试题,例如Java高并发和如何在Java中使用Redis进行缓存。 这些资源可能会给你提供一些有关JavaRedis面试题的参考。你可以根据自己的需求和兴趣选择适合的资源进行学习。希望这些资源能帮助到你。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [redis面试题总结(附答案)](https://blog.csdn.net/guorui_java/article/details/117194603)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [java面试大集合一共485页](https://download.csdn.net/download/wm9028/88268176)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值