0%

📺b后端实习面经(项目拷打,重点看)

前言:我的算法就是屎,赶点想想办法吧

2025.02.17 b站一面(项目和实习拷打,第二天晚上oc)

拷打项目

  1. 数据同步的耗时有没有要求?
  2. 什么场景需要需要百万数据? 从上流数据库批处理工具
  3. 数据的一致性、数据的稳定性、系统的稳定性、效率都是如何考虑的?会不会有丢的情况,丢的话如何处理的?(好难)
  4. Redis锁如果超时了,有没有自动释放机制(注意,不能剥夺,不要说强行剥夺,因为不合常理)
  5. SQL查询是如何做到的?单表还是多表?数据量?大概有多少列?
  6. B+树的结构、节点是怎么组织的,存的是什么,为什么效率比较高?和B树的区别?
  7. B+树一个数据页如果满了,之后会发生什么?
  8. 有没有用过NoSQL型数据库?tidb有了解过吗?
  9. 有没有分表分库?使用了什么中间件?
  10. 项目的灵感来源?为什么要做这个项目?为什么websocket的通信会比较慢?
  11. rpc:负载均衡、轮询、一致性哈希如何实现的
  12. 一致性哈希数据迁移的过程是如何的?
  13. 自定义通信协议是怎么做的?和传统的通信协议有什么区别?
  14. TCP为什么三次握手而不是四次握手?
  15. TCP每次连接时序列号都一样吗?为什么不一样,有什么作用?
  16. time_wait为什么是2MSL?MSL是什么?(报文最大生存时间)
  17. TCP滑动窗口的算法?(不会,我换成拥塞控制算法了,拥塞控制算法也要看一看)
  18. 简单介绍一下限流算法?
  19. 为什么要做ZClub?参考了小红书哪些模块?(跟上设计思路)
  20. 分片上传是怎么想到的?怎么设计的?
  21. 断点重传是如何设计的?
  22. 秒传是如何设计的?(有点扯淡的设计)
  23. Netty相关?零拷贝技术介绍一下?
  24. 多路复用?select、poll、epoll介绍一些
  25. 手撕重排链表
  26. 反问:表现如何(前面还可以,基础扎实,但是算法有点可惜,要加强一下,项目也还可以,结果会在一周内给出)

数据的一致性、数据的稳定性、系统的稳定性、效率都是如何考虑的?会不会有丢的情况,丢的话如何处理的?

  1. 使用事务,保证数据的组装、校验、导入等操作的原子性,如果中间环节失败,自动回滚。
  2. 增量更新使用日期,以日为单位进行更新,防止重复更新
  3. 同时对于同一业务实体的数据,通过RocketMQ顺序消息发送,确保消费者按照顺序处理,避免并发导致的脏数据。
  4. 对于异常情况,记录日志,进行补偿。RocketMQ开启手动ACK模式,仅在数据成功落库之后提交Offset,多次重试之后转存到死信队列人工介入。

系统稳定性如何保证的

使用Redis记录最后处理的批次ID,故障后从断点处理

效率上如何优化的

使用CF对多数据源进行拉取,异步并行处理

Redis分布式 锁如何实现的,有没有兜底策略啥的?

加锁的时候设置过期时间,解锁的时候使用lua脚本,确保判断锁存在,然后删除锁是一个原子操作。
兜底策略:合理的过期时间,使用看门狗,后台线程定期检测业务是否能够完成,延长锁的时间,私信队列/日志记录锁的异常行为,人工排查后强制释放
看门狗机制,每隔一段时间自动续期一次,保证锁不会过期。如果看门狗没有在指定时间内收到心跳恢复,会认为锁的写线程已经发生了故障,会尽量的处理死锁(强制解锁或者触发一个回调方法来处理死锁)

B+树的结构、节点是怎么组织的,存的是什么,为什么效率比较高?和B树的区别?

  1. 非叶子节点存储索引(键值),不存储数据,支持更多分支,降低树的高度,叶子节点存储数据,并且通过双向链表连接,支持范围查询
  2. 树低可以减少磁盘I/O次数
  3. B树非叶子节点也存数据,并且每一层的分支更少,树更高,且数据之间没有形成链表,范围查询时需要进行回溯。

B+树一个数据页如果满了,之后会发生什么?

会分裂为两个页,中间键提升到父节点
流程:

  1. 创建新页:右半部分移到新页,提取中间键(如原表最后一条数据)插入父节点。
  2. 更新父节点索引:父节点未满,直接插入中间键
  3. 若父节点满,则递归分裂:父节点已满,递归触发父节点分裂
  4. 分裂之后维护双向链表以保证顺序访问能够正常

分库分表

使用ShardingSphere或者MyCat,比如可以将帖子按照时间分片

为什么使用WebSocket通信,效率会比较慢

握手阶段需要HTTP升级,头部较大,并且会长期占用资源,高并发时会影响性能

RPC负载均衡的设计

轮询、一致性哈希(相同请求命中固定节点,减少数据迁移)

一致性哈希数据迁移

一致性哈希通过虚拟节点和局部迁移减少数据移动。例如,新增节点时,仅影响相邻区间的数据,

  1. 新增节点:
    • 哈希环上插入新节点的多个虚拟节点
    • 仅迁移新节点与顺时针相邻节点之间的数据
  2. 删除节点:
    1. 移除目标节点的所有虚拟节点
    2. 将数据迁移到顺时针下一个节点
  3. 客户端进行切换,逐步将请求路由到新节点,避免瞬时负载过高。

自定义通信协议设计,对比传统协议如何?

协议的组成:

  1. Header
    • 魔数:1字节
    • 版本号:1字节
    • 序列化器:1字节
    • 消息类型:1字节
    • 消息状态:1字节
    • 请求id:8个字节
    • 压缩方式:1字节
    • 消息体长度:4字节
  2. Body(任意内容,字节)
    优势:支持多种序列化与压缩(如Gzip),使用更灵活,无HTTP头部冗余

为什么TCP每次建立连接时序列号不同?

为了防止重放攻击

time_wait为什么是2MSL?MSL是什么?(报文最大生存时间)

MSL要大于等于TTL消耗为0的时间
MSL是报文的最大生存时间,网络中可能存在来自发送方的数据被接收方处理之后,又会发送响应,一来一回所以需要等待二倍的时间。

拥塞算法

  • 慢启动:初始拥塞窗口指数增长。
  • 拥塞避免:窗口线性增长。
  • 快重传:收到3个重复ACK立即重传。
  • 快恢复:窗口减半后进入拥塞避免。

限流算法有哪些?

  • 固定窗口:单位时间限请求数,简单但临界突发。
  • 滑动窗口:细分时间块,平滑限流。
  • 令牌桶:匀速生成令牌,允许突发。
  • 漏桶:恒定速率处理,平滑流量。

分片上传、断点重传、秒传设计的细节

  • 分片上传
    1. 前端将文件切分为固定大小(如5MB)。
    2. 服务端为每个分片生成唯一ID,并行上传。
    3. 所有分片上传完成后合并。
  • 断点续传
    • 记录已上传分片ID至Redis。
    • 续传时跳过已传分片。
  • 秒传
    • 计算文件MD5作为唯一标识
    • 上传前查询服务器是否存在相同哈希
    • 如果存在直接返回地址,无需重复上传

TCP滑动窗口算法

  1. 接收方维护一个可接受的数据量大小,也就是滑动窗口大小,并且通过ACK报文来通告对方大小,发送方据此来调整发送速率
  2. 动态滑动:每收到一个ACK窗口向前滑动允许发送新的数据
  3. 流量控制:接收方通过减小窗口,抑制发送方速率,防止缓冲区溢出

四次挥手是否可以合并为三次

如果被动关闭方无数据发送,可将FIN和ACK合并,依赖延迟确认机制。
可能会导致主动关闭方每收到最终的ACK,被动方已经关闭

简单介绍一下PageCache

PageCache通过内存缓存磁盘数据,加速文件访问。例如,读取文件时,优先从PageCache获取,未命中再访问磁盘,结合预读和写回优化整体性能。

将频繁访问的文件数据缓存在内存中,从而减少磁盘IO,同时可以根据访问模式预加载后续数据,提升读取效率,写回时可以延迟磁盘写入,合并多次写操作,降低磁盘IO

2025.02.19 二面 (20多分钟 ,问了一点实习,还有一点计网,然后写了个LRU 秒了,怀疑是kpi)

  1. 自我介绍
  2. 实习时间,何时到岗(画饼说如果有hc的可以转正,感觉纯画饼)
  3. 学校安排,如何处理考试啥的
  4. 到岗时间
  5. 实习介绍
  6. 手撕LRU
  7. 反问岗位:直播结算?整体基础不错,但是实习经历比较平淡

后续:挂了

mysql一次性查询200w数据,msyql会出现问题,我该如何处理,如何优化,业务是数据批处理和同步到其他数据库中,如何保证这200w条数据的一致性、准确性、稳定性、容错呢,怎么样保证这个查询不会影响其他查询的性能呢?

  1. 使用基于有序主键的范围查询WHERE id > last_max_id LIMIT batich_size
  2. 流式查询:使用JDBC/连接器的游标,或者服务端游标,减少内存压力
  3. 索引覆盖:确保查询仅能通过所以即可完成避免回表
  4. 资源隔离:通过MySQL资源组和中间件限制查询的CPU/IO资源
    数据一致性如何保证:
  5. 事务与批次提交:使用事务保证单批次操作的原子性,分批提交(每1000条提交一次)
  6. 幂等设计:通过唯一键、版本号避免重复处理
  7. 分布式锁:同步时标记正在处理的记录,防止并发冲突
  8. 补偿机制:记录同步日志,通过定时任务修复不一致数据
    稳定性设计:
  9. 熔断降级:服务中引入熔断机制,异常时暂停任务并且告警
  10. 重试策略:网络抖动使用指数避退重试
  11. 异步化处理:将数据同步任务提交到线程池或者消息队列,解耦试试性要求

为什么使用RocketMQ和Kafka对比,适合场景,RocketMQ底层是如何做的顺序保障的

Kafka:

  1. 高吞吐日志流处理,适合大数据场景
  2. 顺序消息只能保证分区内顺序,需要业务自行管理分区键
    RocketMQ:
  3. 金融级事务消息、顺序消息、延迟消息支持更好
  4. 通过MessageQueue锁机制严格保证同一队列的顺序性
  5. 提供两阶段提交(版消息机制),Kafka需要自行实现。

RocketMQ顺序性的实现原理

  1. 队列分配:生产者通过MessageQueueSelector将同一业务ID的消息发送到固定的队列中
  2. 消费端:消费者对队列加锁,单线程顺序消费
  3. 失败重试:若某条消息消费失败,会阻塞后续消息直到处理成功

MongoDB了解和MySQL的区别

看门狗的底层

浏览器键入URL会发生什么,路由转发过程,每一层如何寻址,如何解数据包和包装