首页
题库
公司真题
专项练习
面试题库
在线编程
面试
面试经验
AI 模拟面试
简历
求职
学习
课程
专栏·文章
竞赛
搜索
我要招人
发布职位
发布职位、邀约牛人
更多企业解决方案
在线笔面试、雇主品牌宣传
登录
/
注册
猿二哈
深圳大学 计算机类
发布于广东
关注
已关注
取消关注
@可拟雀在大厂:
美团暑期后端实习面经解析: 拷打项目细节
嗨~我是可拟雀,一个后端开发工程师,毕业于某985大学,目前供职于bat某大厂核心部门后端。每天分享最新面经答案,希望在大环境不好的当下能帮到你,让你多积累面试经验。需要内推或者面经合集请评论哦。1.介绍一下redisson分布式锁?答:Redisson是一个基于Redis实现的Java分布式对象存储和缓存框架,它提供了丰富的分布式数据结构和服务,如分布式锁、分布式队列、分布式Rate Limiter等。其中,Redisson的分布式锁是一种重要的功能,主要用于在分布式系统中实现互斥性,保证在任意时刻只有一个线程能够持有锁。在Redisson中,使用key来作为是否上锁的标志。当通过getLock(String key)方法获得相应的锁之后,这个key即作为一个锁存储到Redis集群中。在接下来如果有其他的线程尝试获取名为key的锁时,便会向集群中进行查询。如果能够查到这个锁并发现相应的value的值不为0,则表示已经有其他线程申请了这个锁同时还没有释放,则当前线程进入阻塞;否则由当前线程获取这个锁并将value值加一。如果是可重入锁的话,则当前线程每获得一个自身线程的锁,就将value的值加一,而每释放一个锁则将value值减一,直到减至0,完全释放这个锁。Redisson分布式锁具有一些重要的特性。首先,它支持锁的超时时间,这意味着如果一个线程在持锁期间挂掉了而没主动释放锁,那么通过超时时间可以保证该线程在超时后可以释放锁,这样其他线程才可以继续获取锁。其次,Redisson提供了可重入锁、公平锁等常用的分布式锁,还支持异步执行、锁的自动续期、锁的等待等特性。此外,由于Redis是缓存型数据库,拥有很高的性能,因此Redisson的加锁和释放锁开销较小,并且能够很轻易地实现分布式锁。在使用上,Spring Boot项目可以方便地整合Redisson,通过添加Redisson依赖和配置RedissonClient客户端,就可以在项目中使用Redisson的分布式锁功能。2.redission分布式锁底层如何实现答:Redisson分布式锁底层实现主要依赖于Redis的特性和命令,结合Redisson的客户端库进行封装和优化。以下是Redisson分布式锁底层实现的大致原理:Redis数据结构选择:Redisson的分布式锁主要使用Redis的字符串(String)数据结构来存储锁的信息。每个锁在Redis中对应一个特定的key,该key的值用来表示锁的状态。加锁机制:当客户端尝试获取锁时,Redisson会向Redis发送一个SET命令,这个命令会尝试将锁对应的key设置为一个随机的UUID值,并设置过期时间(TTL)。同时,这个SET命令会带上NX(如果key不存在才设置)和PX(设置key的过期时间,单位为毫秒)参数。如果SET命令执行成功,表示客户端成功获取到了锁。这个UUID值作为锁的持有者标识,用于后续的解锁操作。如果SET命令执行失败(即key已经存在),说明锁已经被其他客户端持有,当前客户端需要等待或者返回失败。锁的可重入性:Redisson支持可重入锁,即同一个线程可以多次获取同一个锁而不会产生死锁。在Redisson中,当一个线程多次获取同一个锁时,它会在Redis中对应的key的value上增加重入次数,每次释放锁时,重入次数减一,直到重入次数为0时,才真正释放锁。锁的自动续期:为了避免客户端在持有锁期间因为网络问题或GC等原因导致与Redis服务器的连接断开,Redisson提供了锁的自动续期机制。当一个客户端获取到锁后,它会启动一个后台线程,定时向Redis发送命令延长锁的过期时间。解锁机制:当客户端需要释放锁时,它会向Redis发送一个Lua脚本,这个脚本会检查当前客户端是否持有锁(即比较UUID值),并删除对应的key,从而实现解锁。如果客户端在持有锁期间崩溃,由于设置了锁的过期时间,锁最终会自动释放,避免死锁。公平锁实现:Redisson也支持公平锁,它通过Redis的有序集合(Sorted Set)数据结构来实现。当多个客户端请求锁时,它们会在有序集合中按照请求的顺序排队,Redis会根据集合中元素的顺序来决定哪个客户端能够获取到锁。分布式环境下的安全性:Redisson的分布式锁实现考虑了分布式环境下的安全性问题。例如,它使用UUID作为锁的持有者标识,确保每个锁只能被一个客户端持有;同时,通过Lua脚本原子性地执行加锁和解锁操作,避免在并发环境下出现竞态条件。3.基于setnx实现的分布式锁的缺点有哪些?答:基于SETNX实现的分布式锁虽然是一种常用的解决方案,但也存在一些明显的缺点。以下是这些缺点的主要方面:单点风险:SETNX实现的分布式锁存在单点风险。如果存储分布式锁的Redis节点(或称为key)挂掉,就可能发生丢锁的情况。一旦丢锁,就可能导致多个客户端同时持有锁,从而使得分布式锁失效。锁释放问题:SETNX本身只提供了加锁的机制,对于锁的释放通常依赖于额外的逻辑。例如,一个常见的做法是在业务逻辑完成后使用DEL命令删除锁。然而,如果持有锁的客户端在释放锁之前崩溃或网络中断,那么这个锁就可能永远不会被释放,造成死锁。此外,如果锁的释放逻辑没有正确实现,也可能导致锁的误释放或重复释放。不可重入性:基于SETNX实现的分布式锁通常不具有可重入性。可重入锁允许同一个线程多次获取同一把锁,而不会造成死锁。然而,使用SETNX实现的锁通常不支持这种特性,可能导致同一线程在多次获取锁时发生冲突。性能问题:在高并发场景下,基于SETNX实现的分布式锁可能会成为性能瓶颈。由于每次加锁和解锁都需要与Redis进行网络通信,这可能成为系统的瓶颈,尤其是在锁竞争激烈的情况下。缺乏公平性:SETNX实现的分布式锁通常不提供公平性保证。公平性意味着等待时间最长的客户端应该优先获得锁。然而,基于SETNX的实现通常是基于先到先得的原则,可能导致某些客户端长时间无法获得锁。4.基于redis如何实现可重入的分布式锁答:基于Redis实现可重入的分布式锁,需要确保同一个线程或进程能够多次获取同一把锁而不会造成死锁,并且在释放锁时能够正确计数和解锁。以下是一个基于Redis实现可重入分布式锁的基本思路:锁的数据结构:使用Redis的哈希结构(Hash)来存储锁的信息。每个锁对应一个哈希表,哈希表的key是锁的标识(例如锁的名称),哈希表的value是一个包含多个字段的映射,其中至少包含以下字段:lockCount:表示当前锁被持有的次数(可重入次数)。ownerId:表示当前持有锁的客户端的唯一标识(例如线程ID或进程ID)。expireTime:表示锁的过期时间,用于防止客户端崩溃导致的死锁。加锁:客户端尝试获取锁时,首先检查Redis中是否存在对应的哈希表。如果不存在,则创建一个新的哈希表,并设置lockCount为1,ownerId为当前客户端的唯一标识,并设置一个合理的expireTime。如果已经存在,则检查ownerId是否与当前客户端的唯一标识相同。如果相同,表示当前客户端已经持有该锁,将lockCount加1。如果ownerId不同,表示锁被其他客户端持有,当前客户端需要等待或返回失败。锁的重入:当同一个客户端多次尝试获取同一把锁时,只需要检查ownerId是否匹配,并增加lockCount的值即可。5.项目的qps大概多少6.如何自己实现一个限流算法中的滑动窗口答:滑动窗口限流算法的思路在于维护一个时间窗口,并跟踪这个窗口内的请求数量。当新的请求到达时,算***检查当前窗口内的请求数是否已经达到限制。如果没有达到限制,则允许该请求,并将其添加到窗口中;如果已经达到限制,则拒绝该请求。随着时间的推移,窗口会向前滑动,旧的请求会逐渐移出窗口,从而为新的请求腾出空间。以下是实现滑动窗口限流算法的基本思路:定义窗口大小和请求限制:首先,确定滑动窗口的大小(例如,每秒钟、每分钟或每小时)以及窗口内允许的最大请求数。维护请求队列和时间戳:使用一个队列(如Python的deque)来存储窗口内的请求时间戳。当请求到达时,将其时间戳添加到队列中。检查并移除过期请求:在每次判断请求是否允许之前,检查队列中的最早请求是否已过期(即其时间戳是否超出了窗口的边界)。如果是,则将其从队列中移除。计算当前窗口内的请求数:队列中剩余的元素数量即代表了当前窗口内的请求数。判断请求是否允许:如果当前窗口内的请求数未达到限制,允许新请求,并将其时间戳添加到队列中;如果已达到限制,则拒绝新请求。处理窗口滑动:随着时间的推移,窗口会自动向前滑动,因为过期的请求会被移除。新的请求会填充到窗口的末尾。8.code:用两个队列实现一个栈,java语言9.jvm内存结构答:堆(Heap):这是Java虚拟机中的一块内存区域,所有线程共享。它主要用于存储对象实例和数组。堆被划分为年轻代、老年代和永久代(在JDK8中取消了永久代)。年轻代又被划分为Eden区、Survivor区(含:S0和S1)。默认情况下,年轻代和老年代的比例为1:2,即年轻代占整个堆空间的1/3,老年代占整个堆空间的2/3。方法区(Method Area):这也是线程共享的内存区域,主要用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。虚拟机栈(VM Stack):每个线程运行时所需要的内存称为虚拟机栈。每个栈由多个栈帧组成,对应着每次方法调用时所占用的内存,用于存储局部变量表、操作数栈、常量池引用等信息。程序计数器(Program Counter Register):用于记录下一条JVM指令的执行地址(如果正在执行的是本地方法则为空)。每一个线程都有一个程序计数器,当CPU因为时间片轮转等原因切换线程的时候,能保存当前线程的执行进度。同时,程序计数器不会存在内存溢出。本地方法栈(Native Method Stack):这也是线程私有的,用于支持native方法的执行。10.本地方法栈和虚拟机栈的区别答:本地方法栈(Native Method Stacks)与虚拟机栈(VM Stack)在Java虚拟机中各自扮演着重要的角色,但它们之间存在一些显著的区别。首先,两者的服务对象不同。虚拟机栈主要为Java方法(也就是字节码)服务,主管Java程序运行,保存方法的局部变量、部分结果,并参与方法的调用和返回。而本地方法栈则是为虚拟机使用到的本地(Native)方法服务。本地方法是用其他语言(如C、C++)编写的方法,通过Java Native Interface(JNI)调用。因此,本地方法栈的存在主要是为了支持本地方法的调用。其次,两者在结构上也有所不同。虚拟机栈是每个线程创建时都创建的,内部保存的单位是栈帧,对应一次次方法调用,其生命周期与线程一致。而本地方法栈与虚拟机栈一样,也是线程私有的,每个线程都有一个本地方法栈。这意味着每个线程都有自己独立的本地方法栈和虚拟机栈,它们之间进行独立的分配和释放。最后,两者在异常处理上也有所区别。与虚拟机栈一样,本地方法栈也会在栈深度溢出或者栈扩展失败时抛出异常。具体来说,当线程请求的栈容量超过固定大小时,会抛出StackOverflowError异常;而当没有足够的内存进行动态拓展时,会抛出OutOfMemoryError错误。11.类加载的过程答:类加载的过程在Java中是一个复杂且重要的机制,它确保了类的正确性和安全性。以下是类加载的详细过程:加载(Loading):加载阶段是类加载过程的起始点,主要由类加载器(ClassLoader)完成。类加载器通过类的全限定名查找并读取定义此类的字节码文件(.class文件)。这些字节码文件通常来自文件系统、网络或其他来源。读取到的字节码数据被加载到内存中,并且JVM会为此类创建一个Class对象,作为方法区中这个类的各种数据的访问入口。链接(Linking):链接阶段包括验证、准备和解析三个子阶段。验证(Verification):对加载的类的字节码进行校验,以确保其符合Java虚拟机规范。这个校验过程包括结构验证、语义验证、字节码验证和符号引用验证等,旨在确保类的正确性、安全性和一致性。准备(Preparation):为类的静态变量分配内存空间,并设置初始值。这些静态变量是类级别的变量,而非实例级别的变量。解析(Resolution):将常量池内的符号引用转换为直接引用的过程。这涉及到对其他类或接口的符号引用的解析,以确保它们可以被正确地引用和使用。初始化(Initialization):初始化阶段是类加载过程的最后阶段,在这个阶段中才真正开始执行类中定义的Java代码。如果类中有静态初始化块或静态变量赋值操作,那么这些操作将在初始化阶段被执行。JVM会保证一个类的<clinit>()方法在多线程环境中被正确地加锁和同步,确保类的初始化只会被执行一次。需要注意的是,类加载的过程并不是在程序一启动时就立即完成的,而是遵循“什么时候初始化”的原则进行加载。只有在首次主动使用某个类的时候(如创建类的实例、访问类的静态变量或静态方法、反射调用等),该类才会被初始化。12.redis常见数据结构(常见13.zset的底层数据结构(散列+跳表14.redis缓存穿透的原因和解决办法答:原因缓存穿透是指查询一个不存在的数据,由于缓存中也没有该数据,因此每次查询都会穿透到数据库层,从而给数据库带来压力。这种情况通常发生在恶意攻击或者系统bug时,大量查询不存在的数据,导致数据库负载过高。解决办法:布隆过滤器:布隆过滤器是一种空间效率极高的概率型数据结构,它利用多个哈希函数将元素映射到位图中。当查询一个元素时,可以通过检查对应的位图位置来判断元素是否存在。虽然布隆过滤器存在误判的可能性,即可能将不存在的元素误判为存在,但可以有效地过滤掉大部分不存在的元素,从而降低缓存穿透的概率。缓存空对象:对于不存在的数据,可以在缓存中存储一个空对象或者特殊标记,并设置较短的过期时间。这样,当再次查询这个不存在的数据时,可以直接从缓存中获取空对象或特殊标记,从而避免了对数据库的查询。但需要注意的是,这种方法可能会增加缓存的存储成本,并且如果大量查询不存在的数据,仍然可能给缓存带来压力。数据校验与过滤:在应用层增加数据校验逻辑,对于非法或不符合规范的请求进行过滤。这可以减少恶意请求对缓存和数据库的冲击。限流与熔断:通过限流策略限制对数据库的查询频率,当达到一定的阈值时,可以暂时熔断对数据库的查询,从而保护数据库免受过大的压力。这可以确保在高并发场景下,数据库不会因为过多的无效查询而崩溃。15.mysql索引底层数据结构 (b+树16.mysql对两个不同字段建立索引有几棵b+树答:在MySQL中,对于每一个独立的索引,都会有一棵B+树与之对应。所以,如果你对两个不同的字段分别建立了索引,那么你会有两棵B+树。每棵B+树都是根据该索引字段的值进行排序的。例如,假设你有一个表my_table,并且你对字段field1和field2分别建立了索引,那么:对于field1的索引,MySQL会维护一棵B+树,其中的节点按照field1的值进行排序。对于field2的索引,MySQL会维护另一棵B+树,其中的节点按照field2的值进行排序。这两棵B+树是独立的,互不干扰。当你根据field1进行查询时,MySQL会使用第一棵B+树;当你根据field2进行查询时,MySQL会使用第二棵B+树。17.mysql联合索引的最左前缀原理?答:MySQL的联合索引(也称为复合索引或多列索引)的最左前缀原理是指,当MySQL使用联合索引进行查询时,它会从联合索引的最左列开始匹配查询条件。只有当查询条件使用了联合索引的最左侧列时,索引才会被有效利用。具体来说,假设我们有一个联合索引 (a, b, c),这个索引是按照列 a、b 和 c 的顺序进行排序的。现在,我们考虑以下几种查询情况:单独查询列a:在这种情况下,查询条件使用了联合索引的最左列(列a),因此MySQL可以直接使用这个索引来快速定位到匹配的行。查询列a和列b:查询条件同时包含了列a和列b,这也满足了最左前缀原则,因为列a是联合索引的最左列。MySQL会利用这个联合索引来加速查询。查询列a、列b和列c:当查询条件包含了联合索引的所有列(列a、列b和列c)时,索引的使用效率是最高的,因为所有列都被用来定位数据。然而,以下情况则不会有效地利用联合索引 (a, b, c):只查询列b或列c:由于列b和列c不是联合索引的最左列,因此当查询条件只包含这些列时,联合索引不会被使用。MySQL会进行全表扫描或者尝试使用其他可能的索引(如果有的话)。最左前缀原则也适用于索引的列顺序。如果你有一个 (b, a, c) 的联合索引,那么它对于基于列 b 的查询是高效的,但对于基于列 a 的查询则不是,因为列 a 不是这个联合索引的最左列。18.col1=, col2 between可以用这个联合索引吗19.为什么不等于条件会导致索引失效20.你实习想做什么反问:部分与业务日常吗项目实习,类似日常两个队列咋实现一个栈哇 给我整不会了lc原题,有空做一下q1,q2,push x就往q1加x,然后把q2按顺序全部接到q1后面,然把q1,q2的指针交换, pop就从q2 poll一个原文传送门
点赞 29
评论 5
全部评论
推荐
最新
楼层
网易互娱
校招火热招聘中
官网直投
相关推荐
王阿清啊
昨天 18:17
已编辑
牛客运营
听劝,改简历不能改命,但能增加机会
简历很重要,不用多说,那应届生如何写好个人简历? 每天都会看到牛友们发帖求助,所以我们特意奉上简历法宝!首先记住以下思路其实道理都很简单,难在完全做到!学历、背景这些已经是客观事实,我们可以改变的就是“表达效果”同样一件事情,换一种表达方式则会达到不同的效果,让HR更能认定你的胜任能力!因此,牛客特意开放【简历点评】服务!限量免费使用,先到先得!我们会针对性提出优化建议,提高你的简历竞争力!同时还会根据简历内容,模拟面试押题,助你360度备战!扫码立即使用>>>PS:有任何疑问或建议,可在帖下留言~
点赞
评论
收藏
转发
已经不能更加糟糕了
05-21 17:29
广州大学 计算机类
小公司面经
4.21请你描述一些你的第一个项目。请问有没有缓存的使用经验?为什么使用redis,redis更快速的原因是什么?有没有部署上线过项目?有没有使用过dockerDocker 部署和 平常的部署的区别是什么?4.22Java 中重写和重载是否一样?其各自的意义是什么?了解过哪些 java web相关的框架Mybatis 有哪两种动态传参的方式?分别的意义是什么?使用 MySQL 以及 oracle 编写分页查询语句?线程池核心参数有什么?怎么设置相关的线程池参数?4.28用的是什么数据库语言?数据库有多少种索引?B 树 和 B+树之间有什么区别?有用linux上线过项目吗?linux中的常见指令...
投递Oracle等公司10个岗位 >
点赞
评论
收藏
转发
008号
04-03 12:44
嵌入式软件开发
双非一本25届想找嵌入式实习
麻烦大家帮忙看一下哪里需要修改的,谢谢!! #嵌入式实习生# #简历#
点赞
评论
收藏
转发
giovanniW
04-27 18:14
复旦大学 计算机类
双9但简历抽象,不知道该不该转go
研一,目前还在和组里搞科研,混了几个二作,预计还能继续混几个。此外简历上几乎是空着的,0实习0开发经历,有一些看起来还可以的国外lab,但不知道怎么优化简历。现在行情不好,想转开发写golang,但周围的朋友推荐我这个简历去搞嵌入式,大佬们觉得该怎么转方向呢?如果转golang有什么推荐的项目吗?在上海找实习到处碰壁,不知道怎么开始
点赞
评论
收藏
转发
拯救空军
今天 11:38
门头沟学院 电子信息类
如果延毕三个月,移动offer能保住吗?
如果延毕三个月,移动offer能保住吗?答辩有挂人指标,我在的那个组答辩主席每年都挂人,二辩要等到9月,9月才能拿到双证。哎,搞不懂盲审都过了为难一个学生干什么 #盲审过后你想做什么? #延毕#
点赞
评论
收藏
转发
点赞
收藏
评论
分享
回复帖子
提到的真题
返回内容
全站热榜
1
...
突然发现自己根本不喜欢互联网
4648
2
...
听劝,改简历不能改命,但能增加机会
4428
3
...
快手国际化 java一面 25届暑期
4208
4
...
25届秋招迫在眉睫但也不用太🍌🟢
3997
5
...
腾讯面王,挑战最多面试次数!十五面,六个事业群全涉及
3177
6
...
周一就入职了,go语言一点没学
3020
7
...
58同城面经
2910
8
...
暑期实习0 offer
2776
9
...
腾讯音乐offer啦,面经回馈一下大伙
2645
10
...
美团一面
2645
正在热议
#
牛客帮帮团来啦!有问必答
#
885555次浏览
13979人参与
#
机械制造薪资爆料
#
327291次浏览
3816人参与
#
晒一晒我的offer
#
3536862次浏览
55885人参与
#
大家都开始春招面试了吗
#
270837次浏览
3971人参与
#
金三银四,你有感觉到吗
#
336741次浏览
4295人参与
#
我发现了面试通关密码
#
358877次浏览
6745人参与
#
投了多少份简历才上岸
#
62302次浏览
994人参与
#
如何缓解入职前的焦虑
#
38792次浏览
392人参与
#
面试题刺客退退退
#
47367次浏览
872人参与
#
24届软开秋招面试经验大赏
#
1073885次浏览
17059人参与
#
25届如何提前做秋招准备?
#
6994次浏览
194人参与
#
0offer是寒冬太冷还是我太菜
#
435361次浏览
4988人参与
#
在国企工作的人,躺平了吗?
#
101113次浏览
1284人参与
#
我在牛爱网找对象
#
51801次浏览
343人参与
#
机械人,你的秋招第一份简历被谁挂了
#
34416次浏览
581人参与
#
求职遇到的搞笑事件
#
20136次浏览
293人参与
#
校招入职后的感受
#
57003次浏览
1040人参与
#
国企vs私企,你更想去?
#
26540次浏览
296人参与
#
实习与准备秋招该如何平衡
#
183757次浏览
3262人参与
#
荣耀求职进展汇总
#
75837次浏览
772人参与
牛客网
牛客企业服务