面试题day8
阿里菜鸟
-
二叉搜索树遍历思路?
前中后
根左右 左根右 左右根
-
数据库索引原理?
b+树,遍历层级低,io次数少
非自增id,维护索引代价很大(页分裂);空间占用大;
-
有什么类型索引?各有什么特点?
对比hash索引、数组索引、b+树
- hash索引 无法范围查询
- 数组查询 维护成本高
-
inner join,left join,right join区别
保留记录不同,左连接右补null,右连接左补null
-
高并发的时候,请求量非常大,同时更新数据库的一条数据,这时候应该怎么处理,用锁和不用锁,怎么设计?
使用锁
- 悲观锁,select for update
- 乐观锁,版本号机制/对库存进行判断
不使用锁
- 消息队列,串行化io
-
用缓存怎么实现锁?
redis分布式锁
-
redis为什么能实现分布式锁?除了redis能实现还有其他实现方式吗
set nx
-
redis怎么部署的?
答单机和多机部署。
-
限流是怎么实现的,对什么限流?
-
外界怎么访问接口?
-
BIO和NIO区别
- NIO以流的方式处理数据,NIO以块的方式处理数据,块IO的效率比流IO高很多。
- BIO是阻塞的,NIO是非阻塞的
- BIO基于字节流和字符流进行操作的,而NIO基于Channel(通道)和Buffer(缓冲区)进行操作的
-
线程池原理,有什么参数?
- 线程在有任务的时候会创建核心的线程数corePoolSize
- 当线程满了(有任务但是线程被使用完)不会立即扩容,而是放到阻塞队列中,当阻塞队列满了之后才会继续创建线程。
- 如果队列满了,线程数达到最大线程数则会执行拒绝策略。
- 当线程数大于核心线程数时,超过KeepAliveTime(闲置时间),线程会被回收,最终会保持corePoolSize个线程。
核心线程数 最大线程数 阻塞队列 线程工厂 存活时间 时间单位 拒绝策略
-
为什么要用线程池?
- 降低资源消耗
- 提高响应速度
- 提高线程的可管理性
-
threadlocal是干嘛的?
每个线程创建变量副本,这样就可以保证一个线程对某个变量的修改不会影响到其他线程对该变量的使用。
ThreadLocal是基于每个线程对象内部的一个叫做threadLocals的属性来实现的,它的类型是ThreadLocalMap(说白了就是一个Map对象)。它以ThreadLocal本本身作为键值,副本对象作为value存储,这样当每个线程调用该对象时就可以直接从自身的threadLocals属性中获取变量副本来进行操作。
-
jvm内存模型
堆 直接内存 方法区 虚拟机栈 本地方法栈 程序计数器
对方法区回收,判断类失效
-
什么会导致栈溢出、堆内存溢出?
线程,递归深度超过最大栈深度
对象,对象创建过多
-
怎么排查堆溢出
线程,jstack
对象,jconsole,jmap
-
对springboot理解,它主要特性是什么
auto-configuration 自动装配
starter 模块启动器 在pom.xml中引入相关启动器 就可以使用对应的模块功能
springboot cli 一个命令行使用Spring Boot的客户端工具
actuator Spring Boot的监控插件,本身提供了很多接口可以获取当前项目的各项运行状态指标。
用友
-
springboot自动装配原理
Spring Boot的自动装配得益于Spring推出了JavaConfig的这种模式,Java开发人员可以通过@Configuration + @Bean的方式向Spring IOC容器注入Bean。每个场景启动器其实都添加了一个这样的JavaConfig,只要这些JavaConfig配置类能被加入到IOC容器,那么自然而然的就可以自动注入JavaConfig提供的Bean。
-
进程线程协程区别
进程 资源调度单位
线程 任务执行的单位(切换成本高,且线程数量也受内存限制)
协程 协程运行在线程之上,当一个协程执行完成后,可以选择主动让出,让另一个协程运行在当前线程之上。(协程的切换在用户态完成,切换的代价小)
-
讲讲内存空间
在计算机中,内存空间一般是指主存储器空间(物理地址空间)或系统为一个用户程序分配内存空间。扩展内存空间的方法一般有增加内存大小和虚拟内存
-
索引 select a from database where b=xxx最好的方法?
对b加联合索引,覆盖索引
-
问我项目里面的redis用于哪些功能?
缓存、分布式锁、一人多单
-
怎么设计一个系统?
字节
国际化电商,一面
-
介绍腾讯实习的项目
-
关系型数据库和非关系型数据库
mysql、oracle
redis、mongodb
关系型和非关系型数据库的主要差异是数据存储的方式。关系型数据天然就是表格式的,因此存储在数据表的行和列中。数据表可以彼此关联协作存储,也很容易提取数据。
SQL和NoSQL数据库最大的差别可能是在扩展方式上,要支持日益增长的需求当然要扩展。
如果数据操作需要高事务性或者复杂数据查询需要控制执行计划,那么传统的SQL数据库从性能和稳定性方面考虑是你的最佳选择。SQL数据库支持对事务原子性细粒度控制,并且易于回滚事务。
-
数据库的引擎
innodb、myisam
适用场景 读少写多 读多写少
索引结构 事务 锁粒度 b+树 mvcc
-
Sql语句
sql优化
sql语句执行过程
-
数据库的锁
行锁 表锁 页面锁
意向锁 间隙锁
读锁 写锁
-
数据库的隔离状态
隔离级别 ru rc rr 串行化
-
怎么防止幻读
next-key innodb+rr 解决幻读问题
mvcc 解决幻读(主动进行当前读,幻读依旧存在)
对于InnoDB存储引擎,每一行记录都有两个隐藏列trx_id、roll_pointer,如果表中没有主键和非NULL唯一键时,则还会有第三个隐藏的主键列row_id。
undo log,回滚日志,用于记录数据被修改前的信息。在表记录修改之前,会先把数据拷贝到undo log里,如果事务回滚,即可以通过undo log来还原数据。
read-view,当执行SQL语句查询时会产生一致性视图,它是由查询的那一时间所有未提交事务ID组成的数组,和已经创建的最大事务ID组成的。
- 获取事务自己的版本号,即事务ID
- 获取Read View
- 查询得到的数据,然后Read View中的事务版本号进行比较。
- 如果不符合Read View的可见性规则, 即就需要Undo log中历史快照;
- 最后返回符合规则的数据
-
DNS的过程
域名解析
-
处理中断,恢复中断
-
程序编译的过程
-
http的缓存机制
1.1 长连接,缓存资源
-
乐观锁和悲观锁
先操作后验证 多读少写
先加锁后操作 多写少读
字节
国际化电商,二面
-
聊腾讯实习项目
-
问为什么算法转开发
-
操作系统内存管理
-
逻辑地址和物理地址的转化
-
http状态码
100 服务器收到请求,需要请求者继续执行操作
200 成功
300 重定向
400 客户端报错 401 无权限 403 拒绝请求 404 无法根据客户端的请求找到资源
500 服务器报错
-
tcp怎么保证可靠性
三次握手四次挥手
校验和、ACK 应答、超时重传
流量控制(滑动窗口)和拥塞控制来控制发送方发送速率
-
tcp的拥塞控制
慢开始
慢开始发生在最开始,这个时候不断试探网络是否把握的住,拥塞窗口(cwnd)以2^n的增速开始增长,然后到了设置的阈值,我们就采取拥塞避免的算法每次加一的试探网络,当然后面肯定避免不了超时,我们这时候阈值设为当前阈值的一半,我们重新开始慢开始,到达现在的阈值开始拥塞避免。
拥塞避免
每个传输轮次,拥塞窗口cwnd只能线性加一,而不是像慢开始算法时,每个传输轮次,拥塞窗口cwnd按指数增长。
快速重传
接收器接收到一个不按顺序的数据段,接收器会立马给发送器发送重复确认,如果发送机接收到三个重复确认,它会假定确认件支出的数据段丢失了。这样就不会造成发送方对后面报文出发超时重传,而是提早收到了重传。然后开始快恢复算法。
快恢复算法
发送方一旦收到3个重复确认,就知道现在只是丢失了个别的报文段。于是不启动慢开始算法,而执行快恢复算法;
- 发送方将慢开始门限ssthresh值和拥塞窗口cwnd值调整为当前窗口的一半;开始执行拥塞避免算法。
- 也有的快恢复实现是把快恢复开始时的拥塞窗口cwnd值再增大一些,即等于新的ssthresh + 3。
既然发送方收到3个重复的确认,就表明有3个数据报文段已经离开了网络;
这3个报文段不再消耗网络资源而是停留在接收方的接收缓存中;
可见现在网络中不是堆积了报文段而是减少了3个报文段。因此可以适当把拥塞窗口犷大些。
-
粘包,拆包
TCP是个“流”式的协议,所谓流,就像河里的水,中间没有边界。TCP传输的数据,在网络上就是一连串的数据,没有分界线。TCP协议的底层,并不了解上层业务的具体定义,它会根据TCP缓冲区的实际情况进行包的划分。在业务层面认为一个完整的包,可能会被TCP拆分成多个小包进行发送,也可能把多个小的包封装成一个大的数据包进行发送,这就是所谓的TCP粘包拆包问题。
TCP数据流最终发到目的地,需要通过以太网协议封装成一个个的以太网帧发送出去,以太网数据帧大小最小64字节,最大1518字节,除去header部分,其数据payload为46到1500字节。所以如果以太网帧的payload大于MTU(默认1500字节)就需要进行拆包
解决方法
- 消息定长,发送方和接收方规定固定大小的消息长度,例如每个报文大小固定为200字节,如果不够,空位补空格;
- 在包围增加特殊字符进行分割,例如FTP协议;
- 自定义协议,将消息分为消息头和消息体,消息头中包含消息总长度,这样服务端就可以知道每个数据包的具体长度了,知道了发送数据包的具体边界后,就可以解决粘包和拆包问题了;
-
http1.0 1.1 1.2区别
- 新的二进制格式:HTTP1.1基于文本格式传输数据;HTTP2.0采用二进制格式传输数据,解析更高效。
- 多路复用:在一个连接里,允许同时发送多个请求或响应,并且这些请求或响应能够并行的传输而不被阻塞。
- 头部压缩,HTTP1.1的header带有大量信息,而且每次都要重复发送;HTTP2.0把header从数据中分离,并封装成头帧和数据帧,使用特定算法压缩头帧,有效减少头信息大小。并且HTTP2.0在客户端和服务器端记录了之前发送的键值对,对于相同的数据,不会重复发送。比如请求a发送了所有的头信息字段,请求b则只需要发送差异数据,这样可以减少冗余数据,降低开销。
- 服务端推送:HTTP2.0允许服务器向客户端推送资源,无需客户端发送请求到服务器获取。
-
输入数组nums,要求输出升序排序后的结果。已知数组元素为非负整数,且当数组长度为n时,所有元素的值都小于n;时间复杂度为O(n)
字节
商业化技术,一面
-
聊项目大概十五分钟
-
http报文格式
请求行 请求头 请求体
响应行 响应头 响应体
post和get
- get请求一般是去取获取数据(其实也可以提交,但常见的是获取数据);post请求一般是去提交数据。
- get因为参数会放在url中,所以隐私性,安全性较差,请求的数据长度是有限制的,更加常见的是 1k 以内;post请求是没有的长度限制,请求数据是放在body中;
- get请求刷新服务器或者回退没有影响,post请求回退时会重新提交数据请求。
- get请求可以被缓存,post请求不会被缓存。
- get请求会被保存在浏览器历史记录当中,post不会。get请求可以被收藏为书签,因为参数就是url中,但post不能。它的参数不在url中。
- get请求只能进行url编码(appliacation-x-www-form-urlencoded),post请求支持多种(multipart/form-data等)。
-
sql两种引擎区别
innodb myisam
外键 事务 mvcc 锁粒度 索引结构 场景
-
聚簇索引和非聚簇索引
数据和索引存储位置
-
Sql语句查询前七天数据
-
用户态和内核态
- 用户态和内核态是操作系统的两种运行级别,两者最大的区别就是特权级不同
- 用户态拥有最低的特权级,内核态具有较高的特权级
- 运行在用户态的程序不能直接访问操作系统内核结构和数据
- 操作系统数据都是存放于系统空间的,用户态进程的数据是存放在用户空间的,分开来存放就是为了让系统的数据和用户的数据互不干扰,保证系统的稳定性,分开存放,管理上比较方便,并且对于两部分数据的访问就可以进行控制,避免用户态程序恶意修改操作系统的数据和结构
-
Get post还有什么方式
put delete
-
登录的时候用什么保存状态
session和cookie,都是用来记录用户的状态的方式
- 作用范围不同,Cookie 保存在客户端(浏览器),Session 保存在服务器端。
- 存取方式的不同,Cookie 只能保存 ASCII,Session 可以存任意数据类型,一般情况下我们可以在 Session 中保持一些常用变量信息
- 有效期不同,Cookie 可设置为长时间保持;Session 一般失效时间较短,客户端关闭或者 Session 超时都会失效。
- 隐私策略不同,Cookie 存储在客户端,比较容易遭到不法获取;Session 存储在服务端,安全性相对 Cookie 要好一些。
- 存储大小不同, 单个 Cookie 保存的数据不能超过 4K,Session 可存储数据远高于 Cookie。
分布式session
- Nginx ip_hash 策略,服务端使用 Nginx 代理,每个请求按访问 IP 的 hash 分配,这样来自同一 IP 固定访问一个后台服务器,避免了在服务器 A 创建 Session,第二次分发到服务器 B 的现象。
- Session 复制,任何一个服务器上的 Session 发生改变(增删改),该节点会把这个 Session 的所有内容序列化,然后广播给所有其它节点。
- 共享 Session,服务端无状态话,将用户的 Session 等信息使用缓存中间件来统一管理,保障分发到每一个服务器的响应结果都一致。
-
最小栈怎么实现
-
N叉树每层求最大值