快手一面
1. 我看你项目里涉及多线程,那你对Java线程池应该有一定了解吧,说一下线程池都有哪些参数,然后任务创建的流程是怎么样的
balabala
2. 在多线程这块,你在使用Java容器的时候是怎么用的,用Map举个例子
ConcurrentHashMap==>CAS+sychronized,HashMap + sychronized
3. 看了你的项目,有10w的设备,那你这个数据量有多少
一天150w左右的数据
4. 这样的话查询会很吃力吧,有做分库或者分表么
没分库,但是分表了
5. 按照什么规则分表的
根据甲方实际的需求,他们对于当天0点开始的数据比较在意,也是他们最需要的数据,所以我们按照日期进行分表
6. 那在查询的时候有用到索引么,是怎么用的
把设备id和日期作为索引
7. 我看你简历说对innodb引擎有所了解,那你说说看innodb在底层是怎么存储索引的
B+树
8. 为什么不用红黑树或者hash索引
首先介绍了B+树的特点 ==> B+树是一个平衡树;B+树的关键字节点都在叶上;B+树的叶节点是有序的;非叶节点不存数据,所以可以存更多的索引;叶节点用双向链表进行连接,方便范围查询;节点分裂和合并的时候需要IO较少(这个不知道为什么,背的);有利于磁盘预读和缓存(因为有序存储)。
然后介绍了红黑树和B树为什么不行,Hash索引为什么不行(适合单点查询,存储无序)
9. 我看你框架用的是springboot,你看过springboot的源码么,讲讲Spring的IOC吧
先从配置元数据中获取要DI的POJO,然后把POJO形成的BeanDefinition注入Spring容器,最后使用方通过ApplicationContext从Spring容器直接获得
10. springboot中的循环依赖问题你清楚么,它是怎么解决的
三级缓存
11. 你项目里使用Netty保持和设备的长链接,你能说说看Netty的线程模型么
Netty是Reactor模型,基于多路IO,然后讲了Reactor单线程、Reactor多线程、Reactor主从多线程
12. 项目里我看你用了消息队列,你说说看你从消息队列中消费的时候是怎么做的
每5min有10w条数据,每5k条做一次批量入库
13. 有没有遇到过消息堆积的情况
没..
14. 你项目里用kaptcha+redis实现了验证码登陆,这里redis是怎么用的
记录验证码的uuid和验证码的正确值
15. 问了uuid怎么保证唯一性,以及是否有过期时间
单机部署的服务,kaptcha自己就保证了唯一性;设置了5min的过期时间
16. 书接上回,redis的过期策略是啥
实在没印象了,说了抱歉
17. 如果服务器请求量特别大,出现缓存穿透的话,验证码这边怎么办
先说了缓存穿透==> 缓存和数据库里都没这个数据;然后大脑一片懵不知道怎么解决,最后想到了两个方法,一个是 异步定时更新,另一个是 互斥锁,但是这两个对于验证码的场景都不适用,而且似乎是解决缓存击穿问题的)
后来查了一下,缓存穿透可以使用布隆过滤器。因为缓存穿透的问题大概率是有很多恶意流量请求,来查询一些不存在的数据。
编程题:给了两题,让我二选一。
第一题是给了一个"地图",有一些陆地(1)和一些水(0),问岛屿个数(被水包起来的陆地)有多少
第二题是给了两个链表,每个链表代表一个数,数字的排列顺序从个位到最高位开始排列。要你求这两个数的和,并且用相同格式的链表返回数据。
选了第二题,因为当时觉得第二题很简单(确实也简单,第一题也不难)
思路:
先把链表转成数然后做加法,最后再转成链表。
但是,
写面经的时候想起来,好像说了链表长度最大为1000...所以应该一位一位做加法来着,注意进位就行了。
面完之后去干活了,可能有些问题遗漏了,后面如果有想起来再补充。
---
补充1:InnoDB一次更新事务的流程是怎么样的
InnoDB在更新记录的时候会现在缓存池中查找数据是否在内存,如果不在的话从磁盘读取到内存;然后在修改操作前会记录undolog,保证事务的原子性和一致性(这里我还说了一下undolog可以用来回滚,MVCC机制好像也是用undo log来做的);第三步的是执行update语句的时候,InnoDB会先更新已经读到缓存中的数据,同时将修改操作写入redo log中;然后提交事务,InnoDB将Redo Log写入磁盘,并且将页状态设置为"脏页",表示该页修改了但是未刷盘;紧接着把脏页写入磁盘,保证数据的持久性;最后记录Binlog。
———
补充2:
准备二面的时候想起来,还问了COW
——
约二面了