更多、更全、更新 BATJ 等大厂面试题+Q 群:762073882
零声学院整理出品
2020 年阿里精选面试题及答案
1. 使用 mysql 索引都有哪些原则?索引什么数据结构?
B+tree 和 B tree 什么区别?
1、 对于查询频率高的字段创建索引;
2、 对排序、分组、联合查询频率高的字段创建索引;
3、 索引的数目不宜太多
原因: a、每创建一个索引都会占用相应的物理控件;
b、过多的索引会导致 insert、update、delete 语句的执行效率降低;
4、若在实际中,需要将多个列设置索引时,可以采用多列索引
如:某个表(假设表名为 Student),存在多个字段(StudentNo, StudentName, Sex,
Address, Phone,BirthDate),其中需要对 StudentNo,StudentName 字段进行查询,对
Sex 字段进行分组,对 BirthDate 字段进行排序,此时可以创建多列索引 index
index_name (StudentNo, StudentName, Sex, BirthDate);#index_name 为索引名
在上面的语句中只创建了一个索引,但是对 4 个字段都赋予了索引的功能。
创建多列索引,需要遵循 BTree 类型,即第一列使用时,才启用索引。
在上面的创建语句中,只有 mysql 语句在使用到 StudentNo 字段时,索引才会被启
用。
如:
select * from Student where StudentNo = 1000; #使用到了 StudentNo
字段,索引被启用。
以使用 explain 检测索引是否被启用如:explain select * from Student where
StudentNo = 1000;
5、选择唯一性索引
唯一性索引的值是唯一的,可以更快速的通过该索引来确定某条记录。例如,学生
表中学号是具有唯 一性的字段。为该字段建立唯一性索引可以很快的确定某个学生的
信息。如果使用姓名的话,可能存
6、尽量使用数据量少的索引
在同名现象,从而降低查询速度。
如果索引的值很长,那么查询的速度会受到影响。例如,对一个 CHAR(100)类型的
字段进行全文检索
需要的时间要多。
7、尽量使用前缀来索引
需要的时间肯定要比对 CHAR(10)类型的字段
如果索引字段的值很长,最好使用值的前缀来索引。例如,TEXT 和 BLOG 类型的字
段,进行全文检 索会很浪费时间。如果只检索字段的前面的若干个字符,这样可以提
高检索速度。
8、删除不再使用或者很少使用的索引.
表中的数据被大量更新,或者数据的使用方式被改变后,原有的一些索引可能不再
需要。数据库管理 员应当定期找出这些索引,将它们删除,从而减少索引对更新操作
的影响 B+ tree 树索引, B tree,散列
更多、更全、更新 BATJ 等大厂面试题+Q 群:762073882
零声学院整理出品
2. Mysql 有哪些存储引擎?请详细列举其区别?
InnoDB: 事务型存储引擎, 并且有较高的并发读取频率
MEMORY: 存储引擎,存放在内存中,数据量小, 速度快
Merge:
ARCHIVE: 归档, 有很好的压缩机制
3. 设计高并发系统数据库层面该如何设计? 数据库锁有哪
些类型?如何实现?
1. 分库分表: 同样量的数据平均存储在不同数据库相同表(或不同表)中,减轻单表
压力,如果还是很大,就可以每个库在分多张表,根据 hash 取值或者其他逻辑判断将
数据存储在哪张表中
2. 读写分离: 数据库原本就有主从数据库之分,查询在从服务器,增删改在主服务器,
3. 归档和操作表区分: 建一张归档表,将历史数据放入,需要操作的表数据单独存储
4. 索引啊之类的创建,对于数据量很大,百万级别以上的单表,如果增删改操作不频
繁的话, 可以创建 bitMap 索引,速度要快得多
1. 共享锁:要等第一个人操作完,释放锁,才能操作
2. 更新锁:解决死锁,别人可以读,但不能操作
3. 排他锁:读写都被禁用
4. 意向锁(xlock): 对表中部分数据加锁,查询时,可以跳过
5. 计划锁: 操作时,别的表连接不了这张表,
4. 数据库事务有哪些?
原子性: 所有操作要么全部成功,要么全部失败
一致性: 例如转账,一个事务执行前和执行后必须一致
隔离性: 防止脏读, 重复读问题
持久性: 永久性提交数据库
5. Oracle 常用函数有哪些?
Concat: 字符串拼接, 或者 ||
MConcat: 字符串拼接, 或者 ||
Instr: 指定字符串位置
Length: 长度
Trim: 去空格
更多、更全、更新 BATJ 等大厂面试题+Q 群:762073882
零声学院整理出品
Lower: 小写
Upper:大写
Nvl: 判断空
Replace: 替换
Substr: 截取
Floor: 向下取整
To_number:
To_char:
To_date:
Decode: 判断函数等等
6. Sql 中哪些情况可能不会走索引?
1. 查询谓词没有使用索引的主要边界,换句话说就是 select *,可能会导致不走索
引
2. 单键值的 b 树索引列上存在 null 值,导致 COUNT(*)不能走索引。索引列存在空
值
3. 索引列上有函数运算,导致不走索引
4. 隐式类型转换导致不走索引。
5. 表的数据库小或者需要选择大部分数据,不走索引
6. !=或者<>(不等于),可能导致不走索引
7. 表字段的属性导致不走索引,字符型的索引列会导致优化器认为需要扫描索引大
部分数据且聚簇因子很大,最终导致弃用索引扫描而改用全表扫描方式,
8. 使用 like, in 等, 可能导致不走索引
7. 讲讲分布式唯一 ID?
确定 ID 存储用 64 位,1 个 64 位二进制 1 是这样的 00000000.....1100......0101,切
割 64 位,某段二进制表示成 1 个约束条件,前 41 位为毫秒时间,后紧接 9 位为 IP,
IP 之后为自增的二进制,记录当前面位数相同情况下是第几个 id,如现在有 10 台机器,
这个 id 生成器生成 id 极限是同台机器 1ms 内生成 2 的 14 次方个 ID。
分布式唯一 ID = 时间戳 << 41 位, int 类型服务器编号 << 10,序列自增 sequence。
每个时间戳内只能生成固定数量如(10 万)个自增号,达到最大值则同步等待下个时
间戳,自增从 0 开始。将毫秒数放在最高位,保证生成的 ID 是趋势递增的,每个业务
线、每个机房、每个机器生成的 ID 都是不同的。如 39bit 毫秒数|4bit 业务线|2bit
机房|预留|7bit 序列号。高位取 2016 年 1 月 1 日 1 到现在的毫秒数,系统运行 10 年,
至少需要 10 年 x365 天 x24 小时 x3600 秒 x1000 毫秒=320x10~9,差不多 39bit 给毫秒
数,每秒单机高峰并发小于 100,差不多 7bit 给每毫秒的自增号,5 年内机房小于 100
台机器,预留 2bit 给机房,每个机房小于 100 台机器,预留 7bit 给每个机房,业务线
小于 10 个,预留 4bit 给业务线标识。
64bit 分布式 ID(42bit 毫秒+5bit 机器 ID+12 位自增)等
更多、更全、更新 BATJ 等大厂面试题+Q 群:762073882
零声学院整理出品
生成分布式 ID 的方式:A,2 个自增表,步长相互隔开 B,时间的毫秒或者纳秒 C,UUID
D,64 位约束条件(如上)
8. NIO 和 IO 的区别?
第一点,NIO 少了 1 次从内核空间到用户空间的拷贝。
ByteBuffer.allocateDirect()分配的内存使用的是本机内存而不是 Java 堆上的内存,
和网络或者磁盘交互都在操作系统的内核空间中发生。allocateDirect()的区别在于这
块内存不由 java 堆管理, 但仍然在同一用户进程内。
第二点,NIO 以块处理数据,IO 以流处理数据
第三点,非阻塞,NIO1 个线程可以管理多个输入输出通道
9. Redis 内存数据上升到一定大小会执行数据淘汰策略,
Redis 提供了哪 6 种数据淘汰策略?
LRU:从已设置过期时间的数据集合中挑选最近最少使用的数据淘汰
random:从已设置过期时间的数据中挑选任意数据淘汰
ttl:从已设置过期时间的数据集合中挑选将要过期的数据淘汰。
notenvision:禁止驱逐数据
如 mysql 中有 2 千万数据,redis 只存储 20 万的热门数据。LRU 或者 TTL 都满足热点数
据读取较多,不太可能超时特点。
redis 特点:速度块,O(1),丰富的数据类型,支持事物原子性,可用于缓存,比 memecache
速度块,可以持久化数据。
常见问题和解决:Master 最好不做持久化如 RDB 快照和 AOF 日志文件;如果数据比较
重要,某分 slave 开启 AOF 备份数据,策略为每秒 1 次,为了主从复制速度及稳定,MS
主从在同一局域网内;主从复制不要用图状结构,用单向链表更为稳定 M-S-S-S-S。。。。;
redis 过期采用懒汉+定期,懒汉即 get/set 时候检查 key 是否过期,过期则删除 key,
定期遍历每个 DB,检查制定个数个 key;结合服务器性能调节并发情况。
过期淘汰,数据写入 redis 会附带 1 个有效时间,这个有效时间内该数据被认为是正确
的并不关心真实情况,例如对支付等业务采用版本号实现,redis 中每一份数据都维持
1 个版本号,DB 中也维持 1 份,只有当 redis 的与 DB 中的版本一致时,才会认为 redis
为有效的,不过仍然每次都要访问 DB,只需要查询 version 版本字段即可。
10. 请描述 MyISM 和 InnoDB?
MyISM 采用表级锁,对 Myism 表读不会阻塞读,会阻塞同表写,对 Myism 写则会阻塞读
和写,即一个线程获得 1 个表的写锁后,只有持有锁的线程可以对表更新操作,其他线
程的读和写都会等待。
更多、更全、更新 BATJ 等大厂面试题+Q 群:762073882
零声学院整理出品
InnoDB,采用行级锁,支持事务,例如只对 a 列加索引,如果 update ...where a=1 and
b=2 其实也会锁整个表, select 使用共享锁,update insert delete 采用排它锁,
commit 会把锁取消,当然 select by id for update 也可以制定排它锁。
11. 请描述实时队列?
实时队列采用双队列模式,生产者将行为记录写入 Queue1,worker 服务从 Queue1 消费
新鲜数据,如果异常则写入 Queue2(主要保存异常数据),RetryWorker 会监听 Queue2,
消费异常数据,如果还未处理成功按照一定的策略等待或者将异常数据再写入 Queue2,
如果数据发生积压可以调整 worker 的消费游标,从最新数据重新开始消费,保证了最
新 data 得到处理,中间未处理的一段则可以启动 backupWorker 指定起止游标在消费完
指定区间的数据后,backupWorker 会自动停止。
DB 降级开关后,可直接写入 redis(storm),同时将数据写入一份到 Retry 队列,在
开启 DB 降级开关后消费 Retry 队列中的数据,从而把数据写入到 mysql 中,达到最终
一致性。MYSQL 切分为分片为 2 的 N 次方,例如原来分为两个库 d0 和 d1 均放在 s0 服
务器上,s0 同时有备机 s1,扩容只要几步骤:确保 s0 到 s1 服务器同步顺利,没有明
显延迟;s0 暂时关闭读写权限;确保 s1 已经完全同步到 s0 更新;s1 开放读写权限;
d1 的 dns 由 s0 切换到 s1;s0 开放读写权限。
12. DB 的特性和隔离级别?
4 大特性:原子性,一致性,分离性,持久性
隔离级别:
读提交:写事务禁止读
读未提交:写事务允许读
可重复读:写事务禁止读事务,读禁止写
序列化:全部禁止
详细说明:读提交 1 个事务开始写则全部禁止其他事务访问该行。读未提交 1 个事务开
始写则不允许其他事务同时写,但可以读。可重复读 读事务会禁止写事务,写事物则
禁止其他任何事务。序列化性能最低,全部禁止,串行执行。 MYSQL 默认的是可重复
读。
13. ICMP 是什么协议,处于哪一层?
Internet 控制报文协议,处于网络层(IP 层)
更多、更全、更新 BATJ 等大厂面试题+Q 群:762073882
零声学院整理出品
14. 讲一下 NIO 和网络传输.
NIO Reactor 反应器模式,例如汽车是乘客访问的实体 reactor,乘客上车后到售票员
处 Acceptor 登记,之后乘客 便可休息睡觉了,到达乘客目的地后,售票员 Aceptor 将其唤
醒即可。持久 TCP 长链接每个 client 和 server 之间有存在一 个持久连接,当 CCU(用户
并发数量)上升,阻塞 server 无法为每个连接运行 1 个线程,自己开发 1 个二进制协议,
将 message 压缩至 3-6 倍,传输双向且消息频率高,假设 server 链接了 2000 个 client,
每个 client 平均每分钟传输 1-10 个 message,1 个 messaged 的大小为几百字节/几千字节,
而 server 也要向 client 广播其他玩家的当前信息,需要高速处 理消息的能力。Buffer,
网络字节存放传输的地方,从 channel 中读写,从 buffer 作为中间存储格式,channel 是
网络连 接与 buffer 间数据通道,像之前的 socket 的 stream。
15. 内存泄漏
未对作废数据内存单元置为 null,尽早释放无用对象的引用,使用临时变量时,让引
用变量在推出活动域后自动设置为 null,暗示垃圾收集器收集;程序避免用 String 拼
接,用 StringBuffer,因为每个 String 会占用内存一块区域;尽量少用静态变量(全
局不会回收);不要集中创建对象尤其大对象,可以使用流操作;尽量使用对象池,不
再循环中创建对象,优化配置;创建对象到单例 getInstance 中,对象无法回收被单例
引用;服务器 session 时间设置过长也会引起内存泄漏。
16. 请描述平衡二叉树.
平衡二叉树,左右高度之差不超过 1,Add/delete 可能造成高度>1,此时要旋转,维持
平衡状态,避免二叉树退化为链表,让 Add/Delete 时间复杂度但控制在 O(log2N),旋
转算法 2 个方法,1 是求树的高度,2 是求 2 个高度最大值,1 个空树高度为-1,只有 1
个根节点的树的高度为 0,以后每一层+1,平衡树任意节点最多有 2 个儿子,因此高度
不平衡时,此节点的 2 棵子树高度差为 2。例如单旋转,双旋转,插入等。
红黑树放弃完全平衡,追求大致平衡,保证每次插入最多要 3 次旋转就能平衡。
17. 请问溢出的原因?
是否递归的调用;大量循环;全局变量是否过多;数组,List,Map 数据是否过大;用
DDMS 工具检查地方。
内存溢出的原因
过多使用了 static;static 最好只用 int 和 string 等基本类型;大量的递归或者死循
环;大数据项的查询,如返回表的所有记录,应该采用分页查询。检查是否有数组、List、
map 中存放的是对象的引用而不是对象,这些引用会让对应对象不能被释放。
栈过大会导致内存占用过多,频繁页交换阻碍效率。
32,说一下 http/2
Http/2 采用二进制格式而不是文本
更多、更全、更新 BATJ 等大厂面试题+Q 群:762073882
零声学院整理出品
Http/2 是完全多路复用的,而非有序并阻塞的。
Http/2 使用报头压缩
Http/2 让服务器可以将响应主动推送到客户端缓存中。
18. 单例模式的 7 种写法.
懒汉 2 种,枚举,饿汉 2 种,静态内部类,双重校验锁(推荐)。
19. lucence 倒排索引.
三个文件:字典文件,频率文件,位置文件。词典文件不仅保存有每个关键词,还保留
了指向频率文件和位置文件的指针,通过指针可以找到该关键字的频率信息和位置信息。
field 的概念,用于表达信息所在位置(如标题中,文章中,url 中),在建索引中,
该 field 信息也记录在词典文件中,每个关键词都有一个 field 信息(因为每个关键字一定
属于一个或多个 field)。
关键字是按字符顺序排列的(lucene 没有使用 B 树结构),因此 lucene 可以用二元搜
索算法快速定位关键词。
假设要查询单词 “live”,lucene 先对词典二元查找、找到该词,通过指向频率文件
的指针读出所有文章号,然后返回结果。词典通常非常小,因而,整个过程的时间是毫秒级
的。
对词典文件中的关键词进行了压缩,关键词压缩为<前缀长度,后缀>,例如:当前词为
“阿拉伯语”,上一个词为“阿拉伯”,那么“阿拉伯语”压缩为<3,语>。对数字的压缩,
数字只保存与上一个值的差值。
20. ZooKeeper 分布式是如何做到高可用?
ZooKeeper 运行期间,集群中至少有过半的机器保存了最新数据。集群超过半数的机器
能够正常工作,集群就能够对外提供服务。
zookeeper 可以选出 N 台机器作主机,它可以实现 M:N 的备份;keepalive 只能选出 1
台机器作主机,所以 keepalive 只能实现 M:1 的备份。
通常有以下两种部署方案:双机房部署(一个稳定性更好、设备更可靠的机房,这个机
房就是主要机房,而另外一个机房则更加廉价一些,例如,对于一个由 7 台机器组成的
ZooKeeper 集群,通常在主要机房中部署 4 台机器,剩下的 3 台机器部署到另外一个机房
中);三机房部署(无论哪个机房发生了故障,剩下两个机房的机器数量都超过半数。在三
个机房中都部署若干个机器来组成一个 ZooKeeper 集群。假设机器总数为 N,各机房机器
数:N1 = (N-1)/2 ,N2=1~(N-N1)/2 ,N3 = N - N1 - N2 )。
水平扩容就是向集群中添加更多机器,Zookeeper2 种方式(不完美),一种是集群整
体重启,另外一种是逐台进行服务器的重启。
更多、更全、更新 BATJ 等大厂面试题+Q 群:762073882
零声学院整理出品
21. 如何将数据分布在 redis 第几个库?
redis 本身支持 16 个数据库,通过 数据库 id 设置,默认为 0。
例如 jedis 客户端设置。一:
JedisPool(org.apache.commons.pool.impl.GenericObjectPool.Config poolConfig,
String host, int port, int timeout, String password, int database);
第一种通过指定构造函数 database 字段选择库,不设置则默认 0 库。二:
jedis.select(index);调用 jedis 的 select 方法指定。
22. kafka 高性能的原因?
A,Broker NIO 异步消息处理,实现了 IO 线程与业务线程分离;
B,磁盘顺序写;
C, 零拷贝(跳过用户缓冲区的拷贝,建立一个磁盘空间和内存的直接映射,数据不再
复制到用户态缓冲区);
D,分区/分段(每次文件操作都是对一个小文件的操作,非常轻便,同时也增加了并行
处理能力);
F,批量发送 (可以指定缓存的消息达到某个量的时候就发出去,或者缓存了固定的时
间后就发送出去,大大减少服务端的 I/O 次数)
E,数据压缩
23. 幂等的处理方式?
一、查询与删除操作是天然幂等
二、唯一索引,防止新增脏数据
三、token 机制,防止页面重复提交
四、悲观锁 for update
五、乐观锁(通过版本号/时间戳实现, 通过条件限制 where
avai_amount-#subAmount# >= 0)
六、分布式锁
七、状态机幂等(如果状态机已经处于下一个状态,这时候来了一个上一个状态的变更,
理论上是不能够变更的,这样的话,保证了有限状态机的幂等。)
八、select + insert(并发不高的后台系统,或者一些任务 JOB,为了支持幂等,支
持重复执行)
24. Https 工作流程?
a、客户端发送自己支持的加密规则给服务器,代表告诉服务器要进行连接了