面试经验积累

项目中的性能瓶颈

反应在三个方面:
1、机器不够了:每个机器的cpu利用率都达到了50%以上,需要新增机器。
2、接口性能慢:使用多线程方式去做事情,保证接口响应
1、一次调用第三方模块比较多的情况下出现耗时,把串行方式改为多线程去调用阻塞同步,对一次性查询过多的数据情况,把数据分片查询在组合。
2、对不要求立即返回的操作,做异步处理,比如下载一个Excel文件,可以在子线程中写好通知用户下载,在一些批量操作的情况下,之前是异步的处理,处理好了之后通知用户,后来改成mq的形式,在mq机器上操作完成后通知用户。
3、数据库慢查询:优化sql 使用缓存 使用ES做检索。

系统遇到的坑

1、之前由于某个时段,db集群问题,主从延迟高,所以就使用redis来做一个分布式锁来解决短时间内插入问题,具体问题是我插入记录后,需要进行查询,如果验证没有就需要新增,验证过程走从库,但是从库没有,就又新插入一条数据,所以就有2份数据了,所以就使用了这个方式来阻止插入2个记录,其实也可以在数据库加入一个多个字段联合的唯一索引来实现,但感觉用数据库的索引来约束成本有点高,就使用redis来实现。

2、之前出现过一次cpu利用率过高情况,排查的思路就是:
1、可能猜测的三个原因就是接口调用量增加了发现也没有,如果是就加机器看看。
2、如果不是,先用top找出cpu高的进程,一般都是java进程,然后在top (-Hp pid)出对应的使用率高的线程,然后线程 id 转化16进制,使用了jstack命令(jstack 419 | grep -A 30 58a)去实际定位某一个线程堆栈的具体代码快,发现是某一行代码的问题:进入了死循环导致cpu过高(使用了阻塞队列,把poll改为take poll会返回null导致一直训练 take会阻塞等待)后来才知道公司有一个JVM性能诊断优化平台,选择主机,去诊断5分钟左右,他会自己生成jvm参数、调用堆栈树生成近一段时间各个方法占用CPU的情况,热点分析树(统计出CPU上调用最频繁的方法)。
3、公司内部听过别人分享过一些频繁gc问题:
主要是yongGC fullGC:
1、因为Metaspace不足引发频繁 Full GC排查:好像原因都是因为使用了一些第三方框架(比如AviatorEvaluator、),第三方框架使用了反射手段,反射生产了大量类的class对象,class对象就是类的元信息保存在Metaspace,XX:SoftRefLRUPolicyMSPerMB参数设置不对,因为反射生产出的类的class对象是软引用,如果设置为0就导致这些软引用对象会被频繁yong GC,GC了对象之后后面的反射又回新增class对象,导致Metaspace记录越来越多的类元信息,最后导致Metaspace full GC。
解决方式有:
1、把框架用反射生产的类的class对象缓存起来,有就使用缓存不会新生产一个类的class对象,就不会往Metaspace区写
2、设置调大一些-XX:SoftRefLRUPolicyMSPerMB=0 参数,这样就不会一直yong GC类的class对象。
2、老年代触发FULL GC,查看gc日志发现gc频繁,出现大量Allocation Failure问题,日志里面记录发现多数情况都是因为在年轻代中没有足够的空间能够存储新的数据问题。并且是一些新生代的大对象导致。就直接分配到老年代,触发FULL GC,应避免在局部构建大对象。
工具方法:
1、使用jmap -heap分析堆使用情况 :
2、方法一般都是使用 jmap -dump:format=b,file=/tmp/dump PID 把线上进程的快照dump下来一份分析。但是如果堆比较大,可能暂停太久了不行 和 jmap -histo:live 或手动触发full gc。

  • 还遇到那些线上问题,怎么去解决的
    我再学习学习

待学习点:
三、关于BIO,NIO,AIO,Netty及Redis线程模型
1、BIO,NIO,AIO的区别?
2、什么是阻塞IO以及非阻塞IO?
3、Reactor和Proactor IO设计模式是什么?
4、NIO底层select、poll和epoll实现的区别 ?
5、Java NIO的几个核心组成部分是什么?作用分别是什么?
6、Redis、Netty、Tomcat的线程模型与NIO的联系是什么?

Future、FutureTask、CompletableFuture的比较

mysql事务隔离级别
1、读未提交 可避免丢失更新,不可避免脏读、不可重复的和幻读
2、读已提交 避免脏读,不可避免不可重复的和幻读
3、可重复读(默认隔离级别) 可避免脏读、不可重复读,不能避免幻读
4、可串行化

面试未答上来的题目:
1、jdk8 默认的收集器:Parallel Scavenge(新生代)+ Serial Old(老年代)
2、mysql查询的时候 查了2个索引 会用哪一个呢:优先使用区分度大的索引
3、mysql执行计划里面有什么:执行计划-ID表示执行的顺序,select_type表示查询类型一共6种,table 表示那张表,type显示查询时,使用了哪种查询类型,日常工作中经常接触到的有以下7种,possible_keys可能使用的索引,keys实际使用的索引,key_len索引字段个数,ref哪个字段使用了索引、rows索引查询时大致出来多少行。
4、消息队列消费的情况,如何保证顺序的消费
5、分布式锁的其他实现方式,redis的结果
答得不好的地方:
线程池,既然都说了,肯定会被问的:
创建线程池的参数:
corePoolSize和maximumPoolSize,来了一个任务,如果线程池中线程不足核心线程数,则新建一个线程,如果线程里面线程数据达到了核心线程数,则进入工作队列中,如果工作队列也满了,当线程数量小于maximumPoolSize的情况下,会新建线程去执行任务,如果线程数据达到了maximumPoolSize,则采用任务拒绝策略,通常有以下四种策略:丢弃任务并抛异常、 丢弃任务但是不抛出异常、丢弃队列最前面的任务然后重新提交被拒绝的任务 、由调用线程处理该任务,一般默认是拒绝任务并抛出异常。当线程池中超过corePoolSize线程,但是空闲时间达到keepAliveTime时,关闭空闲线程,当设置allowCoreThreadTimeOut(true)时,线程池中corePoolSize线程空闲时间达到keepAliveTime也将关闭。
线程池的阻塞队列:

调优:
1、CPU密集型任务
CPU密集型任务的特点是需要大量的运算,CPU全速运行,较少的IO而没有阻塞,所以对于CPU密集型任务,应该尽量减少线程切换带来的消耗,参考配置公式:maximumPoolSize = cpu核数+1
2、IO密集型任务
IO密集型任务刚好相反,CPU占用较少,大量的阻塞,对于这种情况,应该尽量利用CPU的空闲时间,最大线程数应该配置比CPU核心数多,参考配置公式:maximumPoolSize = cpu核数/(1-阻塞系数<0.8~0.9>) 比如依赖其他资源的
3、对于混合任务可以进行拆分处理
4、对于有优先级的任务可以使用优先级阻塞队列处理,问题可能是低优先级的任务一直得不到处理
5、使用有界队列,无界队列可能导致oom
线程池监控:
1、线程池监控参数
getActiveCount() 线程池中正在执行任务的线程数量
getCompletedTaskCount() 线程池已完成的任务数量,该值小于等于taskCount
getCorePoolSize() 线程池的核心线程数量
getLargestPoolSize() 线程池曾经创建过的最大线程数量。
getMaximumPoolSize() 线程池的最大线程数量
getPoolSize() 线程池当前的线程数量
getTaskCount() 线程池已经执行的和未执行的任务总数
2、线程池监控注意事项:
可以继承ThreadPoolExecutor,覆盖beforeExecute和afterExecute方法,做一些自定义监控,比如监控每个线程的执行时间。
如何保证核心线程数不被销毁:
在for无限循环中,通过不断的检查线程池状态和队列容量,来获取可执行任务;
在 Runnable r = timed ? workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) : workQueue.take();代码中,分为两种情况:
1、timed 为 true,允许淘汰 Worker,即实际运行的线程,则通过
workQueue.poll的方式定时等待拉取任务,如果在指定keepAliveTime时间内获取任务则返回,如果没有任务则继续for循环并直到timed等于false;
2、timed 为 false,则会调用 workQueue.take 方法,队列中 take 方法的含义是当队列有任务时,立即返回队首任务,没有任务时则一直阻塞当前线程,直到有新任务才返回。

面试一:
1、你常用的多线程方式?
2、什么是aqs,
aqs: 队列同步器,是用来构建锁或者其他同步组件的基础框架,它使用了一个int成员变量表示同步状态(可见性),通过内置的FIFO队列来完成资源获取线程的排队工作,主要的使用方式是子类来继承它对方法做重写,既可以支持独占式地获取同步状态,也可以支持共享式地获取同步状态,实现的有ReentrantLock、ReentrantReadWriteLock和CountDownLatch等,
同步器依赖内部的同步队列(一个FIFO双向队列)来完成同步状态的管理,当前线程获取同步状态失败时,同步器会将当前线程以及等待状态等信息构造成为一个节点 (Node)并将其加入同步队列,同时会阻塞当前线程,当同步状态释放时,会把首节点中的线程唤醒,使其再次尝试获取同步状态,获取同步状态后可以执行。

2、用spring实现多线程或者用@asenk??注解实现多线程
3、多线程的参数怎么配置的。
4、hashmap
5、二叉查找树与红黑树
6、hashmap为什么线程不安全
7、jdk8 默认的收集器
8、如果你来设计垃圾回收,你怎么设计?
9、怎么判断变量要回收
10、垃圾的回收的更节点都包含哪些?
11、除了可达性分析之外,还有那些?引用计数法,2种算法那种效率高?
12、你在这边都做了哪些业务?把业务说清楚
13、mysql索引:查了2个索引 会用哪一个呢:优先使用区分度大的索引
14、联合索引情况下,建立顺序(a\b\c),ab去查询可以 最左前缀匹配原则
15、编程题目:合并2个有序链表到一个
16、编程题目:对个有序链表合并为一个

面试二:
1、有没有遇到线上问题 系统不稳定 内存挂了等?
2、机器有内存泄露 怎么排查?需要把排查过程说清楚,包括每一步用到了什么命令
3、慢查询优化:
4、其他索引失效方式:
5、mysql 执行计划是什么:
6、索引:主键、联合、普通 三种索引有什么区别呢、执行起来有什么不一样呢、sql执行的逻辑有什么不一样
主键索引:不为空且唯一
唯一索引:唯一
普通索引:
联合索引:为了更多的提高mysql效率可建立组合索引,遵循”最左前缀“匹配的原则。
7、线程池的核心参数
8、你知道的java的锁有哪些 每一种的使用场景。
公平锁/非公平锁:公平锁需要通过AQS的来实现线程调度。
可重入锁:lock和Synchronized都是可重入的
独享锁/共享锁:ReentrantLock和Synchronized都是独享锁,ReadWriteLock的读锁是、写锁是
互斥锁/读写锁:
乐观锁/悲观锁
分段锁
偏向锁/轻量级锁/重量级锁
自旋锁

9、Synchronized用的几种场景,锁的是什么?Synchronized可以在普通的方法上加锁吗,可以在静态方法加锁吗
10、lock与Synchronized区别,什么时候使用Synchronized 什么时候使用lock。
第一个实现方式上:Synchronized是java关键字,在jvm上实现,lock是一个接口
可重入lock实现是基于aqs抽象的队列同步器+lock接口实现的。
第二个锁释放方式上:Synchronized会自己释放,lock需要自己调用unlock,所以需要写在fially中。
第三个是否可中断等待:Synchronized不能等待中断只能等待其他线程释放锁,而lock可以主动中断等待。
第四个是能否知道是否已获取锁,Synchronized无法知道,lock锁可以使用trylock.
第五个,lock有读写锁的实现,可以提高并发读场景下的效率,读写锁还可以使用锁降级,读锁降级为写锁,在一边读一边写的情况下提高性能。
第六个在性能上,竞争不激烈情况下,差不多,但是竞争激烈情况下,此时Lock的性能要远远优于synchronized。在具体使用时要根据适当情况选择。
第七个锁的调度方式:synchronized使用Object对象本身的wait 、notify、notifyAll调度机制,而Lock可以使用Condition进行线程之间的调度,Condition可以指定唤醒等待的某一个线程。Condition:
第八个2种锁的锁机制不同:synchronized采用悲观锁机制,线程获得的是独占锁。独占锁意味着其他线程只能依靠阻塞来等待线程释放锁。Lock用的是乐观锁方式使用CAS操作,实现了独享锁和共享锁,比如readwritelock。
第九个,Synchronized是使用对象上进行加锁阻塞线程(对象的wait和notify方法),lock是通过阻塞线程的方式进行。(park unpark一个线程)

11、什么是公平锁和非公平锁
1、公平锁的新入线程不能直接获取锁,必须去排队(除非没有任何竞争发生)。而非公平锁新入的线程则可以先尝试获取锁,如果失败了再排队。
2、非公平锁在 CAS 失败后,和公平锁一样都会进入到 tryAcquire 方法,在 tryAcquire 方法中,如果发现锁这个时候被释放了(state == 0),非公平锁会直接 CAS 抢锁,但是公平锁会判断等待队列是否有线程处于等待状态,如果有则不去抢锁,乖乖排到后面。

12、性能调优:

面试三:
1、通过kafka是几个分区?同一个商家2次状态变更,其中一个服务处理延迟了到es的顺序就乱续了怎么解。
kafka:

2、分布式锁?分布式锁的数据结构用的是什么 redis的数据结结构 kv的命令是什么 redis的操作命令 还有其他实现分布式锁的方式吗,
3、对推荐系统有了解吗
4、数据结构里面,跳跃表了解吗,有序的链表里面怎么实现logn的差查找时间复杂度
5、100个无序重复数据,找到前K个最大的数,使用大根堆,小根堆,或者使用分片方式。

面试四:
1、spring内部的体系了解的怎么样 spring的bean的生命周期
2、springCloud相关的
3、从客户端测 在rpc层面做故障保护或容错
4、从技术侧去推进的一些东西
5、开线程池 怎么评估核心线程数 和最大线程数(怎么去评估参数设置),
6、取决于cpu密集型和io密集型,io密集型对cpu占用其实是没有的,如果线程数不合理,请求大的情况下,队列满了,
7、线程池与ForkJoin的区别
ForkJoin:是一个把大任务分割成 若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架。有一个窃取算法:当某一个线程执行完队列的任务后,可以帮其他线程从尾部那任务执行,ForkJoin2种创建方式:[rɪˈkɜːsɪv]RecursiveAction用于没有返回结果的任务、RecursiveTask用于有返回结果的任务。

8、线程池涉及的线程安全问题怎么处理,
9、如果管理不好,每次追加数据,TL出现内存泄露怎么处理,如果是存在线程里面的东西,线程回收了就回收了,如果是多线程,线程一直在,怎么防止内存泄露
ThreadLocalMap的key为弱引用,那么在下一次垃圾回收的时候必然会被清理掉,会存在key是null的value,所以在每次调用get set remove方法的时候,它会清理key是null的值,但是如果我们没有调用这些方法,会存在泄露 最好手动执行remove方法。
10、TL\ITL、TTL各使用场景
11、线程池底层怎么做线程抢占,2个work怎么去做抢占,怎么保证线程抢占的原子性操作
12、aqs
13、平常怎么样方式做计算上的提升的?
14、中间件方面的关注
15、jvm相关:排查处理问题经历?怎么定位是那块代码的问题?
16、老年代增长厉害 full GC 但是回收率高,产生问题的原因,怎么消除:大对象进入老年的、GC年龄默认15但是有一种动态年龄判断,如果在Survivor空间中相同年龄所有对象大小的总和大于 Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代

17、假设设计一个文件缓存系统做页面静态化,设计一个文件缓存系统提高性能:既能提高命中率又能,
18、java怎么实现lru,除了使用linkhashmap,查的时候需要足够快,删也足够快,
19、FIFO 与LRU的区别
20、后续工作寻找岗位

面试五:
1、java的hashmap
2、给一个key,怎么查找过程
3、为什么链表转红黑树
4、操作系统进程与线程的区别,怎么理解,进程里面的资源分配的是什么?从内存角度,进程与线程区别,进程与进程通信 线程与线程通信有什么差别,
5、服务端应用的监控有了解吗,有什么监控手段
6、

面试六:
1、kafka队列知识
2、kafka怎么消费数据收发数据,有没有实际去发过消息
3、ES
4、mysql
5、redis
6、ssm
7、rpc
8、

二面情况:
面试一:
介绍项目:
1、调一个项目介绍
1、需求是什么、上游和下游是什么 对系统拆解是什么的、从0到1
2、架构是什么,你是什么考虑,你觉得的亮点是什么,在里面你承担的一个角色,
3、我做的部分、做资金管控的考核指标是什么
4、业务上遇到什么坑?
5、2个入口实现是一致的吗 人进入是后台的p
6、用户登录校验是怎么做的?怎么维护用户的登录信息
7、这个userUtils是怎么进来的呢,集成他的sso
8、你能描述一下整个系统怎么跑的吗(SSO),
9、用户点开主页,有没有可能用户当前没有登录,会跳出统一登录页面,还有很多情况,也是没有用户登录信息,所有的sessioncookie都没有,怎么跳到sso,怎么调回来,
10、对未鉴权的请求,在什么地方做了拦截。
todo:请同事给我讲一下sso.
11、系统是微服务吗?
12、你们系统的基础架构是什么样的?
13、用什么样的容器发布呢
14、这个过程就是,你发布了这几个服务的实例,你的服务怎么和其他服务做交互呢?
15、你发多少个实例,你是怎么去管理的,在应用里面怎么知道用那个实例和下游做交互,给了一个url,怎么说这一次的http请求应该到哪一个服务的实例上去,
16、工作的服务要调其他的服务,怎么知道往哪儿调的呢?
17、rpc框架Thrift,有没有给到一个jar包给到调用方,
18、单单的这一个jar包,他是怎么知道下游有几个服务实例来支撑这一次请求呢?
19、其中一个服务挂了,或者从2个扩展4个对方无感知,这块你知道是什么原理吗?
20、合并K个链表
21、应用和应用调用的问题,rpc请求,一定会遇到网络异常,发送成功未回执,1、你认为会发生什么可能性,你怎么解决
22、处理后未回执怎么处理
23、

滴滴面试:
1、从技术上讲,大概是什么流程,做的时候有什么不好解决的点。
2、题目:括号匹配
z_set怎么实现的:
3、innodb索引是什么结构、为什么选择B+树,如果用B树呢,我们希望id是递增,如果不递增会有什么问题、我一直往后加也会调整的、innobd隔离级别,四个分别解决什么问题、解释一下什么是张读、换读、不可重复读
4、redis,几种常用数据结构、z_set怎么实现的,跳跃表如果插入元素什么过程
5、秒杀系统,30台机器,预估会有5000万人来抢, 货品共2万,不可以超卖,可以少量少卖,我的下游有订单,商品,库存,支付等等
6、对这个系统:qps承担不足怎么解决、
使用限流的方式,有以相同速率生产令牌的令牌桶算法,令牌桶满了直接丢弃令牌,只有拿到令牌的用户可以进入系统;漏桶算法基本思路请求过来后加入桶内(可排队或非排队),超过桶大小则抛弃返回每秒通过恒定速率的请求到业务层
在那一层做:
7、怎么防止有人攻击我们,别人刷怎么预防
9、限流限到多少合适,怎么预估
10、怎么保证货物不超卖
12、我有很多下游,怎么保证下游的分布式的一致性
13、下游某一个系统失败了,怎么回滚,
14、怎么保证其他系统的一致性,和支付对上了,但是有一个订单怎么办呢
15、下游没有配合压测,把下游挂了,应该怎么办
16、

秒杀系统的问题点
1、对现有网站业务造成冲击
解决方案:将秒杀系统独立部署,甚至使用独立域名,使其与网站完全隔离。
2.高并发下的应用、数据库负载
解决方案:重新设计秒杀商品页面,不使用网站原来的商品详细页面,页面内容静态化,用户请求不需要经过应用服务。
3.突然增加的网络及服务器带宽
解决方案:因为秒杀新增的网络带宽,必须和运营商重新购买或者租借。为了减轻网站服务器的压力,需要将秒杀商品页面缓存在CDN,同样需要和CDN服务商临时租借新增的出口带宽。
4.直接提前下单
解决方案:为了避免用户直接访问下单页面URL,需要将改URL动态化,即使秒杀系统的开发者也无法在秒杀开始前访问下单页面的URL。办法是在下单页面URL加入由服务器端生成的随机数作为参数,在秒杀开始的时候才能得到。
5.如何控制秒杀商品页面购买按钮的点亮
6.如何只允许第一个提交的订单被发送到订单子系统

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值