【得物】Java岗-有问有答超详细面经

一面

自我介绍
A:结合技术点做个自我介绍
B:…
A:简单介绍一下你的职责和工作内容
B:…

缓存
A:你们的缓存怎么设计的?
B:主要是内存缓存
A:讲一下你们的淘汰策略
B:LRU,用的guva的cache
A:如果让你设计个LRU,你怎么设计?
B:我会基于LinkedHashMap设计吧,hash表+链表的方式
A:为啥用链表呢?
B:因为这里是头插或者尾插的方式,链表的增删性能更高,只需要变动相邻节点
A:数据源变更的时候你们是怎么更新缓存数据的?
B:我们先写数据源,然后清掉缓存,我们每个服务器上都有个本地数据源,我们把数据落下来了
A:如果是多服务器共享的数据源呢,怎么同步每台机器上的内存缓存?
B:这个我想一下啊。。。
B:我想到一个比较笨的办法,可能不是最优解。
A:说说看
B:更新数据源的时候用消息队列去通知每个服务器,发布订阅的方式。
A:嗯,我们差不多也是这种方案
B:如果是这种场景的话缓存我可能会考虑重新设计了,感觉不是最优解。
A:你们的超时时间怎么做的呢?
B:就是用的guva的cache的超时,我们的缓存淘汰主要是通过LRU,我们的超时时间都设置的很长,我没研究过具体实现。
A:如果让你来设计呢,你怎么做?
B:参考redis的超时实现吧,lazy的方式,查询的时候检查是否超时,如果超时返回null,再配合一个后台线程,定时清理超时缓存。
A:嗯,我们也是lazy的方式

分库分表
A:聊一下分库分表吧,你们现在有用分库分表吗?
B:没用,我们现在的系统延迟要求很高,C端的请求都不会落到数据库,基本都是基于内存的。现有的数据库也都是to B的
A:好吧,那我给你构建一个场景:现在有个用户表,我们用uid做的sharding,但是我们想用时间字段做分页查询,你有什么方案吗?
B:我之前做游戏的时候有个类似的场景,我们的用户表根据服务器分表,但是有个需求,不同服务器的玩家可以相互加好友。我们的做法是抽取一个字段比较少的总表,查询的时候查总表添加好友。我感觉可以参考这种方案。如果不行的话就只能扫表,在内存汇总了。
A:嗯,现在差不多也都是总表的方案
A:我们分表的ID能基本保证递增,但是合并起来不保证递增…(这个问题没听太明白)
B:跳过吧,这个暂时没想出来
A:好的没关系


(后面还有些记不太清了)
A:好的,你有什么问题要问我的吗?
B:可以介绍下你们现在的项目和团队情况吗?
A:…
B:你们现在工作中的难点是什么?我过去的话主要负责什么?
A:现在主要的压力还是用户量不停创新高带来的压力,和系统升级迭代的需求
B:好的,差不多就这些吧
A:你看什么时间合适再过来现场面?

二面

项目架构
A:可以画一下你们系统的架构图吗?
B:…
A:设计个秒杀系统,秒杀5000台笔记本,满足用户基本用户积分超过10000分的8级会员可以参加,在某个时间节点准时开始。
B:这个场景有三个数据库交互操作,但是只有秒杀是有时间节点限制的,基本和会员等级校验没有时间节点限制,可以考虑把这两个步骤解耦,在秒杀之前让用户先去做积分和会员等级的校验,校验通过的用户给他一个令牌,参加秒杀的时候用户把令牌带过来做入场券。
A:积分服务和会员服务的并发量是有限的,这样直接把流量打过去会把这两个服务打挂吧?
B:这两个校验没有时间限制,可以在校验服务里面做个限流,就用Semaphore简单实现下也很容易吧
A:嗯
B:然后就是设计秒杀功能,其实处理高并发的本质就是减少最终到达数据库的请求数,基本的思路就是缓冲和缓存。
B:可以在每台服务器上增加一个前置队列,每个队列长度为5000,队列装满之后的用户请求直接拒绝掉,假设有有10台服务器,最后真正进来的请求其实就只有5W个了。
A:但是5W个请求直接打到数据库还是可能把数据库打挂,因为减库存是个比较复杂的操作,可能还会伴随后续流程
B:可以先在缓存里面减库存,比如redis,然后再同步到数据库,做个最终一致性。
A:那你怎么保证不出现超卖呢?
B:这个减库存操作需要加一个分布式锁
A:但是你这样也还有个问题,你操作的是redis的同一个节点,如果并发量足够大,redis也可能成为瓶颈。
B:可以把库存数据分为几份存在redis里,比如分成5份,每份1000个,用户请求过来的时候用uid做分片,用户只能去竞争命中的1000个商品,如果没竞争到就返回失败
A:好的

A:长连接服务器单台机器连接数怎么超过65535的限制?比如在天猫双十一这种极端高并发的情况下硬件资源是有限的
B:没想出来,跳过吧。(当时想错了,之后取查了一下资料,服务端不会受到端口个数的限制,监听一个端口就可以跟多个客户端建立连接,理论上的最大连接数限制是在内存和文件描述符上限,Socket的本质是一个管道文件,linux操作系统默认可以同时打开的文件数量是65535,其实只要把这个参数改大点就可以突破65535的限制了)

框架底层
A:redis的几种数据结构是怎么实现的
B:主要聊了一下Zset的跳表
A:redis怎么实现的数据过期
B:lazy的模式,过期检查+后台清理的模式
A:我现在在redis中存一个数据,半小时过期,那半小时后这个数据还在吗?
B:可能在,也可能不在,要看这个数据有没有被清理掉
A:redis怎么实现的数据同步
B:应该跟mysql的类似吧,具体实现记不清了
A:redis怎么实现分布式锁,如果不用redis怎么实现分布式锁
B:没用过,不过分布式锁的原理都差不多,基本都是去竞争一个第三方资源,乐观锁实现

A:kafaka怎么实现超大吞吐量的
B:kafka有个消息分片发送的设计,在稍微降低吞吐量的代价下实现消息的批量发送,增加了吞吐量

A:netty的线程模型
B:就是多路复用io那一套,用一个线程监听全部Socket的事件,然后生产task供后面的线程池消费

(后面的问题我就不一一写答案了,基本网上也都能查到)

Java基础
hashmap的数据结构
hashmap怎么实现扩容
concurrentHashMap的锁是怎么实现的
线程池的基本参数

JVM布局
垃圾回收算法
JVM参数调优
G1垃圾回收器
线上有遇到过jvm相关的问题吗?怎么解决的

Object的原生方法

数据库相关
数据库索引的索引是怎么实现的
索引为什么要用B+树
什么是聚簇索引
A,B两个字段各自都有索引,where A = ? orderby B ,能用到索引吗?
A,B, C三个字段各自都有索引,where A = ?,B=?,C=?能用到索引?这样写会遇到什么问题吗

redis,mongo和mysql的事务有什么不同?为什么

其他
解决过哪些线上问题
服务发现是怎么实现的
怎么动态负载均衡

发表评论

后才能评论