字节一面整理
时间:2025-6-17
1、实习+项目拷打
2、八股
进程间有哪些通信方式
管道、消息队列、信号量、信号、共享内存、socket套接字
如何使用两个栈实现一个队列
首先一个栈用来扮演入队列的功能,时间复杂度为O(1),另一个栈用来出队列,出队列,首先检查第二个栈有没有这个元素,如果有这个元素,就弹出这个元素,如果没有这个元素,那就将第一个栈的元素弹出,然后装入第二个栈,直到找个要弹出的元素,然后弹出,最多的时间复杂度为O(n)
出队的时间复杂度是多少
mysql的索引使用什么结构存储
B+树和B树有什么区别
mysql的事务隔离级别有哪些
什么是幻读,发生在什么隔离级别下
在同一个事务中,针对同一个表,读取的记录总数前后不一致,发生在读未提交,读已提交
redis的zset的底层结构
ZSet(有序集合)即SortedSet,是一个自动根据元素score排序的有序集合。它是一个可排序的set集合,在 Set 的基础上增加了一个权重参数 score,使得集合中的元素能够按 score 进行有序排列。底层实现有两种方式:当元素较少或总体元素占用空间较少时,使用压缩列表ZipList来实现;当不符合使用压缩列表的条件时,使用跳表SkipList+ 字典hashtable来实现。
ZSet具备下列特性:
-
可排序。根据score值排序,如果多个元素score相同 则会按照字典进行排序
-
元素不重复,member必须唯一。注意:集合成员是唯一的,但评分可以重复
-
查询速度快,也可以根据member查询分数
在 Zset 中,集合元素的添加、删除和查找的时间复杂度都是 O(logn),这得益于 Redis 使用跳表SkipList来实现 Zset。
因为ZSet的可排序特性,经常被用来实现排行榜这样的功能。 -
Redis ZSet 的底层实现为跳跃列表和哈希表两种,跳跃列表保证了元素的排序和快速的插入性能,哈希表则提供了快速查找的能力。
-
当元素数量不多时,HT和SkipList的优势不明显,而且更耗内存。因此zset还会采用ZipList结构来节省内存,不过需要同时满足两个条件:
- 元素数量小于zset_max_ziplist_entries,默认值128
- 每个元素都小于zset_max_ziplist_value字节,默认值64
ZipList是一种紧凑的、为节约内存而设计的顺序型数据结构,元素按照分数从小到大的顺序依次存储在压缩列表中。这种存储方式的优点在于内存使用效率极高,因为它不需要为每个元素额外分配指针空间,所有元素紧密排列在连续的内存区域,减少了内存碎片 。但由于其是顺序存储结构,在查找特定元素时,需要从表头开始逐个遍历节点,时间复杂度为 O (N),N 为压缩列表中的元素个数。当元素数量增多时,查找效率会显著降低。
底层数据结构:本质是一个数组,增加了列表长度、尾部偏移量、列表元素个数、以及列表结束标识,有利于快速寻找列表的首尾节点;但对于其他正常的元素,如元素2、元素3,只能一个个遍历,效率仍没有很高效。例如,假设有一个 ZSet 包含三个元素:{“apple”: 3, “banana”: 1, “cherry”: 2},在压缩列表中可能的存储形式为:[banana, 1, cherry, 2, apple, 3]。
在zset数据多的时候使用压缩列表有什么问题
ZipList是一种紧凑的、为节约内存而设计的顺序型数据结构,元素按照分数从小到大的顺序依次存储在压缩列表中。这种存储方式的优点在于内存使用效率极高,因为它不需要为每个元素额外分配指针空间,所有元素紧密排列在连续的内存区域,减少了内存碎片 。但由于其是顺序存储结构,在查找特定元素时,需要从表头开始逐个遍历节点,时间复杂度为 O (N),N 为压缩列表中的元素个数。当元素数量增多时,查找效率会显著降低。
如何生成一个分布式的全局唯一id
1.采用数据库ID生成策略
单独使用一个数据库实例,在这个实例中新建一个单独的ID表。通过插入一条记录来让数据库生成ID。
2.集群数据库生成ID
解决数据库单点问题,我们可以用一个数据库集群来生成ID。
3.使用UUID生成ID
UID有着全球唯一的特性,其实UUID是满足分布式ID的要求的
4.雪花算法(snowflake)
SnowFlake算法生成id的结果是一个64bit大小的整数
5.Redis ID生成器
这主要依赖于Redis是单线程的,所以也可以用生成全局唯一的ID。
使用set nx命令设计分布式锁会有什么问题
在使用SETNX时,可能会遇到锁失效的问题。例如,客户端获取锁后因网络延迟或业务处理异常导致锁超时释放,其他客户端可能误删不属于自己的锁。
可能问题:
- 锁超时:锁的有效期设置不合理,导致提前释放。
- 误删锁:未校验锁的持有者身份,直接删除锁。
1.为了防止锁永久占用,必须为锁设置一个合理的过期时间。
示例代码:设置锁并指定过期时间 SETNX lock_key "lock_value" EXPIRE lock_key 10 // 设置10秒过期时间
2.通过Redis事务或Lua脚本原子性操作,判断锁是否存在并删除,避免误删其他客户端持有的锁;
//Lua脚本示例:安全解锁
if redis.call("GET", KEYS[1]) == ARGV[1] then return redis.call("DEL", KEYS[1])
else return 0 end
3.引入唯一标识符(如UUID),在加锁和解锁时进行校验,确保锁的拥有者才能解锁。
4.锁失效问题的解决方案流程图
以下是解决锁失效问题的整体流程图,展示了从加锁到解锁的关键步骤。
graph TD;A[开始] -- 加锁 --> B{锁是否存在};B -- 是 --> C[返回失败];B -- 否 --> D[设置锁并指定过期时间];D -- 成功 --> E[执行业务逻辑];E -- 完成 --> F{是否持有锁};F -- 是 --> G[通过Lua脚本安全解锁];G -- 解锁成功 --> H[结束];F -- 否 --> H;
3、手撕
(1)给一个字符串,返回最长无重复字符的子串长度,如“abcdd”,结果为4
(2)在分布式系统设计两个接口:
①将一个长连接URL转换为短连接,如https://d.vofejfe.com/fjeo23jioejwre/index/jflsj转为https://df.com/G4vfd,域名固定,后五位为转换的短连接,每个字符范围为0-9、a-z、A-Z。
②通过短连接获取原始链接
不用写代码,说明数据存储结构、存储格式、接口功能。
时间:2025年6月27号
生活服务(一面,二面)
字节一面面经:
1自我介绍和拷打项目(主要问了订单下单流程) 项目聊了很长时间
2UDP和TCP的区别
3HTTP的三次握手和四次挥手
4mysql索引 和B+树
5解决复杂技术的经验
6算法题:股票差价和多次股票差价(第一个贪心算法+第二个开了一个数组累加)
一面已过,希望二面顺利
字节二面面经:
1.自我介绍加上项目,和一面差不多
2.聊在项目中的mysql使用
3.项目中使用redis的客户端,Jedis、Lettuce,(这个我当时答非所问了)
前面几点总共用时15分钟差不多就到算法题了
4.手写算法题(手写一个catch缓存,需要有过期时间、最大容量、容量达到最大时淘汰过期时间最长的)我当时写了40分钟左右
2025年6月9号
生活服务一面
- 哪个项目比较熟悉?
- 医疗平台项目是做什么的?有哪些模块,你负责的是哪个模块?
- 为什么采用基于DataBase级别的租户数据隔离?
- MySQL体检记录表结构设计?
5.MySQL索引数据结构?相比于其他数据结构的优势?B+树如何支持范围查询?
- B树 vs B+树
数据存储位置:在B树中,数据存储在内节点和叶子节点中,而在B+树中,数据只存储在叶子节点中,内节点仅存储索引。这使得B+树的内节点更加精简,有利于提高查询性能。
叶子节点的链表结构:B+树叶子节点按顺序连接成链表,这使得范围查询可以直接从头节点开始,沿着链表顺序遍历到尾节点,而B树没有这种结构。
- 哈希索引 vs B+树
哈希索引:哈希索引通常只适合等值查询,不能用于范围查询,而B+树不仅能支持等值查询,还能高效支持范围查询。
B+树:B+树适合于大规模数据存储,并能提供多种查询操作,包括等值查询(例如WHERE column = x
)、范围查询(例如WHERE column BETWEEN x AND y
)和前缀匹配查询(如LIKE
操作),此外,B+树的查询时间复杂度为O(log N),对于范围查询更是具有优势。
6. B+树和跳表的区别?为什么MySQL不用跳表?
跳表实在有序链表基础上增加了多级索引,通过多级索引位置的跳转,实现了快速查找元素。这样查找过程就非常类似于一个二分查找,使得查找的时间复杂度可以降低到O(log n)
B+树是一种自平衡的多路查找树,B+树的内部节点仅存储键值和指向子节点的指针,而叶子节点存储了数据的实际值。B+树的所有叶子节点通过指针链接成一个链表,因此支持高效的顺序访问。
- 结构差异:B+ 树是一种多路搜索树,每个节点可以有多个子节点,而跳表是一种基于链表的数据结构,每个节点只有一个下一个节点,但可以有多个快速通道指向后面的节点。
- 空间利用率:B+ 树的磁盘读写操作是以页(通常是 4KB)为单位的,每个节点存储多个键值对,可以更好地利用磁盘空间,减少 I/O 操作。而跳表的空间利用率相对较低。
- 插入和删除操作:跳表的插入和删除操作相对简单,时间复杂度为 O(logN),并且不需要像 B+ 树那样进行复杂的节点分裂和合并操作。
- 范围查询:B+ 树的所有叶子节点形成了一个有序链表,因此非常适合进行范围查询。而跳表虽然也可以进行范围查询,但效率相对较低。
因此,B+ 树和跳表不能简单地相互替换。在需要大量进行磁盘 I/O 操作和范围查询的场景(如数据库索引)中,B+ 树可能是更好的选择;而在主要进行内存操作,且需要频繁进行插入和删除操作的场景(如 Redis)中,跳表可能更有优势。
Redis是直接操作内存的、并不需要磁盘io;而MySQL需要去读取磁盘io,所以MySQL使用b+树的方式去减少磁盘io。B+树原理是 叶子节点存储数据、非叶子节点存储索引,每次读取磁盘页时就会读取一整个节点,每个叶子节点还要指向前后节点的指针,其目的是最大限度地降低磁盘io
数据在内存中读取 耗费时间是磁盘IO读取的百万分之一,而Redis是内存中读取数据、不涉及IO,因此使用了跳表,跳表模型是更快更简单的方式
7. 假如MySQL事务超时了, 如何排查?
- 检查和优化SQL查询
- 分析慢查询:使用
SHOW FULL PROCESSLIST
查看正在执行的事务,特别是那些执行时间较长的查询。 - 使用慢查询日志:开启慢查询日志(
slow_query_log
),并设置合适的慢查询时间阈值(long_query_time
),以便捕获可能引发超时的查询。 - 优化查询:对于发现的慢查询,进行优化,例如通过添加索引、优化查询逻辑、减少JOIN操作等。
- 检查和优化数据库配置
- 调整事务隔离级别:适当调整事务的隔离级别(例如,从
REPEATABLE READ
调整到READ COMMITTED
),这可以减少锁的竞争。 - 增加
innodb_lock_wait_timeout
:这个参数定义了在InnoDB存储引擎中事务等待锁的最大秒数。如果需要更长的等待时间,可以增加此值。 - 增加
max_execution_time
:对于某些长时间运行的事务,可以考虑设置max_execution_time
来限制单个语句的最大执行时间。
- 分析和解决锁争用
- 查看锁等待和锁冲突:使用
SHOW ENGINE INNODB STATUS
查看InnoDB的锁等待和锁冲突情况。 - 分析锁定资源:确定哪些表或行被锁定,并找出造成锁争用的原因,如是否有不必要的长事务未提交或回滚。
- 优化索引和表结构:确保所有被频繁访问的列都有合适的索引,避免全表扫描。
- 监控和日志记录
- 启用和查看错误日志:检查MySQL的错误日志文件,看是否有与事务超时相关的错误信息。
- 使用性能监控工具:利用如
Percona Monitoring and Management (PMM)
、MySQL Workbench
的Performance Dashboard等工具来监控数据库性能和事务状态。
8. MySQL update语句底层原理?
首先,它会解析SQL语句,特别是对给定的update语句进行深入解析,从而提取出表名、需要操作的字段(列名)、更新的具体值以及更新条件等信息。
其次,为了保证数据的一致性和完整性,update操作时会对相关表进行锁定,这可以是行锁或表锁,以防止在操作过程中数据被其他事务所修改。
接着,它会根据update语句中设定的条件,对数据库中的记录进行筛选,找出那些需要被更新的记录。
然后,对筛选出的记录,逐行进行字段的修改操作,也就是将原数据根据预先设定的计算表达式替换为新的数据。
最后,在update操作完成后,会释放锁,允许其他事务重新访问该表。同时,还会返回一个结果,显示本次操作影响了多少行数据。
9. Buffer Pool有哪些区域,分别是是干什么的?
Buffer Pool的结构:
9.1 数据页(Data Pages)
- 数据页是 Buffer Pool 的核心组成部分。
- 每一个数据页存储的是磁盘上某部分数据的内容,例如:
- 一个表的一部分行记录。
- 一个索引的一部分节点。
- 数据页是数据库中数据的基本存储单位(如 InnoDB 中的数据页大小一般为 16KB)。
9.2 内存块(Blocks)
- Buffer Pool 的内存被分割成一个个固定大小的内存块,每个块可以存放一个数据页。
- 可以把内存块想象成一个“空房间”,装载不同的数据页。
- 内存块由 Buffer Pool 统一管理,负责分配和回收。
9.3 控制块(Control Blocks)
- 每个内存块都有一个对应的控制块,用来记录与这个内存块相关的元数据。
- 控制块的作用类似于“身份证”,它记录了数据页的信息,包括:
- 数据页的 Page ID(页号)。
- 引用计数:记录数据页被访问的次数。
- 数据页的状态:比如数据是否被修改、是否在链表中。
- 链表指针:用于表示这个块在链表中的位置(比如自由链表、LRU 链表等)。
9.4 链表结构(Linked Lists)
Buffer Pool 中通过链表来管理 数据页的状态,主要有以下三种链表:
-
自由链表(Free List)
- 存储当前未分配的内存块(空闲块)。
- 当数据库需要加载新的数据页时,优先从自由链表中分配内存块。
- 如果自由链表为空,则需要从 LRU 链表中淘汰旧的数据页。
-
使用链表(LRU List)
- LRU(Least Recently Used)链表存储当前正在使用或最近使用过的数据页。
- 按照最近使用的时间排序,最近使用的页放在链表头部,最久未使用的页放在链表尾部。
- 当需要腾出空间时,优先从链表尾部淘汰最久未使用的页。
-
脏页链表(Flush List)
- 存储所有被修改过但尚未写回磁盘的数据页(即“脏页”)。
- 后台线程会定期扫描脏页链表,并将这些脏页写回磁盘以保持数据一致性。
Buffer Pool 中的页有三种状态:
- 空闲页:通过空闲页链表(Free List)管理。
- 正常页:通过LRU链表(LRU List)管理。
- 脏页:通过LRU链表和脏页链表(Flush List)管理。
10. Buffer Pool有什么机制能够保证不会因为一次大查询把所有的数据都替换掉?(不会)
通过 LRU算法 和 预读机制 来保证不会因为一次大查询把所有的数据都替换掉。
10.1 LRU算法
LRU(Least Recently Used)算法是Buffer Pool管理缓存页的主要机制。LRU算法将最近最少使用的页移到缓冲池的末尾,当缓冲池满时,最先被淘汰的是这些页。这种机制确保了最近频繁访问的数据不会被轻易淘汰,从而保证了性能的稳定性12。
10.2 预读机制
预读机制是指磁盘读写不是按需读取,而是按页读取,通常一次至少读一页数据(一般是4K)。如果未来要读取的数据就在页中,就能够省去后续的磁盘IO,提高效率。这种机制利用了数据的局部性原理,即使用一些数据时,大概率会使用附近的数据,从而减少磁盘IO1。
10.3 脏页刷新机制
当Buffer Pool中的数据被修改时,这些页会被标记为“脏页”。 后台线程 会定期将这些脏页刷新到磁盘,确保数据的一致性。这种异步刷新机制避免了因为一次大查询就替换掉所有数据的情况
11. 项目中多线程如何使用的?线程池参数有哪些?执行原理?拒绝策略?
- 通过使用多线程,可以将一个长时间运行的任务分解成多个子任务,每个子任务由一个独立的线程执行,从而减少单个任务的执行时间。例如,在图像处理、数据分析、科学计算等场景中.
线程池的主要参数包括:
- corePoolSize:线程池核心线程数,即使线程处于空闲状态也不会被销毁。
- maximumPoolSize:线程池能够容纳的最大线程数。
- keepAliveTime:非核心线程的空闲存活时间。
- unit:时间单位。
- workQueue:任务队列,用于存储等待执行的任务。
- threadFactory:用于创建新线程的工厂,可以设置线程名、是否为守护线程等。
- handler:拒绝策略,用于处理无法执行的任务
线程池的执行原理:
线程池通过复用已创建的线程来减少线程创建和销毁的开销。用户提交任务到线程池后,线程池中的线程会从任务队列中取出任务执行。当所有核心线程都在忙碌时,新任务会被放入任务队列中等待执行;如果任务队列已满且所有核心线程都在忙碌,则会创建新的非核心线程来处理任务。当线程池中的线程数量超过核心线程数且所有非核心线程都在忙碌时,会根据拒绝策略处理无法执行的任务。
常见的拒绝策略包括:
- CallerRunsPolicy:由调用者所在线程(即提交任务的线程)直接执行被拒绝的任务。
- AbortPolicy:直接丢弃任务并抛出
RejectedExecutionException
异常。 - DiscardPolicy:直接丢弃任务,不抛出异常。
- DiscardOldestPolicy:丢弃队列中最老的未处理任务,然后尝试重新提交当前任务
12. 如何保证线程池中的任务不丢失?
- 将任务存储在外部持久化存储(如消息队列、数据库)中,而不是仅存在于内存中的线程池队列。
- 在服务运行过程中,将线程池中的关键数据(如任务的状态、中间结果)定期保存到数据库或文件系统中。
- 实时监测线程池的状态,并在服务重启时根据监测到的状态进行恢复。
13. 项目中多个业务公用一个线程池还是分多个线程池?分析这两个方案的优劣?
共用线程池的优缺点
优点:
- 资源利用率高:共用一个线程池可以减少线程的创建和销毁开销,提高资源利用率,减少系统开销。
- 管理简便:统一管理可以简化配置和维护工作,减少代码复杂度12。
缺点: - 任务干扰:不同业务的任务可能会相互干扰,影响任务的独立性和执行效率。
- 调试困难:当出现问题时,难以定位具体是哪个业务的问题,调试和维护难度较大
分多个线程池的优缺点
**优点: - 任务独立性:每个业务使用独立的线程池,任务之间互不干扰,保证任务的独立性和完整性12。
- 错误排查:当出现问题时,可以快速定位到具体业务,便于调试和维护12。
**缺点: - 资源浪费:每个业务都有自己的线程池,可能会导致资源浪费,增加系统开销12。
- 配置复杂:每个业务需要单独配置线程池,增加了配置和管理的复杂度12。
14. 如果线程池使用后,没有达到预期效果,你会如何排查?
日志分析:通过分析日志文件,可以了解线程池的工作状态和任务执行情况。例如,可以通过日志分析工具查看线程池的日志,找出任务执行缓慢或失败的原因1。
性能监控:使用性能监控工具(如JProfiler、VisualVM等)监控线程池的性能指标,如线程池的活跃线程数、任务队列长度、任务执行时间等。这些指标可以帮助识别瓶颈和问题所在2。
代码审查:检查线程池的配置参数,如核心线程数、最大线程数、保持存活时间等,确保这些参数设置合理。同时,检查任务的提交方式和方法,避免不必要的线程创建和销毁2。
任务分析和优化:分析任务的执行时间和资源消耗,优化任务的执行逻辑和算法,减少不必要的计算和等待时间。对于长时间运行的任务,可以考虑将其拆分成多个小任务并行处理1。
拒绝策略和异常处理:检查线程池的拒绝策略和异常处理机制,确保在任务无法执行时能够合理处理,避免系统崩溃或数据丢失
15. 如何排查java中的死锁?
方法一
步骤一:使用jsp查找程序进行
步骤二:使用jstack查看线程堆栈信息
方法二
通过jdk提供的工具jconsole排查死锁问题
jconsole:jdk提供的一个可视化的工具,方便排查程序的一些问题,如:程序内存溢出、死锁问题等等。
方法三
通过jdk提供的工具VisualVM排查死锁问题
切换到"线程"窗口
手撕:二叉树最近公共祖先
反问:部门业务,简历有什么可以优化的地方(回答简历亮点不够突出,没有亮点,写的比较简单,最好突出一些自己负责的部分)
二面(6月12日)
- 海洋物联网平台是做什么的?
- 如何接入多源异构的设备数据?描述一下数据结构之间有什么差异?
由于不同设备的数据格式可能不同,如关系型数据库、NoSQL数据库、CSV文件、XML文件等,需要使用数据转换工具和中间件将不同格式的数据转换为统一的格式。这包括数据清洗、格式转换和数据映射,以确保数据的一致性和可用性
3.你提到反射,Java中实现反射有哪几种方式?
通过类的.class属性:这是最直接的方式,通过类的.class属性可以直接获取到该类的Class对象。例如,Class<?> c = MyClass.class
通过Class.forName(String className)方法:这种方法需要传入类的全限定名(包括包名),然后返回该类的Class对象。例如,Class<?> c = Class.forName("com.example.MyClass")
。
通过对象实例的getClass()方法:通过创建对象实例后调用该实例的getClass()
方法获取Class对象。例如,MyClass obj = new MyClass(); Class<?> c = obj.getClass();
4. CgLib和JDK动态代理差异?
答:JDK 动态代理是 Java 标准库提供的代理方式,要求目标类必须实现接口。它通过反射生成代理类,实现接口并转发方法调用。缺点是性能略低,且不能代理没有接口的类。
而 CGLIB 动态代理是通过继承目标类的方式生成子类,重写方法实现增强。它不依赖接口,性能更优,但不能代理 final 类和 final 方法。
在 Spring AOP 中,两者都被使用,默认是 JDK 动态代理,如果目标类没有接口或设置了 proxy-target-class=true,则使用 CGLIB。
JDK 动态代理需要“接口”。代理类并不会继承目标类,而是实现目标类实现的接口。
代理类:
特点:
- 依赖接口,目标类必须实现接口
- 底层通过 反射+字节码拼接生成代理类
- 性能不如 CGLIB(因为反射调用有损耗)
- 优点:标准、安全、稳定
CGLIB 采用的是 继承的方式,代理类是目标类的子类,通过继承+重写来实现“增强”
特点: - 不依赖接口,可以代理普通类
- 通过继承生成子类的方式创建代理类
- 性能优于 JDK 动态代理(不走反射,调用快)
- 目标类不能是 final,方法不能是 final/static
- 存在类加载问题(和 Spring AOP 结合时可能踩坑)
-
数据是如何存储的?按照每半年存储,如果我想查6~8月数据,如何查询?查询出来的数据如何计算?
-
MySQL索引有哪些?用过MySQL的全文索引吗?(没有)举出索引和非聚簇索引的区别?
B-Tree索引: 这是最常用的索引类型,适用于全键值、键值范围或键值前缀查找。 适用于等值查询、范围查询和排序操作。 默认情况下,InnoDB和MyISAM存储引擎都使用B-Tree索引。
全文索引(FULLTEXT): 用于对文本内容执行全文搜索。 主要用于InnoDB和MyISAM存储引擎。
哈希索引: 基于哈希表实现,提供等值比较的快速访问。 不适合范围查询,因为哈希索引的查找效率依赖于键的哈希值的一致性。 主要用于Memory存储引擎。
空间索引(Spatial Index): 用于地理空间数据类型,如POINT、LINESTRING、POLYGON等。 主要用于MyISAM和InnoDB存储引擎。
聚簇索引与非聚簇索引的区别
聚簇索引(Clustered Index): 在InnoDB存储引擎中,聚簇索引决定了表中数据的物理存储顺序。 一个表只能有一个聚簇索引。 聚簇索引通常基于主键创建,如果没有定义主键,则基于第一个唯一非空索引创建。 数据行直接存储在聚簇索引的叶子节点中。
非聚簇索引(Non-Clustered Index): 非聚簇索引的叶子节点包含的是对应数据行的主键值,而不是数据行本身。 一个表可以有多个非聚簇索引。 数据行本身存储在数据文件中,而非聚簇索引的叶子节点包含的是指向数据行的指针。 非聚簇索引可以基于表中的任何列创建,包括非主键列。 -
假设一个SQL执行很慢,如何排查?哪些原因可能导致索引未命中?
首先,确认查询确实慢。可以使用EXPLAIN或EXPLAIN ANALYZE(取决于你的数据库系统,如PostgreSQL、MySQL等)来查看查询的执行计划,这可以显示是否使用了索引,以及是否进行了全表扫描等。 -
Spring事务传播行为有几种?为什么要有事务传播行为?(没背,寄)
有7种
REQUIRED:如果当前没有事务,就新建一个事务;如果当前存在事务,则加入这个事务。这是默认的传播行为。
SUPPORTS:如果当前存在事务,则加入这个事务;如果当前没有事务,则以非事务方式执行。
MANDATORY:使用当前的事务,如果当前没有事务,则抛出异常。
REQUIRES_NEW:新建一个事务,如果当前存在事务,则挂起当前事务。
NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,则挂起当前事务。
NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
NESTED:如果当前存在事务,则在嵌套事务内执行;如果当前没有事务,则执行与REQUIRED类似的操作
不同的传播行为可以应对不同的业务需求,通过定义不同的事务传播行为,可以精确控制哪些操作需要在同一个事务中执行,哪些可以独立执行。 -
消息队列有什么应用场景?
https://baijiahao.baidu.com/s?id=1795990074476365260&wfr=spider&for=pc -
Kafka有深入了解过吗?Kafka中有哪些组件?broker是什么? Kafka如何保证消息不丢失?
问到30时候开始手撕,后面45min都是手撕,最难绷的一集 -
写sql: 员工表和部门表,计算每个部门薪资最高的员工(不难,但是当时降智没写出来,面试官一步步引导,最后勉强写出)
-
一个日志系统的场景题,有三个小问
2.1 写shell脚本统计日志系统中的top10 IP(不会写shell,寄)
2.2 用java统计日志系统中top 10 IP(用堆来统计,需要手写堆,写出伪代码就好,不会,寄)
2.3 日志系统统计一天内哪一秒峰值在线人数最多:
class Line {
String ip;
int start;
int end;
}
用差分 + 前缀和做的,最后还是靠面试官引导做出来
反问:简历可以优化的点?(没说)面试结果大概什么时候出?(不一定,然后被问是否有其他offer比较着急?)
三面(6月16日)
- 介绍实习经历?做了哪些工作?有什么产出?多少人协作?
- 接收到的数据格式?如何处理?数据类型有多少种?
- 你觉得做的过程中有什么难点和收获?(答得不太好,问到这里可能感觉实习没什么难点,就开始问八股了~)
- MQ如何保证消息不丢失?什么情况下消息会重复?如何保证消息不重复?
- 分布式ID生成方案?
- 如何用Redis实现分布式锁?
- 假如让你实现一个消息队列,你会怎么实现?#牛客AI配图神器#
- 考虑一个大文件,而内存很小,如何统计大文件里某个特定字符串出现的次数?
手撕:阿拉伯数字字符串转大写,如:“1234” -> “壹仟贰佰叁拾肆”; “123456” -> “壹拾贰万叁仟肆佰伍拾陆”, 写了一会被叫停,说由于时间关系,说个思路就好,然后反问后就下播了~
三次字节面试都感觉面试官对简历不太感兴趣,觉得实习没有亮点,估计是要遗憾离场~
反问:面试结果什么时候能出?(说和一二面面试官对一下,周三之前反馈)
hr面
- 本硕是考的还是保送?
- 研究生期间研究方向?
- 实习经历?实习最大的收获?
- 开发人员和测试人员如何协作?
- 你是如何快速了解业务的?
- 研究生期间成绩排名?
- 你觉得自己有什么需要改进的地方?
- 什么时候可以入职?
最后说和业务部门对一下,没问题就发起审批
时间:25年6月16日
字节生活服务一面凉经
项目难点,解决?
断点重传怎么实现的
XXL-Job任务调度机制
Spring Boot 特点、原理
Springboot是一个用于简化Spring应用程序开发的框架,它通过提供快速启动的方式、自动配置和约定优于配置的原则,极大化简化了Spring应用的开发过程。
- Springboot 提供了快速启动的能力,通过内嵌的服务器(如Tomcat、Jetty等),可以将应用程序打包成一个可执行的JAR文件,从而简化了部署和运行。开发者无需手动配置服务器,只需编写少量的代码即可完成应用的开发。
- Springboot 采用了自动配置ID机制,根据应用程序中引入的依赖和配置,Springboot可以自动配置整个应用程序的环境。这大大减少了开发者需要进行的手动配置工作。
- 基于条件注解和spring的SPI机制来实现。 - Springboot遵循"约定大于配置"的原则,提供了一系列默认的配置和约定,如果开发者按照这些约定进行开发,就可以大大减少配置文件的编写和配置项的设置。约定大于配置并不是约定项和配置项同时存在的使用,约定项的优先级更高,而是在没有自定义配置项时,提供默认的配置项。
Spring Boot 和 Spring Cloud 区别
Elasticsearch原理
ES是基于Lucene分布式搜索服务,可以存储整个对象或文档。主要用于大量数据的索引查询。
- 用户将数据提交到Elastic Search 数据库中
- 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据
- 用户搜索数据时候,再根据权重将结果排名,打分,再将返回结果呈现给用户
MySQL索引为什么用B+树
TCP的可靠性是怎么保证的
1应用数据被分割成TCP认为最合适发送的数据块
2.TCP给每个数据包指定序列号
3.TCP将保持它首部和数据的校验和
4.TCP连接的每一方都有固定大小的缓冲空间,TCP的接收端只允许发送端发送接收端缓冲区能接纳的数据
5.当网络拥塞时,减少数据的发送。
6.每发送完一个分组就停止发送,等待对方确认。
7.超时重传。
数据库隔离等级有哪些
读未提交
读提交
串行化
可重复读
可重复读是怎么实现的
指在整个事务过程中该事务看到的记录,自始至终都是一样的。因为事务A一开始就创建好了Read View,一直到提交前都采用同一个Read View。
https://blog.csdn.net/LNF568611/article/details/131627710
手撕–54张扑克牌抽7张判断其中有没有顺子
6月8号
字节生活服务一面凉经
拷打项目,问的挺详细,很多没考虑到的问题,没回答上来,还有压力测试啥的,涉及到qps相关的
少量八股,八股也会夹着项目问:
mysql隔离级别
redis和redission的区别,redission的优点,能否单例部署
redis的bitmap的相关语句书写
手撕:提供一个数组和一个链表,要求删除链表中出现过的数组中的节点,链表结构要自定义
6月5号
一面凉经
- 自我介绍。
- 具体介绍一下项目中的缓存优化。
- “结合数据库更新事件触发删除缓存操作”是指什么?
- 介绍一下“租约状态重构”这块。
- 介绍一下 “ JWT 登录和 ThreadLocal 透传”。
- Java 的 Object 类提供的常用方法有哪些?
- 有没有用过 equals() 方法?
==
是操作符,可用于基本数据类型和引用类型比较。
equals()
是定义在Object类中的方法,仅用于对象比较
- 有了解 hashCode() 方法吗?
在散列表中,hashcode()相等即两个键值对的哈希值相等,然而哈希值相等,并不一定能得出键值对相等
但是equals()相等,hashcode()一定相等。
- 如果只重写了 hashCode() 方法而没有重写 equals() 方法会有问题吗?
如果不重写equals()方法,默认使用Object类的equals()方法,该方法比较的是对象的内存地址。而重写的hashCode()方法可能会产生不同的哈希值,这会导致哈希冲突,即不同的对象可能具有相同的哈希值,从而影响集合的正确性和性能
- Java 中的 HashMap 是怎么实现的?
JDK7中的hashmap使用的是数组+链表的实现方式,即拉链法。
在JDK7版本因为使用了链表,在出现hash冲突时,会在冲突位置形成链表。
JDK8引入了红黑树,链表长度超过8时,会将链表转换为红黑树,以提高在链表长度较长时的查询性能。
- HashMap 中插入一个元素是怎么定位的?
利用indexfor方法
static int indexFor(int h, int length) {
return h & (length-1);
}
该方法利用了hash值与数组长度,计算得到索引。
-
哈希函数和刚才说的 hashCode() 方法有关系吗?
-
怎么判断插入的元素是否重复?和刚才讨论的 equals()、hashCode() 方法有关系吗?
-
数据库事务有哪些特性?
隔离性,原子性,一致性,持久性 -
隔离性中的隔离级别有了解吗?
读未提交,读提交,可重复读,串行化 -
读已提交隔离级别下存在什么问题?
不可重复读和虚幻读 -
幻读是什么?
-
在同一个事务中,针对同一个表,读取的记录总数前后不一致
-
MVCC 可以解决幻读问题吗?
-
假设有两个数组 A 和 B,怎么求交集?
-
了解快速排序的思想吗?快排的时间复杂度和空间复杂度?
-
所做的项目有没有用到进程间的通信?
-
进程间有哪些通信方式了解吗?
-
TCP 和 UDP 最大的不同点?
-
后端服务和数据库的连接是基于 TCP 还是 UDP 协议的?
后端服务与数据库之间的连接是基于 TCP 协议 的。
数据库通信(如 MySQL、PostgreSQL、Oracle)需要确保数据传输可靠、有序、完整;
TCP 提供了三次握手、确认应答、重传机制、流量控制等功能,适合要求高可靠性的业务通信。
像“写入数据”、“提交事务”这类操作容不得数据丢失;
UDP 是不可靠协议,不提供顺序与重传保障,不适用于此类场景。 -
后端服务和数据库的连接是进程间通信吗?
-
算法题:*****************************的变体,输出改为最长子串(有多个只需输出一个即可),ACM 模式,用飞书写。
-
反问。
字节一面:
7月1号
介绍项目,拷打项目
八股:
- mysql的索引结构
- 事务的隔离级别?有什么特点
- 可重复读的实现原理了解吗?(MVCC + )
- mysql 的日志(只答了redolog和undolog)
- mysql的binlog了解吗
- mysql的锁了解吗?有哪些锁
- mysql的锁是如何在update过程中使用的?
- 什么情况下使用分布式锁,怎么使用的?
- 其他的分布式锁了解吗?比如可重入的分布式锁
- 还有没有其他方法解决超卖问题?在分布式锁的基础上优化的方法