小红书PE后端一面
《面试题目》
- 自我介绍
- 线程池有哪些常见参数
- RPC 调用情况下你会使用怎么配置线程池?
- IO 密集型任务线程大多时间是在等待外部资源响应,此时线程处于空闲状态,CPU 利用率较低,可以设置较大线程数
- CPU 密集型任务,例如浮点计算等,很少会有阻塞情况,此时线程数多会造成上下文切换频繁影响性能能
- ConcurrentHashMap 底层的读写是怎么处理并发冲突的
- 读:将 value 和 链表 next 指针设置为 volatile,多线程修改 volatile 变量时不会使用自己的副本,是修改公共内存中的变量,每个线程都可以取到最新的数据,读的时候不需要加锁
- 写:首先判断有无冲突,如果没有冲突的话直接 CAS 插入即可,如果有冲突的话就 synchronized 锁住头节点遍历链表进行插入
- 扩容:ConcurrentHashMap 的扩容也是并发安全的,且支持多线程协同扩容。扩容时,会将原数组的桶迁移到新数组(容量翻倍)。多个线程可以同时参与数据迁移工作。系统会将任务拆分成一个个小的“区域”(TransferRegion),线程领取任务后进行迁移。在扩容期间,读操作依然可以正常进行(可能会读到旧数据或新数据,但最终一致性有保障),写操作则会协助扩容或等待。
- Synchronized 和 ReentrantLock 两种锁的选择
- Synchronized 关键字:使用方式简单,可以加在代码块和代码上,只能实现非公平锁,多线程来了之后谁抢到谁执行,而不是排队。JDK 1.6 引入了偏向锁和锁升级机制提高了性能,性能和 ReentrantLock 相差不大。底层通过 Java 对象头中的 Mark Word 标记字实现,标记字中有 2 比特记录当前锁状态,
- 无锁状态记录 hash 值和 GC 年龄
- 偏向锁状态记录当前线程 ID,当第一个线程来时记录
- 轻量级锁,记录持有锁的线程的锁记录,每一个线程都有自己的锁记录,第二个线程来时转为轻量级锁;
- 重量级锁:记录堆中的 ObjectMonitor 对象指针,这个对象有一个队列存储没有获取锁的线程进行排队,当线程执行完毕后会唤醒队列中的线程竞争锁
- ReentrantLock:通过 AQS 抽象队列同步器实现,底层有一个 state 记录冲入次数、一个先进先出 FIFO 的 DLQ 双向链式队列记录排队线程,公平锁先查看队列再竞争锁,非公平锁先尝试获取锁操作失败才入队列等待。
- Redis 为什么快
- Redis 大 key 怎么解决
- Hive2CK 导入数据是直接 CK 导入还是使用中间件
- ClickHouse 和 MySQL 底层有什么区别
- ClickHouse 主要的使用场景在哪里
- ClickHouse 并发支持如何
- ClickHouse 物化视图是什么
- Agent 项目用户转人工拦截率这个数据口径是怎么统计的,有没有遇到过用户找不到人工 Oncall 入口而投诉的
- 讲述一下你的冷热分层项目
- 你这个 OOM 问题是怎么排查的,最后怎么解决的(OkHttpClient 没单例且没指定线程池导致的 OOM)
- Kafka LAG 一般怎么排查(从提交消息消费成功出排查,查看是线程挂掉了还是处理该消息耗时太长导致 LAG
- 算法题:翻转01字符串 k 次,找到翻转后最长相同串(eg: 10101 k=1, res=3, 翻转一个0得到111, 翻转一个1得到000
《参考解析》
-
计算机网络:TCP(传输控制协议)是面向连接、可靠的传输协议,提供流量控制和拥塞控制;UDP(用户数据报协议)是无连接、不可靠但速度更快的协议。TCP通过三次握手建立连接(SYN→SYN+ACK→ACK),四次挥手断开(FIN→ACK→FIN→ACK)。
-
MySQL深度:MySQL InnoDB使用B+树索引,支持ACID事务。关键知识点:聚簇索引(主键索引)叶节点存完整行数据;辅助索引叶节点存主键值(需回表);MVCC通过undo log版本链+ReadView实现多版本并发控制,解决脏读/不可重复读;事务隔离级别从低到高:读未提交→读已提交→可重复读(默认)→串行化。
-
Redis核心:Redis常用数据结构:String/Hash/List/Set/ZSet。持久化:RDB(定期快照,恢复快,数据可能丢失)和AOF(追加日志,数据安全,文件大)。缓存穿透用布隆过滤器;缓存雪崩加随机过期时间+多级缓存;缓存击穿用互斥锁或逻辑过期。分布式锁用SET key value NX PX + Lua脚本保证原子释放。
-
JVM与GC:JVM内存模型:堆(对象分配,GC管理)、方法区(类信息、常量池)、虚拟机栈(栈帧/局部变量/操作数栈)、本地方法栈、程序计数器。GC算法:标记-清除(内存碎片)、标记-整理(无碎片,但移动对象)、复制(新生代)。G1按Region划分堆,预测停顿时间。