面试过程
1. 美团一面挂
1.1 为什么没转计算机?
1.2 什么时候开始自学?
1.3 webserver是跟视频学还是怎么样学?
1.4 线程池,为什么要做线程池
1.5 work解析请求是不是在线程池里面做的?
1.6 工作线程用线程池,线程池开的多大?
最直接的限制因素是CPU处理器的个数。
如果CPU是4核的,那么对于CPU密集的任务,线程池的线程数量最好也为4,或者+1防止其他因素导致阻塞。
如果是IO密集的任务,一般要多于CP的核数,因为 IO 操作不占用 CPU,线程间竞争的不是CPU资源而是IO,IO的处理一般比较慢,多于核数的线程将为CPU争取更多的任务,不至于在线程处理IO的时候造成CPU空闲导致资源浪费。
而对于混合型的任务,如果可以拆分,拆分成 IO 密集型和 CPU 密集型分别处理,前提是两者运行的时间是差不多的,如果处理时间相差很大,则没必要拆分了。
如果任务执行时间长,在工作线程数量有限的情况下,工作线程很快就很被任务占完,导致后续任务不能及时被处理,此时应适当增加工作线程数量;反过来,如果任务执行时间短,那么工作线程数量不用太多,太多的工作线程会导致过多的时间浪费在线程上下文切换上。
回到这个问题本身来,这里的“高并发”应该是生产者生产任务的速度比较快,此时需要适当增大任务队列上限。
但是对于第三个问题并发高、业务执行时间长这种情形单纯靠线程池解决方案是不合适的,即使服务器有再高的资源配置,每个任务长周期地占用着资源,最终服务器资源也会很快被耗尽,因此对于这种情况,应该配合业务解耦,做些模块拆分优化整个系统结构。
1.7 解析完请求要查数据库,是不是也是在线程里面做的呢
1.8 开了8个线程,假设有一个查询用了100ms会不会影响qps?
1. 高并发、任务执行时间短的业务怎样使用线程池?
2. 并发不高、任务执行时间长的业务怎样使用线程池?
3. 并发高、业务执行时间长的业务怎样使用线程池?
线程池本质上是生产者和消费者模型,包括三要素:
往线程池队列中投递任务的生产者;
任务队列;
从任务队列取出任务执行的工作线程(消费者)。
要想合理的配置线程池的大小,得分析线程池任务的特性,可以从以下几个方面来分析:
根据任务的性质来分:CPU 密集型任务;IO 密集型任务;混合型任务。
根据任务的优先级:高、中、低
根据任务的执行时间:长、中、短
不同性质的任务可以交给不同配置的线程池执行。
1.9 开了8个线程,假设要处理比较慢的逻辑,这些逻辑放在工作线程是不是会阻塞掉,不断地cup密集,IO密集,性能会比较差吗
会影响接下来的客户请求,因为线程池内线程的数量时有限的,如果客户请求占用线程时间过久的话会影响到处理请求的效率,当请求处理过慢时会造成后续接受的请求只能在请求队列中等待被处理,从而影响接下来的客户请求。
应对策略:
我们可以为线程处理请求对象设置处理超时时间, 超过时间先发送信号告知线程处理超时,然后设定一个时间间隔再次检测,若此时这个请求还占用线程则直接将其断开连接。
给每一个线程处理任务设定一个时间阈值,当某一个客户请求时间过长,则将其置于任务请求最后,或断开连接。
1.10 请求解析的逻辑用单独的线程去处理吗?
1.11 negix的提问,他这样的工作是通过多进程的方式去实现的
1.12 多进程方式去实现这样的工作线程可以吗?会有什么优缺点?
1.13 如果我开8个进程的池和8个线程的池去处理?有什么区别?
1.14 目前的qps大概是多少
1.15 如果需要达到20000qps或者30000的qps你有什么优化策略?
在集群化的架构下,可以采用池化(内存池,连接池,线程池),分布式缓存,分布式消息队列,流控技术(服务降级,应用拆分,限流)和数据库高并发(分库分表,读写分离等)提高并发能力
增加并发数
后端开发的尽量无服务状态,可以更好的横向扩展
数据库的连接请求量、服务器的连接数、以及与服务器匹配的线程数,满足更多的需求
内存池
:通过malloc的分配(大小合适的内存适应相应的内存)
线程/线程池
:充分利用资源,减少开销
连接池
:数据库预先创建好连接给线程等(提高速度)减少平均响应时间
Mq:流量削峰,适当的给流量减压,还可以使用mq进行降低接口的延迟
redis缓存
:进行写少读多的缓存压力
算法
:优化程序(通过调用一些算法),可看我这篇文章:java中常见的限流算法详细解析
网络层面
:减少网络开销,适当长连接或者短连接
数据库层面
:尽量命中索引(单库中尽量MVCC在不加锁的情况下,实现并发读写,同时通过事务隔离级别控制并发效率。)(集群中分库分表,读写分离等)
流控
:通过服务降级服务优化等
1.16 哈希表是如何解决哈希冲突的
1.17 实际有使用什么设计模式?
1.18 为什么要用单例模式,出了单例模式还了解什么设计模式
1.19 mysql单表为什么建议不要超过500万的数据,只考虑单表情况,为什么不要超过500W的数据?
事实上,这个数值和实际记录的条数无关,而与 MySQL 的配置以及机器的硬件有关。因为,MySQL 为了提高性能,会将表的索引装载到内存中。InnoDB buffer size 足够的情况下,其能完成全加载进内存,查询不会有问题。但是,当单表数据库到达某个量级的上限时,导致内存无法存储其索引,使得之后的 SQL 查询会产生磁盘 IO,从而导致性能下降。当然,这个还有具体的表结构的设计有关,最终导致的问题都是内存限制。这里,增加硬件配置,可能会带来立竿见影的性能提升哈。
那么,我对于分库分表的观点是,需要结合实际需求,不宜过度设计,在项目一开始不采用分库与分表设计,而是随着业务的增长,在无法继续优化的情况下,再考虑分库与分表提高系统的性能。对此,阿里巴巴《Java 开发手册》补充到:如果预计三年后的数据量根本达不到这个级别,请不要在创建表时就分库分表。那么,回到一开始的问题,你觉得这个数值多少才合适呢?我的建议是,根据自身的机器的情况综合评估,如果心里没有标准,那么暂时以 500 万行作为一个统一的标准,相对而言算是一个比较折中的数值。
1.20 mysql可重复读的实现原理?
1.21 做一道链表翻转的题
QA
请问对我的学习有什么建议?
1.口语表达
2.基本功 操作系统,网络,
8个进程 IO密集 work可以在多线程,多进程 后面的逻辑放在线程池里面做
3.如果要转业务开发 java,mysql,Redis,spring可以多看看