继续分享热乎乎的面经
今天依旧是分享组织内部成员的真实面试经历。
他个人感觉面试不太满意,尤其是分布式锁那一块回答的不太好也不知道怎么回答,大家可以看一下整个面试过程,如果你对这些问题有更好的见解可以发在评论区,大家一起讨论一下:
岗位介绍
Golang后端开发工程师 10-15K·13薪 深圳
岗位职责:
- 参与音视频后端业务系统的模块设计、微服务开发和维护;
- 参与微服务基础设施落地建设:包括不限于服务治理、 可观测、消息队列、数据库等中间件技术;
参与线上问题攻坚和后端业务系统稳定性建设;
任职资格:
- 本科及以上学历、两年以上相关工作经验;
- 精通Linux平台下Golang/C/C++/python/java任一编程语言、 熟练掌握常见数据结构和算法;
- 熟练使用MysqlPostgresql. Redis、 kafka; 具备调优和问题定位分析能力;
- 熟悉分布式、微服务架构、docker/k8s 容器编排等云原生相关技术;
- 积极主动、具有良好的沟通、分析、解决问题能力。
面经分享
1. 实习公司的产品功能,服务于什么行业的?
2. MySQL 一行记录是怎么存储的?
- 存储位置
数据存储在.ibd
文件中,每个表对应一个文件(InnoDB引擎)。文件路径可通过SHOW VARIABLES LIKE 'datadir'
查看。 - 表空间层级
由段(数据段/索引段)、区(连续64个页,1MB)、页(默认16KB)、行构成。页是磁盘读写的最小单位,区用于减少随机I/O。 行格式(以Compact为例)
- 变长字段长度列表:逆序存储VARCHAR等字段的实际长度,使字段值与长度信息在CPU缓存中相邻。
- NULL值列表:用位图标记允许为NULL的列,逆序存储。
- 记录头信息:包含删除标记、下一条记录指针、记录类型(普通/索引节点/最小/最大)。
隐藏字段:
row_id
(无主键时自动生成)trx_id
(事务ID)roll_pointer
(指向旧版本数据的指针,支持MVCC)。
- 行溢出处理
当单行数据超过页大小时,Dynamic格式仅存储溢出页指针(20字节),而Compact会部分存储真实数据。 行格式选择
- Compact(5.7前默认):适合小字段。
- Dynamic(5.7后默认):对大字段仅存指针,空间利用率更高
3. 为什么使用分布式锁,分布式锁和mysql锁的区别?
他的业务场景:活动期间,瞬间有大量请求发送过来频繁出现数据不一致问题。多个用户同时修改同一群组的积分时,积分值可能被覆盖或计算出错,导致最终结果与预期不符。
他的做法:使用Redis的SETNX命令实现分布式锁,确保同一时刻仅一个请求能修改特定群组的积分,为避免死锁,为锁设置超时时间
面试官追问:为什么这个场景需要分布式锁,使用mysql的锁不行吗,而且mysql也能保证并发安全,为什么还要使用呢?
从这里就卡住了,因为他的场景是单个数据库内的,然后面试官就质疑了,说没有分库分表,不用分布式锁也能保证数据一致性。仔细一想确实是这样,这样我也推荐大家写简历的时候,如果场景是单个数据库,最好不要提到分布式锁。
分布式锁和mysql锁的区别
一、核心定位
维度 | 分布式锁 | MySQL 锁 |
---|---|---|
作用范围 | 跨进程、跨节点的全局资源协调 | 单数据库连接或单节点内的资源互斥 |
目标 | 解决分布式系统多节点并发竞争 | 保障单数据库事务的 ACID 特性 |
二、实现机制
分布式锁
- Redis:通过
SET key value EX NX
实现,结合超时和续期(如 Redisson 看门狗)。 - ZooKeeper:基于临时顺序节点和监听机制,保证公平性。
- MySQL 特殊设计:通过唯一索引或乐观锁字段实现跨节点互斥。
- Redis:通过
MySQL 锁
- 悲观锁:
SELECT ... FOR UPDATE
直接锁定数据行或表。 - 乐观锁:通过版本号字段实现非阻塞并发控制。
- 悲观锁:
三、适用场景
场景 | 推荐方案 | 原因 |
---|---|---|
单节点事务并发控制 | MySQL 锁 | 无需额外组件,直接利用数据库 ACID 特性。 |
跨节点资源协调(如集群任务) | 分布式锁 | 解决多节点并发问题(如 Redis 高吞吐、ZooKeeper 强一致)。 |
高并发短时操作(如秒杀) | Redis 分布式锁 | 单线程模型适合高频短时锁操作。 |
四、性能与可靠性
维度 | 分布式锁 | MySQL 锁 |
---|---|---|
性能 | Redis(微秒级) > ZooKeeper(毫秒级) | 行锁中等,表锁并发性能差。 |
可靠性 | Redis 需集群防单点故障;ZooKeeper 强一致 | 依赖数据库主从切换容错。 |
4. 说一下项目中kitex框架,跟其他框架有什么区别
在对现有框架进行调研后,我们发现像网关与微服务之间采用 gRPC、Thrift 等协议通信的方案,主要依赖于代码生成来实现协议解析和传输。这意味着每当有更新时,都需要重新生成代码并发布,无法支持动态更新。以 gozero 为例,它遵循了这种模式。
Kitex 提供了一个不同的解决方案。Kitex 支持所谓的泛化调用,这使得作为客户端的网关能够动态维护业务接口的 IDL(接口定义语言)。通过这种方式,可以实现从 HTTP 接口到 RPC 接口的转换,无需依赖业务服务端的客户端代码,从而实现了网关与业务逻辑之间的代码解耦。
网关仅需关注通用逻辑的维护,例如鉴权插件等,而无需关心具体的业务代码。当有新的服务上线时,也不需要停机更新。这种方法不仅加速了业务迭代,也提高了整体效率。
5. 基于RBAC理论怎么设计用户鉴权
根据组织的业务需求和安全策略,定义不同的角色,并为每个角色分配相应的权限。然后,将用户与合适的角色进行关联,用户在登录系统后,通过激活相应的角色来获取该角色所拥有的权限,从而在其会话期间能够访问和操作被授权的系统资源。
- 实现一个中间件用来做权限拦截
- 定义一个角色权限关联表,用用户角色查询权限关系鉴权
- 使用rediss缓存用户的权限数据,使用jwt
6. mmap是什么,项目使用mmap解决了什么问题
- mmap(memory-mapped files,内存映射文件)是一种将文件或设备直接映射到进程地址空间的机制,允许应用程序像访问内存一样访问文件数据。
mmap 的工作原理
- 通过系统调用将文件映射到进程的虚拟地址空间
- 操作系统负责在后台处理实际的文件I/O
- 访问映射区域时会触发页错误,操作系统按需将文件内容加载到物理内存
项目中 mmap 解决的问题
- 高效文件I/O:
- 避免了传统的read/write系统调用开销
- 减少了用户空间和内核空间之间的数据拷贝
- 大文件处理:
- 可以处理比物理内存大的文件
- 只有实际访问的部分才会被加载到内存
- 共享内存通信:
- 多个进程可以映射同一个文件实现高效通信
- 比管道或消息队列更高效
- 随机访问优化:
- 对大型数据结构的随机访问更高效
- 不需要维护复杂的文件偏移量
7. OSI七层协议说一下,TCP,http属于哪一层的,数据链路层有哪些协议
应用层、表示层、会话层、传输层、网络层、数据链路层、物理层。
数据链路层(第2层)的协议包括但不限于以太网(Ethernet)、PPP(点对点协议)、SLIP(串行线路互联网协议)等。这些协议负责在同一网络中的不同节点之间进行可靠的数据帧传输。
8. 数据库的三大范式
- 第一范式(1NF):确保每列都是不可再分的基本数据项,即数据库表中的每一列都是不可分割的原子值,不允许表中有重复的组或数组出现。简单来说,就是消除重复的列,确保每个字段都只存储单一值。
- 第二范式(2NF):在满足第一范式的基础上,要求实体必须完全依赖于主键,而非部分依赖。这意味着如果一个关系中有复合主键,那么非主键字段必须依赖于整个主键组合,而不是主键的一部分。这主要是用来解决数据库中存在部分依赖的问题,保证数据的一致性和减少冗余。
- 第三范式(3NF):在满足第二范式的基础上,进一步消除传递依赖,即非主键字段之间不能存在依赖关系。也就是说,所有非主键字段必须直接依赖于主键,而不能通过其他非主键字段间接依赖主键。这一步是为了消除那些不是由主键直接决定的数据冗余。
9. 数据库的事务ACID特性
- 原子性(Atomicity):指事务是一个不可分割的工作单位,事务中的操作要么全部成功执行,要么全部不执行,不存在部分执行的情况。如果在事务过程中发生错误,系统会进行回滚,使数据库状态回到事务开始之前的状态。
- 一致性(Consistency):确保事务执行后,数据库从一个一致状态转移到另一个一致状态。一致性是由用户定义的约束和业务规则来维护的,事务应当将数据库从一种有效的状态转变为另一种有效的状态,保证数据的完整性。
- 隔离性(Isolation):指并发执行的多个事务之间相互隔离,互不影响。每个事务都感觉不到系统中有其他事务在并发地执行。根据不同的隔离级别,可以不同程度地避免脏读、不可重复读和幻读等问题。
- 持久性(Durability):一旦事务被提交,它对数据库中数据的改变就是永久性的,即便系统出现故障也不应丢失已提交的更新。即事务完成后,该事务的结果对系统的影响是永久的。
欢迎关注 ❤
我们搞了一个免费的面试真题共享群,互通有无,一起刷题进步。
没准能让你能刷到自己意向公司的最新面试题呢。
感兴趣的朋友们可以加我微信:wangzhongyang1993,备注:面试群。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。