重点八股总结

感恩牛客的各位大佬给我的各种面经,把我自己整理的重点面经也发出来给后来人看看。

其实,到后面才发现这些不过是非常简单的问题,所以不妨把战线拉长一点。切不要为暂时的得失而胆怯!

重点的知识

CMS(Concurrent Mark-Sweep)垃圾回收器

CMS(Concurrent Mark-Sweep)是一种以最小化停顿时间为目标的垃圾回收器,适用于低延迟的应用场景。它主要用于老年代的垃圾回收。CMS 的工作过程分为四个阶段:

  1. 初始标记(Initial Mark):标记直接与 GC Roots 相连的对象,这个阶段会触发“Stop The World(STW)”,但时间很短。
  2. 并发标记(Concurrent Mark):在该阶段,GC 线程和应用程序线程并发运行,标记从 GC Roots 可达的对象。应用程序可以继续运行,因此不会有明显的停顿。
  3. 重新标记(Remark):为了处理并发标记过程中新增的对象或修改的引用关系,需要一次重新标记,这个阶段也会触发 STW,不过时间较短。
  4. 并发清除(Concurrent Sweep):在该阶段,GC 线程并发清理未被标记的对象空间,不会影响应用线程。

优点

  • 并发标记和清除阶段几乎不会停止应用程序运行,停顿时间较短。

缺点

  • 清理时不会对内存进行整理,容易产生碎片,可能导致老年代无法分配大对象。
  • 需要更多的 CPU 资源,特别是在并发阶段,GC 线程和用户线程争夺资源。

G1垃圾回收器

G1 收集器不采用传统的新生代和老年代物理隔离的布局方式,仅在逻辑上划分新生代和老年代,将整个堆内存划分为2048个大小相等的独立内存块Region,每个Region是逻辑连续的一段内存,具体大小根据堆的实际大小而定。

G1收集器通过跟踪Region中的垃圾堆积情况,每次根据设置的垃圾回收时间,回收优先级最高的区域,避免整个新生代或整个老年代的垃圾回收,使得stop the world的时间更短、更可控,同时在有限的时间内可以获得最高的回收效率。

三色标记算法

三色标记算法是并发收集阶段的重要算法,它是描述追踪式回收器的一种有用的方法,利用它可以推演回收器的正确性。 首先,我们将对象分成三种类型的。

黑色:根对象,或者该对象与它的子对象都被扫描了灰色:对象本身被扫描,但还没扫描完该对象中的子对象白色:未被扫描对象,扫描完成所有对象之后,最终为白色的为不可达对象,即垃圾对象

MVCC 在 InnoDB 的实现方案

MVCC(多版本并发控制)是 InnoDB 用于实现事务隔离的技术。其核心是通过保存数据的多个版本来避免读写冲突。具体实现包括:

  • 为每行记录添加两个隐藏字段:一个表示数据版本的创建时间戳,一个表示删除时间戳。
  • 当读数据时,根据事务的时间戳判断当前事务能否看到该数据版本,来实现快照读和当前读。
  • MVCC 主要用于实现 READ COMMITTEDREPEATABLE READ 两种隔离级别。

Redis 除了缓存,还有什么应用场景

  • 消息队列:通过列表或发布订阅模式实现消息队列。
  • 分布式锁:通过 setnx 和过期时间实现分布式锁。
  • 计数器:Redis 的自增操作非常适合实现高并发场景下的计数器。
  • 会话管理:通过 Redis 存储会话,保证分布式系统中会话的共享。
  • 排行榜:使用有序集合存储用户排名数据。

Redis 实现超时订单取消

可以使用 Redis 的延时队列,或通过 setnx 设置订单的超时时间,当订单超时后通过定时任务扫描未支付订单并取消。

Redis 实现分布式锁

1. setnx

Redis 实现分布式锁常用 SET key value NX EX time 命令:

  • NX 保证锁只会被一个客户端获取。
  • EX 设置锁的过期时间,防止死锁。
2. Redisson 分布式锁

Redisson 是一个基于 Redis 的高级客户端库,提供了许多实用的 Redis 功能,包括分布式锁。相比于原生的 SETNX,Redisson 实现了一个更加复杂和完善的分布式锁机制。

  • 高抽象封装:Redisson 提供了类似 Java 中的 ReentrantLock 的分布式锁实现,API 简单且易用,隐藏了底层细节。
  • 自动续期:Redisson 实现了锁的自动续期功能,当持有锁的线程仍在执行时,Redisson 会不断延长锁的过期时间,防止锁过期失效导致其他线程误拿锁。
  • 公平锁和非公平锁:支持公平锁(多个线程按照获取锁的顺序排队)和非公平锁。
  • 可重入锁:Redisson 支持可重入锁(Reentrant Lock),即同一个线程可以多次获取同一把锁,而不会发生死锁。
3. Redlock 分布式锁

目的是在一个分布式环境中,使用多个 Redis 实例来实现一个高可用的分布式锁。

  • 多实例加锁:假设有 5 个 Redis 节点(推荐奇数个节点,至少 3 个)。在每个节点上执行 SETNX 操作。
  • 多数派锁定:如果客户端能在大多数节点(至少 3 个节点)上成功加锁,并且加锁操作的总耗时小于锁的过期时间,则认为加锁成功。
  • 解锁:当任务执行完毕后,客户端需要在所有节点上解锁
  1. 优点: 容错性强:即使部分 Redis 节点宕机,只要大多数节点成功加锁,仍可以认为加锁成功。 可靠性高:相比单个 Redis 实例的锁,在 Redis 实例出现网络分区或节点故障时,Redlock 能提供更高的可靠性。
  2. 缺点: 实现复杂,需要维护多个 Redis 实例。 因为需要在多个节点上执行锁定操作,性能较 SETNX 和 Redisson 略低。

Spring 什么时候初始化 Bean

Spring 默认在容器启动时(应用启动时)初始化单例 Bean,使用懒加载时则在第一次使用时才初始化。

AOP 的底层原理

AOP(面向切面编程)通过动态代理机制实现。Spring 使用 JDK 动态代理(基于接口)和 CGLIB 动态代理(基于类)来实现切面逻辑,将横切关注点(如日志、事务)分离出来。

计网的分层

计算机网络通常分为五层:应用层、传输层、网络层、数据链路层和物理层。在 OSI 七层模型中,多了表示层和会话层。

HTTP 和 HTTPS 属于哪一层

HTTP 和 HTTPS 属于应用层。

TCP 和 UDP 属于哪一层,TCP 如何实现可靠连接

TCP 和 UDP 属于传输层。TCP 通过三次握手建立连接,通过确认应答机制、超时重传、流量控制、拥塞控制等手段保证连接的可靠性。

以下是对你提供问题的简要解答:

线程池拒绝策略

当线程池中的任务队列已满且所有线程都在忙碌时,会触发拒绝策略,主要有四种常见的拒绝策略:

  • AbortPolicy:默认策略,直接抛出 RejectedExecutionException 异常,阻止系统正常工作。
  • CallerRunsPolicy:由提交任务的线程来执行该任务,降低任务的提交速度,减轻线程池的负担。
  • DiscardPolicy:直接丢弃无法处理的任务,不抛异常。
  • DiscardOldestPolicy:丢弃任务队列中最旧的任务,然后尝试重新提交当前任务。 开发者也可以通过实现 RejectedExecutionHandler 接口自定义拒绝策略。

让我做一个订单搜索怎么做,通过商品名搜索订单

在 MySQL 中可以通过 全文索引(Full-Text Index)来提高文本搜索效率。创建全文索引的步骤:

  • 首先,确保数据库表的存储引擎为 InnoDB 或 MyISAM。
  • 对 商品名 字段创建全文索引:
  • 然后使用 MATCH() 和 AGAINST() 函数来搜索商品名匹配的订单:通过这种方式,MySQL 会使用索引加速商品名的模糊匹配搜索。

G1 怎么设置它的区大小

G1 GC(Garbage First Garbage Collector)中的堆内存分成了多个相同大小的 Region。这些 Region 的大小可以通过 JVM 参数配置:

  • -XX:G1HeapRegionSize=n:设置每个 Region 的大小,取值范围是 1MB 到 32MB,必须是 2 的幂。默认大小根据堆的大小自动确定。 G1 的区大小越大,垃圾回收的开销越小,但可能会造成内存浪费。

单机为什么用redis缓存?

  1. redis的读写比mysql快很多,基于内存、数据结构优化、基于单线程;
  2. 对于变动少、查询时间长的数据是比较合适放在redis中

如何解决redis和mysql双写一致性问题

  1. 旁路缓存策略(CashAside方法)

一般在项目中都是此案用旁路缓存策略,具体思想是先更新数据库,再删除缓存。那么就有两个问题

(1)为什么不是先更新数据库,再更新缓存。假设我们有两个线程A和B,分别执行更新数据库、更新缓存,两个操作,如果是顺序执行,自然是没有问题;如果是两个线程同时执行,考虑网络等问题,会出现

A更新数据库,B更新数据库,B更新缓存,A更新缓存,这样数据库就是B的数据,缓存是A的数据。这样读取的就是脏数据,如果是删除缓存,就不会出现这个问题。而且写的操作消耗IO也比较多,不推荐这个。

(2)为什么不能先删除缓存,再更新数据库尼?继续考虑这样的场景,A线程:写操作,需要1.删除缓存;2.更新数据库; B线程:读操作,1.查询缓存 2. 若缓存未命中,查询数据库并更新缓存。这样的话,A删除缓存后,B执行完,读取缓存,缓存未命中,更新缓存,A再更新数据库。这样数据库和缓存的数据就不一致了。

(3)当然先更新数据库、再删除缓存也存在很多问题:

  1. A:更新数据库,删除缓存;B:查询缓存,缓存未命中查询数据库,更新缓存。B查询缓存未命中,查询数据库为10,准备写入缓存时,A线程来了,更新数据库为20,删除缓存一气呵成,然后B再更新缓存为之前的10,也有数据不一致的问题,但是写入缓存只有几毫秒的时间,这种情况下需要更新数据库和删除缓存,很难得。所以是弱一致性。
  2. 如果删除数据库失败了怎么办?引入延迟双删操作,就是1.更新数据库,2.删除数据库3.定时任务,过几百毫秒后再次尝试删除数据库。目的是删除缓存中可能出现的旧数据。或者失败重试机制,或者监听binlog数据变更情况,异步删除。也就是引入多次删除的策略,强制刷新缓存。

缓存击穿、缓存穿透、缓存雪崩分别对应什么场景?

  1. 缓存击穿:hot key失效,由于采用先更新数据库,再删除缓存的操作,所以大量的操作会查询数据库,更新缓存,所以我们可以加锁,让第一个获得互斥锁的线程,查询数据库,更新缓存。其他的线程重试,看看缓存是否更新了,但是这样就会有大量的线程空转,浪费资源。所以可以采用逻辑删除+异步更新。给hot key设置逻辑过期时间,每次获取hot key都检查是否过期,如果过期,开启一个线程异步更新,这个线程和其他线程正常返回老的数据即可,但是这样也有数据不一致的情况,但是资源消耗很少。
  2. 缓存穿透:查询的数据,压根在缓存和数据库中不存在,属于恶意访问。所以最简单的直接记录key和value,返回null值,但是这样会增加缓存压力。所以可以在参数层做校验,将所有可能的参数的hash到布隆过滤器,这样可以极大的防止无效的访问,但是也存在的误判率,比如你的布隆过滤器开的长度很小,参数又多,直接全为1了,布隆过滤器就失效了。所以在分布式架构中,对这种高QPS的请求做一定的限流,做好预警的工作。
  3. 缓存雪崩:大量key同时失效或者redis服务宕机。减少key,采用更多的静态化页面。给key设置不同的预期过期时间。采用多级缓存机制,L2Cache机制(本地缓存之王Caffine+redis)。构建redis服务集群。

redis为什么快

  1. 内存
  2. 高效的数据结构
  3. 单线程
  4. IO多路复用

https://www.cnblogs.com/coderacademy/p/18099027

redis的数据结构和持久化策略

接口幂等性

https://www.cnblogs.com/coderacademy/p/18082540

  • UUID,雪花算法,自定义唯一的标识符
  • 业务判断,更新论文的审核状态,某个时间是从未批改改为已经审核,update 强制让status=1
  • 兜底的话,就是定时查询,及时更新状态

MQ如何解决消息堆积问题

  • 引入惰性队列,接收到消息后直接存入磁盘而非内存,消费者消费需要从磁盘加载到内存中
  • 支持百万级别的消息存储

超时消费

  • 延迟队列

ES

什么是倒排索引

  1. 正排索引就是根据文档查找词条,判断文档中是否有该词条,不适合模糊查询。
  2. 倒排索引就是根据分词的结果(词条)来查询文档,拿到文档id后到正向索引中查找文档
  3. 常用的分词器是IK分词器,支持扩展词典,

Redis集群

全部评论
无论最终是国企还是私企,都希望自己健健康康,开开心心
4 回复 分享
发布于 2024-11-08 21:42 上海
加油加油
点赞 回复 分享
发布于 2024-11-27 17:09 陕西
谢谢佬
点赞 回复 分享
发布于 2024-11-19 10:58 河北

相关推荐

1、OPPO面试经验OPPO后端开发岗位总共分为1轮笔试+2轮技术面试+1轮hr面试。笔试包含单选和多选,注意java后端开发也会考一些C++的知识,比如指针、数组、构造函数和析构函数、虚函数等,可适当补充点知识。编程题总共3道,一般比互联网大厂简单,第一题暴力模拟即可,第二题稍微加点优化,第三题记录状态的dp。程序猫当时A了2题,通过了筛选,因此笔试方面小伙伴压力无需太大。一面实验室项目拷打;超卖问题怎么解决的?怎么保证秒杀的性能,有没有其它方案?消息重复消费、消息丢失,有考虑过吗?幂等具体怎么做的?优惠券分发怎么解决单条消息消费时间过长问题?为什么使用redisson,红锁是什么?讲一下java内存区域?hashmap和concurrenthashmap的区别,后者怎么保证的线程安全性,他们能插入null吗?讲一下AOP及其原理?二面实验室项目拷打;布隆过滤器会误判吗,能删除元素吗,要删怎么办?有没有遇到过数据倾斜问题,怎么解决的?为什么选择murmurhash?其它hash算法有对比过吗?结算逻辑怎么做的?极端情况下redis宕机,你的程序会出错吗?假如我想完成能叠加优惠券的结算,满足优惠券规则的情况下尽可能优惠最大金额,你会怎样设计?接口和抽象类的区别?new String("hello")会创建几个对象?hr面介绍一下你的竞赛你原生家庭对你的影响是什么你自己的优缺点你大学期间最有成就感的事情如果老板不给你派活,你会怎么样如何平衡工作和生活总结OPPO一面二面压力都不会很大,面试官很和善,不会压力人,问的问题也都不会很偏很怪。一般流程就是 自我介绍 + 问项目 + 场景 + 适当的八股,两次面试都是这个流程,无手撕。手撕比较差的伙伴可以好好准备下项目和八股,有很大机会。求关注,现在关注,以后就是老粉了,其它问题欢迎留言--------------------------------------下一期OPPO筛简历玄学,双九被刷(二)2、OPPO暑期实习待遇及转正情况;美团OC,只因这两个项目(一) 1、 超适合实习的项目推荐;
点赞 评论 收藏
分享
04-25 16:04
已编辑
深圳大学 Java
一面1. 为什么从腾讯离职2. 问实习做的模块本人的职责3. 问实习经历写的SQL优化,有没有考虑别的方案4. 联合索引在匹配的时候要考虑什么,答最左前缀法则和索引跳跃扫描5. 数据量变成原来十倍怎么办6. 有没有用过ES7. 怎么利用Redisson解决重复调度8. 了解过看门狗机制吗9. 如果续锁失败怎么办10. 校园经历的技术社团的职务干了什么11. 团队成员技术方案不一致怎么处理12. 反问,业务:基础平台中台,也有下沉的业务需求包括知识分享和直播;转正机会:往年60%,不区分日常和暑期,有三到四面;对实习生有什么期待,觉得煮波能胜任嘻嘻—————————分割线—————————二面1. 问实习做的定时任务,有一块没讲明白2. 线程池参数3. 怎么配置线程数4. 为什么CPU密集用多进程,IO密集用多线程,面试官给我解释说CPU密集也可以用多线程,多进程是为了防止任务崩溃影响其他任务,后来搜了一下原来是Python有GIL,多线程利用不了多核CPU,Java还是可以的5. 有没有听说过英特尔宣传自己是几核几线程,是什么意思,没听过(乐6. 你看看自己电脑是多少核,真的有这么多核吗,我说12个,细想难道利用了什么虚拟化技术让我们用起来比真的核数要多吗(悬疑7. 那你讲下什么叫虚拟化,讲了下虚拟机和Docker8. 你们这个特色班有什么特色9. 有没有用过AI辅助编程,有的兄弟有的10. 反问,业务,有什么建议:补好操作系统基础(太搞了
查看40道真题和解析
点赞 评论 收藏
分享
04-02 11:15
武汉大学 后端
分享面经,积攒好运🙏一面见之前的帖子3.10二面(过)自我介绍你们实验室做什么项目?你这个用布隆过滤器替代分布式锁访问数据库提升QPS的,介绍一下Redisson的底层是什么样的?你这个短链接是怎么生成的?有没有了解过别的生成算法开放题:我现在要提升你这个系统的QPS,你怎么从0开始设计?你说加机器,那你数据库支持水平拆分吗介绍一下这个ShardingSphere的原理?你有没有了解过逻辑sql怎么转真实sql的?ShardingSphere支持自动迁移数据吗?如果我使用了order by,那ShardingSphere会这么处理?查32个表吗?讲一下你认为的项目亮点你说一下这个读写锁的应用场景,我感觉不需要啊?Redisson这个读写锁是什么原理你知道吗?如果我发一个消息到MQ,十分钟后才被消费,怎么办?期间分组被改了怎么办?你这个RPC介绍一下你介绍一下这个自定义协议,为啥要自定义协议?头部有哪些字段?你用的什么网络框架?你知道netty是哪种网络模型吗?阻塞/非阻塞?同步/异步?Socket用过吗?说一下系统调用是什么?MySQL索引为啥用b+树?redis单线程,为什么还这么快?大模型用过吗?除了工作部分,还用大模型做些什么?手撕:布隆过滤器3.13三面(挂)自我介绍你的项目的技术难点在哪里?你数据表是怎么设计的?表里的索引怎么设计的?缓存空间有多大(?)你怎么统计用户的访问数据?用消息队列?消息队列会阻塞吗?就是满了怎么办?(?)短时间内大量请求打满消息队列怎么办?(答了扩容+加消费者)如果是集群,负载均衡你会怎么设计?讲一下一致性哈希讲一下你这个重试策略数据库热点问题你怎么解决?慢sql问题你怎么解决?你分析过慢sql吗?explain?我设计的系统如果想接入微信扫码登陆,你会怎么做?了解过微信支付宝的授权登录协议没有?手撕:sql:抖音活跃用户分析(完全没准备sql,写的一坨)手撕:128. 最长连续序列
点赞 评论 收藏
分享
评论
32
156
分享

创作者周榜

更多
牛客网
牛客企业服务