互联网面试问题以及答案20200506

一面

1 了解Java运行时数据区域吗

回答就是jvm 内存的分布:方法区 堆 本地方法栈 程序计数器 虚拟机栈

2 了解垃圾回收机制吗?

什么是垃圾,怎么方法来确定是垃圾的,怎么样的方法来实现垃圾的回收 堆内存的分配原理  CMS垃圾回收的机制 G1垃圾回收机制。

引用计数法(在对象的相互引用的时候出现永远不可能进行垃圾的回收)

在 Java 中,引用和对象是有关联的。如果要操作对象则必须用引用进行。因此,很显然一个简单的办法是通过引用计数来判断一个对象是否可以回收。简单说,即一个对象如果没有任何与之关联的引用, 即他们的引用计数都不为 0, 则说明对象不太可能再被用到,那么这个对象就是可回收对象。

可达性分析

为了解决引用计数法的循环引用问题, Java 使用了可达性分析的方法。通过一系列的“GC roots”对象作为起点搜索。如果在“GC roots”和一个对象之间没有可达路径,则称该对象是不可达的。要注意的是,不可达对象不等价于可回收对象, 不可达对象变为可回收对象至少要经过两次标记过程。两次标记后仍然是可回收对象,则将面临回收。

标记清除算法:

最基础的垃圾回收算法,分为两个阶段,标注和清除。标记阶段标记出所有需要回收的对象,清除阶段回收被标记的对象所占用的空间。如图:

从图中我们就可以发现,该算法最大的问题是内存碎片化严重,后续可能发生大对象不能找到可利用空间的问题。

复制算法:

为了解决 Mark-Sweep 算法内存碎片化的缺陷而被提出的算法。按内存容量将内存划分为等大小的两块。每次只使用其中一块,当这一块内存满后将尚存活的对象复制到另一块上去,把已使用的内存清掉,如图:

这种算法虽然实现简单,内存效率高,不易产生碎片,但是最大的问题是可用内存被压缩到了原本的一半。且存活对象增多的话, Copying 算法的效率会大大降低

标记整理算法(Mark-Compact)

结合了以上两个算法,为了避免缺陷而提出。标记阶段和 Mark-Sweep 算法相同, 标记后不是清理对象,而是将存活对象移向内存的一端。然后清除端边界外的对象。如图:

 新生代与复制算法

目前大部分 JVM GC 对于新生代都采取 Copying 算法,因为新生代中每次垃圾回收都要回收大部分对象,即要复制的操作比较少,但通常并不是按照 1 1 来划分新生代。一般将新生代划分为一块较大的 Eden 空间和两个较小的 Survivor 空间(From Space, To Space),每次使用Eden 空间和其中的一块 Survivor 空间,当进行回收时,将该两块空间中还存活的对象复制到另一块 Survivor 空间中。

https://img-blog.csdn.net/20141107224401036?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhiMTIzR0dHR0dH/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

老年代与标记复制算法

老年代因为每次只回收少量对象,因而采用 Mark-Compact 算法

  1. JAVA 虚拟机提到过的处于方法区的永生代(Permanet Generation)它用来存储 class 类,

常量,方法描述等。对永生代的回收主要包括废弃常量和无用的类。

  1. 对象的内存分配主要在新生代Eden Space和 Survivor Space 的 From Space(Survivor 目前存放对象的那一块),少数情况会直接分配到老生代。
  2. 当新生代的EdenSpace和 From Space 空间不足时就会发生一次 GC,进行 GC 后,Eden

Space 和 From Space 区的存活对象会被挪到 To Space,然后将 Eden Space 和 From Space 进行清理。

  1. 如果 To Space 无法足够存储某个对象,则将这个对象存储到老生代。
  2. 在进行 GC 后,使用的便是 Eden Space 和 To Space 了,如此反复循环。
  3. 当对象在 Survivor 区躲过一次 GC 后,其年龄就会+1。 默认情况下年龄到达 15 的对象会被移到老生代中

GC 垃圾收集器

Java 堆内存被划分为新生代和年老代两部分,新生代主要使用复制和标记-清除垃圾回收算法;年老代主要使用标记-整理垃圾回收算法,因此 java 虚拟中针对新生代和年老代分别提供了多种不同的垃圾收集器, JDK1.6 Sun HotSpot 虚拟机的垃圾收集器如下:

CMS 收集器(多线程标记清除算法)

  Concurrent mark sweep(CMS)收集器是一种年老代垃圾收集器,其最主要目标是获取最短垃圾回收停顿时间,和其他年老代使用标记-整理算法不同,它使用多线程的标记-清除算法。最短的垃圾收集停顿时间可以为交互比较高的程序提高用户体验。CMS 工作机制相比其他的垃圾收集器来说更复杂,整个过程分为以下 4 个阶段:

初始标记只是标记一下 GC Roots 能直接关联的对象,速度很快,仍然需要暂停所有的工作线程。

并发标记进行 GC Roots 跟踪的过程,和用户线程一起工作,不需要暂停工作线程。

重新标记为了修正在并发标记期间,因用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,仍然需要暂停所有的工作线程。

并发清除:清除 GC Roots 不可达对象,和用户线程一起工作,不需要暂停工作线程。由于耗时最长的并发标记和并发清除过程中,垃圾收集线程可以和用户现在一起并发工作, 所以总体上来看CMS 收集器的内存回收和用户线程是一起并发地执行:

G1 收集器

3 static关键字

静态变量先于静态代码块执行,整个执行顺序是:1.父类静态变量初始化。2.父类静态代码块。3.子类静态变量初始化。4.子类静态语句块。5.父类变量初始化。6.父类代码块。7.父类构造函数。8.子类变量初始化。9.子类语句块。10.子类构造函数

4 什么时候会报StackOverFlowError/OutOfMemoryError

Java内存溢出的几种情况:1Java堆溢出(对象数量到达最大堆的容量限制后就会产生内存溢出异常。)2虚拟机栈和本地方法栈溢出。3.方法区和运行时常量池溢出4本机直接内存溢出,DirectMemory容量可通过-XX: MaxDirectMemorySize指定,如果不指定,则默认与Java堆最大值 (-Xmx指定)一样。

Java代码导致OutOfMemoryError错误的解决:

检查代码中是否有死循环或递归调用。

检查是否有大循环重复产生新对象实体。

检查对数据库查询中,是否有一次获得全部数据的查询。一般来说,如果一次取十万条记录到内存,就可能引起内存溢出。这个问题比较隐蔽,在上线前,数据库中数据较少,不容易出问题,上线后,数据库中数据多了,一次查询就有可能引起内存溢出。因此对于数据库查询尽量采用分页的方式查询。

检查List、MAP等集合对象是否有使用完后,未清除的问题。List、MAP等集合对象会始终存有对对象的引用,使得这些对象不能被GC回收。

解决java.lang.OutOfMemoryError的方法有如下几种:

增加jvm的内存大小。方法有:
1)在执行某个class文件时候,可以使用java -Xmx256M aa.class来设置运行aa.class时jvm所允许占用的最大内存为256M。

2)对tomcat容器,可以在启动时对jvm设置内存限度。对tomcat,可以在catalina.bat中添加

3)对resin容器,同样可以在启动时对jvm设置内存限度。在bin文件夹下创建一个startup.bat文件,

4)优化程序,释放垃圾。主要包括避免死循环,应该及时释放种资源。

5 Mock,PowerMock的底层原理知道吗

6 你用过哪些PowerMock的方法

7 你是怎么对sql语句进行优化的

         字段优化,表格结构的优化,索引优化 读写分离 分库分表 集群搭建

8 同样是走索引,走索引A为什么比走索引B效果要好,你是怎么进行判断的

        可能A是做全表的扫描,但是的B做的是联合索引。通过explain的来查看的走什么索引和主键类型。

9 秒杀系统的架构

10 有没有进行压测,压测效果怎么样,压测超出请求量到最后会发生什么故障

11 手撕算法题:不用考虑输入输出,不用编译,两个数M和N,N个数相加得到M,输出所有可能。例如M=7,N=2,输出1,6;2,5;3,4。

12 发散题:如何估算一条地铁线上一天的客流量

13 你认为你相比实验室或者宿舍的同学优点在哪里

14 职业生涯规划

15 你有什么要问我的

二面

1 你认为你比别人优秀的点在哪里

2 平时是怎么学习的

3 学习一门新的技术遇到的印象最深刻的困难是什么,怎么解决的

4 跟老师同学同事沟通上有没有出现过分歧,怎么解决的

5 为什么选择美团点评(公司前景,个人发展,地域)

6 抽象类和接口的区别:

抽象类和接口的区别:一个类只能继承一个抽象类,而一个类却可以实现多个接口。(单继承多实现方式)

 

接口

抽象类

相同点

接口和抽象类都不能被实例化,它们都位于继承树的顶端,用于被其他类实现和继承。实现接口或继承抽象类的普通子类都必须实现这些抽象方法

不同点

1只能包含抽象方法,静态方法和默认方法,不能为普通方法提供方法实现(但是在JDK1.8以后可以使用default和static关键字来修饰接口中定义的普通方法)

2接口中的成员变量只能是 public static final 类型的

3接口不能包含构造器

4接口里不能包含初始化块

1完全可以包含普通方法,接口中的普通方法默认为抽象方法

2抽象类中的成员变量可以是各种类型的

3抽象类可以包含构造器,抽象类里的构造器并不是用于创建对象,而是让其子类调用这些构造器来完成属于抽象类的初始化操作。

4抽象类里完全可以包含初始化块。

7 一些场景下索引的设计。例如:需求是select A, B, C from T where A = 'a',此时怎么设计索引,当需求改为select A, B, C from T where A = 'a' and B = 'b',你会怎么办

8 高并发系统的设计。你认为高并发系统最关键的要注意什么,如何保证系统稳定,如何解决重复下单问题,如何解决超卖问题

一面

1 自我介绍

2 Kafka有了解吗

3 项目中怎么用的Kafka

4 Kafka如何保证消息顺序

5 Kafka如何保证消息不丢失,不重复

6 Redis与MySQL的区别

7 Redis单线程为什么快

Redis 完全基于内存,绝大部分请求是纯粹的内存操作,非常迅速,数据存在内存中,类似于 HashMap,HashMap 的优势就是查找和操作的时间复杂度是 O(1)。

数据结构简单,对数据操作也简单。

采用单线程,避免了不必要的上下文切换和竞争条件,不存在多线程导致的 CPU 切换不用去考虑各种锁的问题,不存在加锁释放锁操作,没有死锁问题导致的性能消耗。

使用多路复用 IO 模型,非阻塞 IO。

8 Redis消息队列用过吗

用来实现的分布式的锁的。通过自身锁的锁的编号解决锁的问题

9 SQL优化

字段优化 表结构的优化 索引的优化 查询的优化 读写分离的 分库分表 集群的模式

10 Mysql索引讲一下

mysql采用的是B+树来实现的。

索引的概念

数据库索引其实就是为了使查询数据效率快。索引有哪些优缺点?

索引的优点:1可以大大加快数据的检索速度,这也是创建索引的最主要的原因。2通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。

索引的缺点:1时间方面:创建索引和维护索引要耗费时间,具体地,当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,会降低增/改/删的执行效率;2空间方面:索引需要占物理空间。

索引使用场景

索引覆盖:如果要查询的字段都建立过索引,那么引擎会直接在索引表中查询而不会访问原始数据(否则只要有一个字段没有建立索引就会做全表扫描),这叫索引覆盖。因此我们需要尽可能的在select后只写必要的查询字段,以增加索引覆盖的几率。这里值得注意的是不要想着为每个字段建立索引,因为优先使用索引的优势就在于其体积小。

索引的类型

主键索引: 数据列不允许重复,不允许为NULL,一个表只能有一个主键。

唯一索引: 数据列不允许重复,允许为NULL值,一个表允许多个列创建唯一索引。

可以通过 ALTER TABLE table_name ADD UNIQUE (column); 创建唯一索引

可以通过 ALTER TABLE table_name ADD UNIQUE (column1,column2); 创建唯一组合索引

普通索引: 基本的索引类型,没有唯一性的限制,允许为NULL值。

可以通过ALTER TABLE table_name ADD INDEX index_name (column);创建普通索引

可以通过ALTER TABLE table_name ADD INDEX index_name(column1, column2, column3);创建组合索引

全文索引:是目前搜索引擎使用的一种关键技术。可以通过ALTER TABLE table_name ADD FULLTEXT (column);创建全文索引。

索引的数据结构

索引的数据结构和具体存储引擎的实现有关,在MySQL中使用较多的索引有Hash索引,B+树索引等,而我们经常使用的InnoDB存储引擎的默认索引实现为:B+树索引。对于哈希索引来说,底层的数据结构就是哈希表,因此在绝大多数需求为单条记录查询的时候,可以选择哈希索引,查询性能最快;其余大部分场景,建议选择BTree索引。

索引的原则:

选择唯一性索引唯一性索引的值是唯一的,可以更快速的通过该索引来确定某条记录。索引虽好,但也不是无限制的使用,最好符合一下几个原则:

1) 最左前缀匹配原则,组合索引非常重要的原则,mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整。

2)较频繁作为查询条件的字段才去创建索引

3)更新频繁字段不适合创建索引

4)若是不能有效区分数据的列不适合做索引列(如性别,男女未知,最多也就三种,区分度实在太低)

5)尽量的扩展索引,不要新建索引。比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可。

6)定义有外键的数据列一定要建立索引。

7)对于那些查询中很少涉及的列,重复值比较多的列不要建立索引。

8)对于定义为text、image和bit的数据类型的列不要建立索引

索引算法

索引算法有 BTree算法和Hash算法

BTree算法

BTree是最常用的mysql数据库索引算法,也是mysql默认的算法。因为它不仅可以被用在=,>,>=,<,<=和between这些比较操作符上,而且还可以用于like操作符,只要它的查询条件是一个不以通配符开头的常量, 例如:-- 只要它的查询条件是一个不以通配符开头的常量

select * from user where name like 'jack%';

-- 如果一通配符开头,或者没有使用常量,则不会使用索引,例如:select * from user where name like '%jack';

Hash算法

Hash Hash索引只能用于对等比较,例如=,<=>(相当于=)操作符。由于是一次定位数据,不像BTree索引需要从根节点到枝节点,最后才能访问到页节点这样多次IO访问,所以检索效率远高于BTree索引。

创建索引的原则和使用原则

索引虽好,但也不是无限制的使用,最好符合一下几个原则

1)最左前缀匹配原则,组合索引非常重要的原则,mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整。

2)较频繁作为查询条件的字段才去创建索引

3)更新频繁字段不适合创建索引

4)若是不能有效区分数据的列不适合做索引列(如性别,男女未知,最多也就三种,区分度实在太低)

5)尽量的扩展索引,不要新建索引。比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可。

6)定义有外键的数据列一定要建立索引。

7)对于那些查询中很少涉及的列,重复值比较多的列不要建立索引。

8)对于定义为text、image和bit的数据类型的列不要建立索引。

创建索引时需要注意什么?

非空字段:应该指定列为NOT NULL,除非你想存储NULL。在mysql中,含有空值的列很难进行查询优化,因为它们使得索引、索引的统计信息以及比较运算更加复杂。你应该用0、一个特殊的值或者一个空串代替空值;

取值离散大的字段:(变量各个取值之间的差异程度)的列放到联合索引的前面,可以通过count()函数查看字段的差异值,返回值越大说明字段的唯一值越多字段的离散程度高;

索引字段越小越好:数据库的数据存储以页为单位一页存储的数据越多一次IO操作获取的数据越大效率越高

使用索引查询一定能提高查询的性能吗?

通常,通过索引查询数据比全表扫描要快。但是我们也必须注意到它的代价。索引需要空间来存储,也需要定期维护,每当有记录在表中增减或索引列被修改时,索引本身也会被修改。 这意味着每条记录的INSERT,DELETE,UPDATE将为此多付出4,5 次的磁盘I/O。 因为索引需要额外的存储空间和处理,那些不必要的索引反而会使查询反应时间变慢。使用索引查询不一定能提高查询性能,索引范围查询(INDEX RANGE SCAN)适用于两种情况:1基于一个范围的检索,一般查询返回结果集小于表中记录数的30%。2基于非唯一性索引的检索。

百万级别或以上的数据如何删除

关于索引:由于索引需要额外的维护成本,因为索引文件是单独存在的文件,所以当我们对数据的增加,修改,删除,都会产生额外的对索引文件的操作,这些操作需要消耗额外的IO,会降低增/改/删的执行效率。所以,在我们删除数据库百万级别数据的时候,查询MySQL官方手册得知删除数据的速度和创建的索引数量是成正比的。

所以我们想要删除百万数据的时候可以先删除索引(此时大概耗时三分多钟)

然后删除其中无用数据(此过程需要不到两分钟)

删除完成后重新创建索引(此时数据较少了)创建索引也非常快,约十分钟左右。与之前的直接删除绝对是要快速很多,更别说万一删除中断,一切删除会回滚。那更是坑了。

前缀索引 什么是最左前缀原则?

顾名思义,就是最左优先,在创建多列索引时,要根据业务需求,where子句中使用最频繁的一列放在最左边。

最左前缀匹配原则,非常重要的原则,mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整。

=和in可以乱序,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮你优化成索引可以识别的形式

聚簇索引与非聚簇索引

聚簇索引:将数据存储与索引放到了一块,找到索引也就找到了数据

非聚簇索引:将数据存储于索引分开结构,索引结构的叶子节点指向了数据的对应行,myisam通过key_buffer把索引先缓存到内存中,当需要访问数据时(通过索引访问数据),在内存中直接搜索索引,然后通过索引找到磁盘相应数据,这也就是为什么索引不在key buffer命中时,速度慢的原因

B+树在满足聚簇索引和覆盖索引的时候不需要回表查询数据,

在B+树的索引中,叶子节点可能存储了当前的key值,也可能存储了当前的key值以及整行的数据,这就是聚簇索引和非聚簇索引。 在InnoDB中,只有主键索引是聚簇索引,如果没有主键,则挑选一个唯一键建立聚簇索引。如果没有唯一键,隐式的生成一个键来建立聚簇索引。

当查询使用聚簇索引时,在对应的叶子节点,可以获取到整行数据,因不用再次进行回表查询。

非聚簇索引一定会回表查询吗?

不一定,这涉及到查询语句所要求的字段是否全部命中了索引,如果全部命中了索引,那么就不必再进行回表查询。

举个简单的例子,假设我们在员工表的年龄上建立了索引,那么当进行select age from employee where age < 20的查询时,在索引的叶子节点上,已经包含了age信息,不会再次进行回表查询。一般范围查询需要回表查询。

联合索引是什么?为什么需要注意联合索引中的顺序?

MySQL可以使用多个字段同时建立一个索引,叫做联合索引。在联合索引中,如果想要命中索引,需要按照建立索引时的字段顺序挨个使用,否则无法命中索引。这个遵循最左前缀原则。

SQL什么情况下不会使用索引(不包含,不等于,函数)

  1. 查询谓词没有使用索引的主要边界,换句话说就是select *,可能会导致不走索引。
  2. 单键值的b树索引列上存在null值,导致COUNT(*)不能走索引。索引列上有函数运算,导致不走索引
  3. 隐式转换导致不走索引
  4. 表的数据库小或者需要选择大部分数据,不走索引
  5. cbo优化器下统计信息不准确,导致不走索引
  6. !=或者<>(不等于),可能导致不走索引,也可能走 INDEX FAST FULL SCAN
  7. 表字段的属性导致不走索引,字符型的索引列会导致优化器认为需要扫描索引大部分数据且聚簇因子很大,最终导致弃用索引扫描而改用全表扫描方式。
  8. 建立组合索引,但查询谓词并未使用组合索引的第一列,此处有一个INDEX SKIP SCAN概念,
  9. like '%liu' 百分号在前
  10. not in ,not exist

11 explain有哪些字段,tpye有哪些类型

MySQL提供了explain命令来查看语句的执行计划。而执行计划,显示数据库引擎对于SQL语句的执行的详细情况,其中包含了是否使用索引,使用什么索引,使用的索引的相关信息等。

Type:(非常重要,可以看到有没有走索引)访问类型

    ALL 扫描全表数据

    index 遍历索引

    range 索引范围查找

    index_subquery 在子查询中使用 ref

    unique_subquery 在子查询中使用 eq_ref

    ref_or_null 对Null进行索引的优化的 ref

    fulltext 使用全文索引

    ref 使用非唯一索引查找数据

    eq_ref 在join查询中使用PRIMARY KEYorUNIQUE NOT NULL索引关联。

possible_keys:可能使用的索引,注意不一定会使用。查询涉及到的字段上若存在索引,则该索引将被列出来。当该列为 NULL时就要考虑当前的SQL是否需要优化了。

Key:显示MySQL在查询中实际使用的索引,若没有使用索引,显示为NULL。

TIPS:查询中若使用了覆盖索引(覆盖索引:索引的数据覆盖了需要查询的所有数据),则该索引仅出现在key列表中

key_length:索引长度

ref:表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值

rows:返回估算的结果集数目,并不是一个准确的值。

Extra:的信息非常丰富,常见的有:

    Using index 使用覆盖索引

    Using where 使用了用where子句来过滤结果集

    Using filesort 使用文件排序,使用非索引列进行时出现,非常消耗性能,尽量优化。

    Using temporary 使用了临时表 sql优化的目标可以参考阿里开发手册

12 Mysql慢查询有了解吗

用于记录执行时间超过某个临界值的SQL日志,用于快速定位慢查询,为我们的优化做参考。

慢查询的优化首先要搞明白慢的原因是什么? 是查询条件没有命中索引?是load了不需要的数据列?还是数据量太大?

所以优化也是针对这三个方向来的,

    首先分析语句,看看是否load了额外的数据,可能是查询了多余的行并且抛弃掉了,可能是加载了许多结果中并不需要的列,对语句进行分析以及重写。

    分析语句的执行计划,然后获得其使用索引的情况,之后修改语句或者修改索引,使得语句可以尽可能的命中索引。

    如果对语句的优化已经无法进行,可以考虑表中的数据量是否太大,如果是的话可以进行横向或者纵向的分表。

13 手撕算法:将栈中元素从栈顶降序排列,允许使用一个额外的栈

14 有什么要问我的

二面

1 自我介绍

2 如何防止超卖

3 Redis预减库存就不会超卖吗

4 有没有做压力测试,觉得瓶颈在哪里

5 如何做sql优化

字段优化 表结构的优化 索引的优化 查询的优化 读写分离的 分库分表 集群的模式

6 如何设计表结构

7 Kafka了解多少

8 Kafka如何保证消息不丢失不重复

9 手撕算法:第K大的数

采用的是的Treeset这样的一种结构俩

三面

1 系统态、用户态,什么时候会进入系统态

2 32位操作系统,单个进程空间的大小

3 函数调用的入参出参的存放位置

4 虚拟内存

5 进程调度的算法

1 先来先服务 2 权重优先3 最短优先(优先队列)4基于时间片的轮转调度算法

6 进程通信的方式

五种方式:信号量 管道通信 共享内存 socket通信 消息队列

7 网络传输过程(讲了五层模型)

物理层 数据链路层 网络层 传输层 应用层

8 系统调用是在哪一层

9 TCP、UDP区别

10 从系统层面上,UDP如何保证尽量可靠

11 TCP四次握手为什么是四次,不是两次

TCP的四次挥手:所谓四次挥手(Four-Way Wavehand)即终止TCP连接,就是指断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开。在socket编程中,这一过程由客户端或服务端任一方执行close来触发。

12 如果a给b发送FIN,b给a发送ACK,a给b发送FIN但是网络断了,这时候双方会做什么

13 10亿条数据(id、上线时间、下线时间),要求画出每一秒在线人数的曲线图

14 硬盘数据的容错容灾

一面

一面先自我介绍,然后立刻甩两道题:

1 给一颗二叉树,输入格式为若干行,每行格式为:当前节点,左节点,右节点;输出二叉树的前序、中序、后序遍历。

二叉树的前序 中序 后序前面三种的用的是的Arraylist  层序遍历是四种用得是的队列的和Arraylist的两种数据结构。

2 给一个数组,输出数组的魔法值。数组的每个子数组中可以找出最大的两个数x、y,对x、y求异或得到m,作为这个子数组的魔力值,所有子数组中最大的魔力值作为数组的魔法值。只会O(n^2)暴力解决。

二面

springboot怎么处理请求,经过了哪些模块,做了那些事

restful是什么

REST是英文representational state transfer(表象性状态转变)或者表述性状态转移;Rest是web服务的一种架构风格;使用HTTP,URI,XML,JSON,HTML等广泛流行的标准和协议;轻量级,跨平台,跨语言的架构设计;它是一种设计风格,不是一种标准,是一种思想.
网络上的所有事物都被抽象为资源, 每个资源都有一个唯一的资源标识符,同一个资源具有多种表现形式(xml,json等),对资源的各种操作不会改变资源标识符, 所有的操作都是无状态的.在RESTful架构中,每个网址代表一种资源(resource),

restful规范了哪些东西,跟Json、RPC有什么不同

RPC是指远程过程调用。服务器A要调用服务器B上的某个方法,由于内存空间不同,无法直接调用,需要通过网络来表达调用的语义和传达调用的数据。需解决以下问题:

通信问题:在服务器A与B之间建立起TCP连接(有答案说UDP也可以);TCP、UDP是属于传输层的协议

参数的序列化和反序列化:参数通过网络传输,需把服务器A内存里的内容序列化后进行传输。

方法映射:参数中包含着要调用的方法,服务器B必须建立起参数与所要调用方法的映射关系

服务器B执行完方法后返回,同样经历上述过程。

restful是一种API设计风格。这里可以发现,其实restful和json-rpc其实是没有可比性的。其对比的应该是RPC.

restful必须依赖于http,因为它需要http请求的类型(post、get、put、delete)来标榜对该资源进行如何的处理。

restful设计难点:需要将所有的接口抽象成某种资源

如想delete多个id怎么办?全部写在url中吗(delete没有body)?不,你应该把删除多个ID抽象成某个任务(即抽象成另一种资源),然后对这个资源使用post。比如用户的登录和登出,不适合对用户这个资源进行操作,应该抽象成对session这个资源进行操作。想使用restful必须要有这样的抽象能力。

知乎对restful一个总结(个人觉得挺到位的):看Url就知道要什么(资源)看http method就知道干什么看http status code就知道结果如何,一定要有以资源为主体的思维。之前也有人说过restful是名词,rpc是动词,大概想表述的也是这个意思

http请求过程

1、输入地址

浏览器补全url地址。会直接从浏览器的缓存中把网页展示出来。

2、浏览器查找域名的 IP 地址

1浏览器会首先查看本地硬盘的 hosts 文件,如果有的话就直接使用hosts文件里面的 ip 地址。2如果在本地的 hosts 文件没有能够找到对应的 ip 地址,浏览器会发出一个 DNS请求到本地DNS服务器

3、达本地DNS服务器之后,本地DNS服务器会首先查询它的缓存记录,如果缓存中有此条记录,就可以直接返回结果,如果没有,本地DNS服务器还要向DNS根服务器进行查询。

4、根DNS服务器告诉本地DNS服务器。过程是迭代的过程。

5、本地DNS服务器继续向域服务器发出请求。

6、本地DNS服务器向域名的解析服务器发出请求,这时就能收到一个域名和IP地址对应关系,本地DNS服务器把这个对应关系保存在缓存中,加快网络访问。

https如何加密

说说对Redis的了解

event loop怎么实现的

zset的底层原理

字符串处理(string): 在 Redis 中,对于所有键,都是字符串类型,其底层实现是 SDS,而键值对的值,其实最终都是以字符串为粒度的,底层都是 SDS 实现。

链表(list):Redis的链表在双向链表上扩展了头、尾节点、元素数等属性

字典(Hash):Redis的Hash,就是在数组+链表的基础上,进行了一些rehash优化等。

Set使用底层使用了intset和hashtable两种数据结构存储的,intset我们可以理解为数组,hashtable就是普通的哈希表(key为set的值,value为null)

https://upload-images.jianshu.io/upload_images/6302559-db0e5a8fc6f52d2f.png?imageMogr2/auto-orient/strip|imageView2/2/w/865

压缩列表(ziplist): ziplist是redis为了节约内存而开发的顺序型数据结构。它被用在列表键和哈希键中。一般用于小数据存储。

zset底层的存储结构包括ziplist或skiplist,在同时满足以下两个条件的时候使用ziplist,其他时候使用skiplist。快速列表(quicklist):一个由ziplist组成的双向链表。但是一个quicklist可以有多个quicklist节点,它很像B树的存储方式。是在redis3.2版本中新加的数据结构,用在列表的底层实现。

https://upload-images.jianshu.io/upload_images/6302559-8e856eebe2fb78ed.png?imageMogr2/auto-orient/strip|imageView2/2

Redis序列化有哪些方式

手撕算法:股票问题,要求是记录下买卖的时间

猜你喜欢

转载自blog.csdn.net/weixin_41605937/article/details/105957590