高频面试题
2021-11-03 18:53:38 0 举报
AI智能生成
包过
作者其他创作
大纲/内容
网络编程
OSI七层和TCP/IP五层模型
应用层
http和https的区别和工作方式
状态码含义
http1.0和1.1区别
http1.x和http2.0区别
采用二进制格式,替换字符串
头部压缩
只传索引
多路复用
1.1只能串行执行,2.0使用流id提供并行,解决阻塞
服务器推送
预先推送减少请求
网页解析全过程
传输层
三次握手和四次挥手的机制
为何要进行多次握手
为何却需要4次挥手
CLOSE_WAIT和TIME_WAIT的状态和意义
TIME_WAIT为何时2msl
当客户端发出最后的 ACK 确认报文时,并不能确定服务器端能够收到该段报文。所以客户端在发送完 ACK 确认报文之后,会设置一个时长为 2 MSL 的计时器。MSL(Maximum Segment Lifetime),指一段 TCP 报文在传输过程中的最大生命周期。2 MSL 即是服务器端发出 FIN 报文和客户端发出的 ACK 确认报文所能保持有效的最大时长。
若服务器在 1 MSL 内没有收到客户端发出的 ACK 确认报文,再次向客户端发出 FIN 报文。如果客户端在 2 MSL 内收到了服务器再次发来的 FIN 报文,说明服务器由于一些原因并没有收到客户端发出的 ACK 确认报文。客户端将再次向服务器发出 ACK 确认报文,并重新开始 2 MSL 的计时。
若客户端在 2MSL 内没有再次收到服务器发送的 FIN 报文,则说明服务器正常接收到客户端 ACK 确认报文,客户端可以进入 CLOSE 阶段,即完成四次挥手。
所以客户端要经历 2 MSL 时长的 TIME-WAIT 阶段,为的是确认服务器能否接收到客户端发出的 ACK 确认报文。
作者:力扣 (LeetCode)
链接:https://leetcode-cn.com/leetbook/read/networks-interview-highlights/esno32/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
tcp粘包问题处理
原因
① 发送方写入的数据大于套接字缓冲区的大小,此时将发生拆包。
② 发送方写入的数据小于套接字缓冲区大小,由于 TCP 默认使用 Nagle 算法,只有当收到一个确认后,才将分组发送给对端,当发送方收集了多个较小的分组,就会一起发送给对端,这将会发生粘包。
③ 进行 MSS (最大报文长度)大小的 TCP 分段,当 TCP 报文的数据部分大于 MSS 的时候将发生拆包
④ 发送方发送的数据太快,接收方处理数据的速度赶不上发送端的速度,将发生粘包
解决办法
① 在消息的头部添加消息长度字段,服务端获取消息头的时候解析消息长度,然后向后读取相应长度的内容。
② 固定消息数据的长度,服务端每次读取既定长度的内容作为一条完整消息,当消息不够长时,空位补上固定字符。但是该方法会浪费网络资源。
③ 设置消息边界,也可以理解为分隔符,服务端从数据流中按消息边界分离出消息内容,一般使用换行符。
何时需要处理
当接收端同时收到多个分组,并且这些分组之间毫无关系时,需要处理粘包;而当多个分组属于同一数据的不同部分时,并不需要处理粘包问题。
超时重传
流量控制和拥塞控制
拥塞控制四种算法’
如果接收方滑动窗口满了,发送方怎么办
tcp如何保证可靠性
数据分块
超时重传
SYN后就开启定时器,一定时间内如果没有ACK 重新发送数据
拥塞控制
在实际的网络通信系统中,除了发送方和接收方外,还有路由器,交换机等复杂的网络传输线路,此时就需要拥塞控制。拥塞控制是作用于网络的,它是防止过多的数据注入到网络中,避免出现网络负载过大的情况。常用的解决方法有:慢开始和拥塞避免、快重传和快恢复。
四种算法
慢开始
拥塞避免
快重传
快恢复
流量控制
所谓流量控制就是让发送方的发送速率不要太快,让接收方来得及接收。如果接收方来不及接收发送方发送的数据,那么就会有分组丢失。在 TCP 中利用可变长的滑动窗口机制可以很方便的在 TCP 连接上实现对发送方的流量控制。主要的方式是接收方返回的 ACK 中会包含自己的接收窗口大小,以控制发送方此次发送的数据量大小(发送窗口大小)。
校验和
序列号和确认应答
ARQ
网络层
数据链路层
物理层
分布式
分布式调度
集中式结构
分布式存储
分布式发号器
雪花算法
分布式计算
mapreduce
流水线
actor
stream
分布式协调与同步
分布式锁
使用数据库、redis、zookeeper分别如何实现
锁超时问题
Redlock算法
选举
分布式数据一致性
分布式事务
分布式通信
RPC
消息队列
分布式存储
一致性哈希
分布式数据复制
分布式缓存
分布式高可靠性
负载均衡
轮训
随机
哈希
一致性哈希
带有限负载的一致性哈希
带虚拟节点的一致性哈希
带权重
取模
流量控制
故障隔离
故障恢复
分布式理论
CAP
C
数据在多个副本之间能够保持一致的特性
A
系统提供的服务必须一直处于可用的状态,每次请求都能获取到非错的响应(不保证获取的数据为最新数据)
P
遇到任何网络分区故障的时候,仍然能够对外提供满足一致性和可用性的服务,除非整个网络环境都发生了故障
BASE
Basically Available(基本可用),Soft State(软状态)和Eventually Consistent(最终一致性)
分布式事务
2pc
单点故障
同步阻塞
数据不一致
rcc
事务消息
三阶段提交方法
在2pc基础上引入超时机制和准备阶段
分布式锁
主流方法
基于数据库实现
redis
zookeeper或者etcd实现
消息队列
如何防止消息丢失
保证消息幂等处理
利用数据库的唯一约束实现幂等
为更新的数据设置前置条件
增加版本号属性
记录并检查操作
token或者GUID
消息按顺序处理
种类
kafka
activemq
rabbitmq
rocketmq
消息队列的事务
生产者和消费者的数据一致性问题
消息积压了如何处理
后端存储实战
并发场景下的ABA问题
由于重试导致的数据不一直问题
版本号概念
架构
RPC
核心功能
provider
队列、线程池
将不同类型请求,放入各自队列,每个队列分配队里的线程池,资源隔离
超时丢弃
快速失败已经超时的请求,缓解队列堆积
优雅关闭
进程退出前确保收到的请求全部处理完成
过载保护
高级功能
熔断
当服务出现不可用或者响应超时,防止雪崩,暂时停止对该服务调用
降级
业务降级,跳过异常调用
限流
动态权重
产品
GRPC
http2
protobuf
客户端寻址
多语言支持
redis
redis是单线程的吗
为何单线程还如此之快
使用场景都有哪些
数据类型
string
list
hash
set
sort set
bitmap
geo
hyperloglog
底层数据结构
sortted set 有序集合
跳表和压缩列表
hash
压缩列表和哈希表
网络事件处理器
过期删除策略
策略
惰性删除
定时删除
删除方式
定时删除
惰性删除
定期删除
内存淘汰策略
LRU算法
持久化机制
RDB
AOF
如何保证高可用和集群模式
主从复制
核心原理
哨兵模式
功能
集群监控
消息通知
故障转移
配置中心
集群模式
选举
保证在线扩容的安全性
事务
案例
如何在1亿个key中,找出10个key含java
消息队列
实现分布式锁
常规锁
锁过期,但是还未处理完
看门狗之守护线程
RedLock红锁
缓存数据库的数据一致性
先更新数据库再更新缓存(不建议使用);
先更新数据库再删除缓存(推荐);
先删除缓存再更新数据库不推荐
解决方案
设置缓存有效时间(最简单),在接受最终一致性的场景下,配置合理的失效时间。
使用消息队列,例如rocketMq等消息队列可以保证数据操作顺序一致性,确保缓存系统的数据正常
缓存穿透、击穿、雪崩
布隆过滤器
与memcached比较
数据类型
持久化
事务
集群模式
性能对比
网络IO模型
redlock
Redis 官方站提出了一种权威的基于 Redis 实现分布式锁的方式名叫Redlock。此种方式比原先的单节点的方法更安全。它可以保证以下特性:
安全特性:互斥访问,即永远只有一个 client 能拿到锁;
避免死锁:最终 client 都可能拿到锁,不会出现死锁的情况,即使原本锁住某资源的 client crash 了或者出现了网络分区;
容错性:只要大部分 Redis 节点存活就可以正常提供服务;
缓存异常
穿透
解决方案
对查询结果为空的情况也进行缓存,缓存时间设置短一点。
该key对应的数据 insert 了之后清理缓存。
采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的 bitmap 中,一个一定不存在的数据会被这个 bitmap 拦截掉,从而避免了对底层存储系统的查询压力。
雪崩
解决方案
key的失效期分散开,不同的key设置不同的有效期;
设置二级缓存;
高可用方案,比如Redis集群,保证不会因为缓存系统崩溃而导致缓存雪崩;
击穿
解决方案
用分布式锁控制访问的线程,如:使用redis的setnx互斥锁先进行判断,这样其他线程就处于等待状态,保证不会有大并发操作去操作数据库。
场景
主要是针对热点数据
elasticsearch
2019年常见Elasticsearch面试题答案解析
mysql
事务隔离级别
事务隔离级别
读未提交(Read Uncommitted)
读已提交(Read Committed)
可重复读(Repeatable Read)
串行化(Serializable)
脏读、幻读、不可重复读
事务A、B交替执行,事务A被事务B干扰到了,因为事务A读取到事务B未提交的数据,这就是脏读。
在一个事务范围内,两个相同的查询,读取同一条记录,却返回了不同的数据,这就是不可重复读。
事务A查询一个范围的结果集,另一个并发事务B往这个范围中插入/删除了数据,并静悄悄地提交,然后事务A再次查询相同的范围,两次读取得到的结果集不一样了,这就是幻读。
MVCC
原理解析
特性
AICD
原子性: 事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。
一致性: 指在事务开始之前和事务结束以后,数据不会被破坏,假如A账户给B账户转10块钱,不管成功与否,A和B的总金额是不变的。
隔离性: 多个事务并发访问时,事务之间是相互隔离的,即一个事务不影响其它事务运行效果。简言之,就是事务之间是进水不犯河水的。
持久性: 表示事务完成以后,该事务对数据库所作的操作更改,将持久地保存在数据库之中。
实现思想
原子性:是使用 undo log来实现的,如果事务执行过程中出错或者用户执行了rollback,系统通过undo log日志返回事务开始的状态。
持久性:使用 redo log来实现,只要redo log日志持久化了,当系统崩溃,即可通过redo log把数据恢复。
隔离性:通过锁以及MVCC,使事务相互隔离开。
一致性:通过回滚、恢复,以及并发情况下的隔离性,从而实现一致性。
索引
常用数据结果
hash
b树
红黑树
b-树
b+树
数据库为什么使用B+树而不是B树?
在B树中,键和值即存放在内部节点又存放在叶子节点;在B+树中,内部节点只存键,叶子节点则同时存放键和值。
B+树的叶子节点有一条链相连,而B树的叶子节点各自独立的。
B+树索引的所有数据均存储在叶子节点,而且数据是按照顺序排列的,链表连着的。那么B+树使得范围查找,排序查找,分组查找以及去重查找变得异常简单。.
B+树非叶子节点上是不存储数据的,仅存储键值,而B树节点中不仅存储键值,也会存储数据。innodb中页的默认大小是16KB,如果不存储数据,那么就会存储更多的键值,相应的树的阶数(节点的子节点树)就会更大,树就会更矮更胖,如此一来我们查找数据进行磁盘的IO次数有会再次减少,数据查询的效率也会更快.
类型
聚簇索引和非聚簇索引
一个表中只能拥有一个聚集索引,而非聚集索引一个表可以存在多个。
聚集索引,索引中键值的逻辑顺序决定了表中相应行的物理顺序;非聚集索引,索引中索引的逻辑顺序与磁盘上行的物理存储顺序不同。
索引是通过二叉树的数据结构来描述的,我们可以这么理解聚簇索引:索引的叶节点就是数据节点。而非聚簇索引的叶节点仍然是索引节点,只不过有一个指针指向对应的数据块。
聚集索引:物理存储按照索引排序;非聚集索引:物理存储不按照索引排序;
主键索引、普通索引
覆盖索引
覆盖索引: 查询列要被所建的索引覆盖,不必从数据表中读取,换句话说查询列要被所使用的索引覆盖。
回表:二级索引无法直接查询所有列的数据,所以通过二级索引查询到聚簇索引后,再查询到想要的数据,这种通过二级索引查询出来的过程,就叫做回表。
联合索引
底层实现
最左前缀
最左前缀原则,就是最左优先,在创建多列索引时,要根据业务需求,where子句中使用最频繁的一列放在最左边。
当我们创建一个组合索引的时候,如(k1,k2,k3),相当于创建了(k1)、(k1,k2)和(k1,k2,k3)三个索引,这就是最左匹配原则。。
索引时效的原因分析
查询条件包含or,可能导致索引失效
如何字段类型是字符串,where时一定用引号括起来,否则索引失效
like通配符可能导致索引失效。
联合索引,查询时的条件列不是联合索引中的第一个列,索引失效。
在索引列上使用mysql的内置函数,索引失效。
对索引列运算(如,+、-、*、/),索引失效。
索引字段上使用(!= 或者 < >,not in)时,可能会导致索引失效。
索引字段上使用is null, is not null,可能导致索引失效。
左连接查询或者右连接查询查询关联的字段编码格式不一样,可能导致索引失效。
mysql估计使用全表扫描要比使用索引快,则不使用索引。
不适用的场景
数据量少的不适合加索引
更新比较频繁的也不适合加索引
区分度低的字段不适合加索引(如性别)
潜规则
覆盖索引
回表
索引数据结构(B+树)
最左前缀原则
索引下推
创建原则
最左前缀匹配原则
频繁作为查询条件的字段才去创建索引
频繁更新的字段不适合创建索引
索引列不能参与计算,不能有函数操作
优先考虑扩展索引,而不是新建索引,避免不必要的索引
在order by或者group by子句中,创建索引需要注意顺序
区分度低的数据列不适合做索引列(如性别)
定义有外键的数据列一定要建立索引。
对于定义为text、image数据类型的列不要建立索引。
删除不再使用或者很少使用的索引
锁
库锁
表锁
行锁
如何实现的
算法有哪些
record lock
gap lock 间隙锁
如何实现乐观锁和悲观锁
悲观锁
悲观锁思想就是,当前线程要进来修改数据时,别的线程都得拒之门外~ 比如,可以使用select…for update ~
悲观锁她专一且缺乏安全感了,她的心只属于当前事务,每时每刻都担心着它心爱的数据可能被别的事务修改,所以一个事务拥有(获得)悲观锁后,其他任何事务都不能对数据进行修改啦,只能等待锁被释放才可以执行。
乐观锁
乐观锁思想就是,有线程过来,先放过去修改,如果看到别的线程没修改过,就可以修改成功,如果别的线程修改过,就修改失败或者重试。实现方式:乐观锁一般会使用版本号机制或CAS算法实现。
乐观锁的“乐观情绪”体现在,它认为数据的变动不会太频繁。因此,它允许多个事务同时对数据进行变动。实现方式:乐观锁一般会使用版本号机制或CAS算法实现。
死锁和死锁检测
排查步骤
查看死锁日志show engine innodb status;
找出死锁Sql
分析sql加锁情况
模拟死锁案发
分析死锁日志
分析死锁结果
存储引擎
innodb
myisam
区别
InnoDB支持事务,MyISAM不支持事务
InnoDB支持外键,MyISAM不支持外键
InnoDB 支持 MVCC(多版本并发控制),MyISAM 不支持
select count(*) from table时,MyISAM更快,因为它有一个变量保存了整个表的总行数,可以直接读取,InnoDB就需要全表扫描。
Innodb不支持全文索引,而MyISAM支持全文索引(5.7以后的InnoDB也支持全文索引)
InnoDB支持表、行级锁,而MyISAM支持表级锁。
InnoDB表必须有主键,而MyISAM可以没有主键
Innodb表需要更多的内存和存储,而MyISAM可被压缩,存储空间较小,。
Innodb按主键大小有序插入,MyISAM记录插入顺序是,按记录插入顺序保存。
InnoDB 存储引擎提供了具有提交、回滚、崩溃恢复能力的事务安全,与 MyISAM 比 InnoDB 写的效率差一些,并且会占用更多的磁盘空间以保留数据和索引
InnoDB 属于索引组织表,使用共享表空间和多表空间储存数据。MyISAM用.frm、.MYD、.MTI来储存表定义,数据和索引。
explain
字段含义
如何慢查询优化
主从复制
主从延迟
原因
一个服务器开放N个链接给客户端来连接的,这样有会有大并发的更新操作, 但是从服务器的里面读取binlog的线程仅有一个,当某个SQL在从服务器上执行的时间稍长 或者由于某个SQL要进行锁表就会导致,主服务器的SQL大量积压,未被同步到从服务器里。这就导致了主从不一致, 也就是主从延迟。
解决办法
主服务器要负责更新操作,对安全性的要求比从服务器要高,所以有些设置参数可以修改,比如sync_binlog=1,innodb_flush_log_at_trx_commit = 1 之类的设置等。
选择更好的硬件设备作为slave。
把一台从服务器当度作为备份使用, 而不提供查询, 那边他的负载下来了, 执行relay log 里面的SQL效率自然就高了。
增加从服务器喽,这个目的还是分散读的压力,从而降低服务器负载。
主从同步
步骤
步骤一:主库的更新事件(update、insert、delete)被写到binlog
步骤二:从库发起连接,连接到主库。
步骤三:此时主库创建一个binlog dump thread,把binlog的内容发送到从库。
步骤四:从库启动之后,创建一个I/O线程,读取主库传过来的binlog内容并写入到relay log
步骤五:还会创建一个SQL线程,从relay log里面读取内容,从Exec_Master_Log_Pos位置开始执行读取到的更新事件,将更新内容写入到slave的db
高可用
一主多备
双主
日志
常见问题
如何保证数据不丢失
如何保证主备数据一致
如何保证高可用
读写分离的坑
join语句如何优化
MySQL中DATETIME和TIMESTAMP的区别
存储精度都为秒
区别:
DATETIME 的日期范围是 1001——9999 年;TIMESTAMP 的时间范围是 1970——2038 年
DATETIME 存储时间与时区无关;TIMESTAMP 存储时间与时区有关,显示的值也依赖于时区
DATETIME 的存储空间为 8 字节;TIMESTAMP 的存储空间为 4 字节
DATETIME 的默认值为 null;TIMESTAMP 的字段默认不为空(not null),默认值为当前时间(CURRENT_TIMESTAMP)
优化步骤
show status 命令了解各种 sql 的执行频率
通过慢查询日志定位那些执行效率较低的 sql 语句
explain 分析低效 sql 的执行计划(这点非常重要,日常开发中用它分析Sql,会大大降低Sql导致的线上事故)
如果某个表有近千万数据,CRUD比较慢,如何优化。
分库分表
某个表有近千万数据,可以考虑优化表结构,分表(水平分表,垂直分表),当然,你这样回答,需要准备好面试官问你的分库分表相关问题呀,如
分表方案(水平分表,垂直分表,切分规则hash等)
分库分表中间件(Mycat,sharding-jdbc等)
分库分表一些问题(事务问题?跨节点Join的问题)
解决方案(分布式事务等)
索引优化
除了分库分表,优化表结构,当然还有所以索引优化等方案~
说一下大表查询的优化方案
优化shema、sql语句+索引;
可以考虑加缓存,memcached, redis,或者JVM本地缓存;
主从复制,读写分离;
分库分表;
一条sql执行过长的时间,你如何优化,从哪些方面入手?
查看是否涉及多表和子查询,优化Sql结构,如去除冗余字段,是否可拆表等
优化索引结构,看是否可以适当添加索引
数量大的表,可以考虑进行分离/分表(如交易流水表)
数据库主从分离,读写分离
explain分析sql语句,查看执行计划,优化sql
查看mysql执行日志,分析是否有其他方面的问题
服务器性能分析的方法命令有哪些?
Show status, 一些值得监控的变量值:
Bytes_received和Bytes_sent 和服务器之间来往的流量。 Com 服务器正在执行的命令。 Created 在查询执行期限间创建的临时表和文件。 Handler 存储引擎操作。 Select 不同类型的联接执行计划。 Sort 几种排序信息。
Show profiles 是MySql用来分析当前会话SQL语句执行的资源消耗情况
golang
细节知识
make和new区别
byte和uint8没有区别,rune和uint32没有区别
slice
内部原理‘
扩容机制
其他
拷贝大切片一定比小切片代价大吗?
map
内部原理
hash碰撞
rehash
负载因子
扩容机制
动态缩容方式
sync.map实现原理
channel
优雅关闭
实现原理
其他
对已经关闭的chan进行读写会怎么样?为什么?
对未初始化的chan进行读写,会怎么样?为什么?
for循环select时, 如果通道关闭会怎么样?如果select中的case只有一 个,又会怎么样?
context
底层原理
应用
传递共享数据
取消信号
unsafe包
能说说uintptr和unsafe.Pointer的区别吗?
原理
反射
内部原理
基本用法
其他
reflect (反射包)如何获取字段tag? 为什么json包不能导出私有变量的tag?
mutex和rwmutex锁
实现原理
内存
内存分配
内存回收
内存逃逸
知道Golang的内存逃逸吗?什么情况下回发生内存逃逸?
怎么避免逃逸分析?
GMP
调度原理
G0和m0的作用
并发控制
三种方案
channel
waitgroup
context
微服务
rpc
实现原理
grpc
分布式链路追踪
日志收集上报分析
注册发现
组件
consul
CP
raft
etcd
CP
zookeeper
java
CP
微服务网关
高可用的保障
限流、熔断、降载
监控和报警
负载均衡
统一认证和授权
CICD
jenkins
docker k8s容器编排
秒杀系统设计
简易版
高可用设计
隔离策略
流量控制
削峰限流
降级
热点和灾备
防刷和风控
库存和限购
高性能优化
物理资源极致优化
单机性能优化
百万流量的关键总结
自由主题
0 条评论
下一页