Java程序员11面阿里,错失offer,期间还面了EMC+网易+美团......

一直在面阿里,从提早批投蚂蚁中间件与阿里中间件,最后阿里中间件面完了hr,可是很遗憾最后没能进,被调到了盒马。不过最终仍是拿到了盒马的offer。期间还面了EMC、网易、携程(水到不行)、美团、拼多多,目前出了美团跟拼多多没有出结果,其余几家公司也都顺利拿到意向,在此回馈一波你们。php

面经部分出自阿里,其余几家公司有少部分补充,内容是我的整理,若有不对,还请纠正,谢谢!html


网络编程

ISO模型与协议前端

应用层:为操做系统或网络应用程序提供访问网络服务的接口。协议Telnet、FTP、HTTP、SNMP、DNSjava

http1.0:须要使用keep-alive参数来告知服务器端要创建一个长链接node

http1.1:默认长链接。支持只发送header信息,能够用做权限请求。支持Host域。mysql

http2.0:多路复用的技术,作到同一个链接并发处理多个请求。HTTP2.0使用HPACK算法对header的数据进行压缩。支持HTTP2.0的web server请求数据的时候,服务器会顺便把一些客户端须要的资源一块儿推送到客户端,省得客户端再次建立链接发送请求到服务器端获取。这种方式很是合适加载静态资源。linux

表示层:对上层数据进行变换(加密、解密、压缩、格式转换等),确保两台主机的应用层程序能过理解。协议ASCII、ASN.一、JPEG、MPEGgit

会话层:负责管理主机之间的会话进程,负责创建、管理、终止进程之间的会话。web

传输层:将上层数据分段并提供端到端的、可靠的或不可靠的传输,还要处理端到端的差错控制和流量控制问题。协议TCP、UDP、SPX面试

网络层:对子网间的数据包进行路由选择。此外,网络层还能够实现拥塞控制、网际互连等功能。协议IP、IPX、RIP、OSPF

数据链路层:在不可靠的物理介质上提供可靠的传输。该层的做用包括:物理地址寻址、数据的成帧、流量控制、数据的检错、重发等。协议SDLC、HDLC、PPP、STP、帧中继

物理层:为上层协议提供了一个传输数据的物理媒体。

TCP\IP模型与协议

应用层:单位是数据段,协议有FTP、TELNET、HTTP、SMTP、SNMP、TFTP、NTP、DNS

运输层:单位是数据包,协议有TCP、UDP

网络层:单位是数据帧,协议有IP

网络接口层:单位是比特,ARP、RARP


三次握手与四次挥手

tcp拆包粘包

因为一批发送的数据太多或缓冲区过小,将一批数据分红多个segment来发送,叫拆包。

将多批小数据写入一个缓冲区,或读取不及时,一个缓冲区存在多批数据,叫粘包。

解决方式:根据消息头中的长度与偏移量来重组数据。设置定长消息,使得一个缓冲区中的segment老是一批数据的。设置消息边界。

BIO NIO AIO

BIO:同步阻塞IO,每一个请求都要一个线程来处理。

NIO:同步非阻塞IO,一个线程能够处理多个请求,适用于短链接、小数据。

AIO:异步非阻塞IO,一个线程处理多个请求,使用回调函数实现,适用于长链接、大数据。

DDOS攻击原理与防护方式

SYN flood:伪造ip地址发送请求,占满半链接队列,致使正常连接被服务器抛弃。攻击方须要很高的带宽资源。

ACK flood:大量ACK链接请求服务器,服务器须要花费CPU资源去查询链接队列并回应。只有当流量很高时才会对服务器形成影响。

Connection Flood:利用真实IP,在服务器上创建大量链接,从而占满服务器链接队列,致使正常链接被丢弃。

HTTP Get Flood:发送大量会产生sql查询的链接,使得数据库负载很高。

CSRF跨站请求伪造原理

攻击者盗用了你的身份,以你的名义发送恶意请求。

CSRF攻击是源于WEB的隐式身份验证机制!WEB的身份验证机制虽然能够保证一个请求是来自于某个用户的浏览器,但却没法保证该请求是用户批准发送的!

防护方式:1.验证码;2. 后台生成token,让前端请求携带。3.使用对称加密,后端随机给前端一个密钥,前端进行加密,后端解密。

会话劫持

经过暴力破解、 预测、窃取(经过XSS攻击)等方式获取到用户session

防护方式

更改Session名称

关闭透明化Session ID。透明化Session ID指当浏览器中的Http请求没有使用Cookie来存放Session ID时,Session ID则使用URL来传递。

设置HttpOnly。经过设置Cookie的HttpOnly为true,能够防止客户端脚本访问这个Cookie,从而有效的防止XSS攻击。

XSS攻击

XSS攻击是Web攻击中最多见的攻击方法之一,它是经过对网页注入可执行代码且成功地被浏览器执行,达到攻击的目的,造成了一次有效XSS攻击,一旦攻击成功,它能够获取用户的联系人列表,而后向联系人发送虚假诈骗信息,能够删除用户的日志等等,有时候还和其余攻击方式同时实施好比SQL注入攻击服务器和数据库、Click劫持、相对连接劫持等实施钓鱼,它带来的危害是巨大的,是web安全的头号大敌。

XSS反射型攻击,恶意代码并无保存在目标网站,经过引诱用户点击一个连接到目标网站的恶意连接来实施攻击的。

XSS存储型攻击,恶意代码被保存到目标网站的服务器中,这种攻击具备较强的稳定性和持久性,比较常见场景是在博客,论坛等社交网站上,但OA系统,和CRM系统上也能看到它身影,好比:某CRM系统的客户投诉功能上存在XSS存储型漏洞,黑客提交了恶意攻击代码,当系统管理员查看投诉信息时恶意代码执行,窃取了客户的资料,然而管理员绝不知情,这就是典型的XSS存储型攻击。

+解决方法

在表单提交或者url参数传递前,对须要的参数进行过滤

过滤用户输入。检查用户输入的内容中是否有非法内容。如<>(尖括号)、”(引号)、 ‘(单引号)、%(百分比符号)、;(分号)、()(括号)、&(& 符号)、+(加号)等

RPC与HTTP服务的区别

数据库原理

MYISAM与innodb搜索引擎原理

MyISAM引擎使用B+Tree做为索引结构,叶节点的data域存放的是数据记录的地址。其采用索引文件与数据文件,索引文件只存放索引,叶子节点存放数据的物理地址。数据文件存放数据。其索引方式是非汇集的。

InnoDB也使用B+Tree做为索引结构。可是它的主索引与数据都放在一个文件中。这种索引叫作汇集索引,由于InnoDB的数据文件自己要按主键汇集,因此InnoDB要求表必须有主键(MyISAM能够没有),若是没有显式指定,则MySQL系统会自动选择一个能够惟一标识数据记录的列做为主键,若是不存在这种列,则MySQL自动为InnoDB表生成一个隐含字段做为主键,这个字段长度为6个字节,类型为长整形。

区别一:InnoDB的主索引与数据都放在一个文件中。而MYISAM是分开存放的。

区别二:InnoDB的辅助索引data域存储相应记录主键的值而不是地址。

区别三:InnoDB的主键索引是汇集索引,而MYISAM不是汇集索引。

索引,聚簇索引和二级索引的加锁区别

汇集(clustered)索引,也叫聚簇索引。数据行的物理顺序与列值(通常是主键的那一列)的逻辑顺序相同,一个表中只能拥有一个汇集索引。

非汇集(unclustered)索引。该索引中索引的逻辑顺序与磁盘上行的物理存储顺序不一样,一个表中能够拥有多个非汇集索引。会发生二次查询。

稠密索引:稠密索引文件中的索引块保持键的顺序与文件中的排序顺序一致。

稀疏索引:稀疏索引没有为每一个数据都建立一个索引,它比稠密索引节省了更多的存储空间,但查找给定值的记录需更多的时间。只有当数据文件是按照某个查找键排序时,在该查找键上创建的稀疏索引才能被使用,而稠密索引则能够应用在任何的查找键。

联合索引:将一张表中多个列组成联合索引(col1,col2,col3),其生效方式知足最左前缀原则。

最左前缀:假如咱们建立了联合索引(col1,col2,col3),那么至关于建立了(col1),(col1,col2),(col1,col2,col3)这3个索引,而后where条件会根据出现的列名挑选最严格的索引。例如where col1=? and col2=? and col3=?,那么就会使用(col1,col2,col3);若是where col1=? and col3 =?,那么就会使用(col1);若是where col2=? and col3=?,那么一个都不会使用。所以在建立多列索引时,要根据业务需求,where子句中使用最频繁的一列放在最左边。

选择性:不重复数占全部记录的比例,假若有10w条记录,unique以后有9w条,那么选择性位90%。主要有两个做用:1. 查看某一列是否有必要创建索引;2. 对于String、hash值、日期等字段,应该取多少位来创建索引(即便用前缀索引),由于主键越短,整个索引表越小。

覆盖索引:对于二级索引而言,在innodb中通常是须要先根据二级索引查询到主键,而后在根据一级索引查询到数据。可是若是select的列都在索引中,就避免进行一级查询。

主键选择

在使用InnoDB存储引擎时,若是没有特别的须要,请永远使用一个与业务无关的自增字段做为主键。

where 1 = 1:可以方便咱们拼sql,可是使用了以后就没法使用索引优化策略,所以会进行全表扫描,影响效率。

分表分库

水平拆分:依据表中的数据的逻辑关系,将同一个表中的数据依照某种条件拆分到多台数据库(主机)上面。按照1个或多个字段以及相应的规则,将一张表重的数据分到多张表中去。好比按照id%5的规则,将一张大表拆分红5张小表。适合具备超大表的系统。

垂直拆分:依照不一样的表(或者Schema)来切分到不一样的数据库(主机)之上。通常按照模块来分库。适合各业务之间耦合度很是低的系统。

validationQuery:用来验证数据库链接的查询语句,这个查询语句必须是至少返回一条数据的SELECT语句。

select锁定记录

select * from table where ?;不加锁

将查询放到事物中

select * from table where ? lock in share mode;加共享锁

select * from table where ? for update;加排它锁

insert, update, delete;加排它锁

隔离级别

read uncommit:读不加锁,写加共享锁。会产生脏读、幻读。

read commit:读加共享锁,写加排它锁,但不加间隙锁。间隙锁的主要做用是防止不可重复读,但会加大锁的范围。

repeatable read(innodb默认):读加共享锁,写加间隙排它锁。注意,Innodb对这个级别进行了特殊处理,使得这个级别可以避免幻读,但不是全部引擎都可以防止幻读!(网易面试官问)

serialization:会给整张表加锁,强一致,可是效率低。

innodb中的锁

MVCC(multi-Version Concurrency Control):读不加锁,读写不冲突。适合写少读多的场景。读操做分为:快照读(返回记录的可见版本,不加锁)、当前读(记录的最新版本,加锁,保证其它记录不修改)。

LBCC(Lock-Based Concurrency Control):

join原理

Simple Nested-Loop Join:效率最低,按照join的次序,在join的属性上一个个扫描,并合并结果。

Index Nested-Loop Join:效率最高,join的属性上面有索引,根据索引来匹配。

Block Nested-Loop Join:用于没有索引的列。它会采用join buffer,将外表的值缓存到join buffer中,而后与内表进行批量比较,这样能够下降对外表的访问频率

galera

多主架构:真正的多点读写的集群,在任什么时候候读写数据,都是最新的。

同步复制,各节点间无延迟且节点宕机不会致使数据丢失。

紧密耦合,全部节点均保持相同状态,节点间无不一样数据。

无需主从切换操做。

无需进行读写分离。

并发复制:从节点在APPLY数据时,支持并行执行,有更好的性能表现。

故障切换:在出现数据库故障时,由于支持多点写入,切的很是容易。

热插拔:在服务期间,若是数据库挂了,只要监控程序发现的够快,不可服务时间就会很是少。在节点故障期间,节点自己对集群的影响很是小。

自动节点克隆:在新增节点,或者停机维护时,增量数据或者基础数据不须要人工手动备份提供,Galera Cluster会自动拉取在线节点数据,最终集群会变为一致。

对应用透明:集群的维护,对应用程序是透明的,几乎感受不到。

如下是缺点

目前的复制仅仅支持InnoDB存储引擎

DELETE操做不支持没有主键的表

在多主环境下LOCK/UNLOCK TABLES不支持以及锁函数GET_LOCK(), RELEASE_LOCK()

因为集群是乐观的并发控制,事务commit可能在该阶段停止。

整个集群的写入吞吐量是由最弱的节点限制,若是有一个节点变得缓慢,那么整个集群将是缓慢的。为了稳定的高性能要求,全部的节点应使用统一的硬件。

LSM Tree,主要应用于nessDB、leveldb、hbase

核心思想的核心就是放弃部分读能力,换取写入的最大化能力。它假设假定内存足够大,所以不须要每次有数据更新就必须将数据写入到磁盘中,而能够先将最新的数据驻留在内存中,等到积累到最后多以后,再使用归并排序的方式将内存内的数据合并追加到磁盘队尾。(使用归并排序是要由于带排序树都是有序树)

LSM具备批量特性,存储延迟。B树在insert的时候可能会形成分裂,可能会形成随机读写。而LSM将屡次单页随机写,变成一次多页随机写,复用了磁盘寻道时间,极大提高效率。

LSM Tree放弃磁盘读性能来换取写的顺序性。

通常会使用Bloom Filter来优化LSM。当将内存中的数据与磁盘数据合并的时候,先要判断数据是否有重复,若是不用Bloom Filter就须要在磁盘上一层层地找,而使用了以后就会下降搜索代价。

多线程

synchronized、CAS

Collections

支持高并发的数据结构,如ConcurrentHashMap

基于AQS实现的锁、信号量、计数器原理

Runnable与Callable的区别

线程池

做用

减小在建立和销毁线程上所花的时间以及系统资源的开销 。

当前任务与主线程隔离,能实现和主线程的异步执行,特别是不少能够分开重复执行的任务。

阻塞队列

threadlocal

框架

Spring

IOC/DI

Core、Beans、Context、Expression Language

JDBC、ORM、OXM、JMS、Transaction

AOP

Web

Test

@Autowired原理

工厂模式

反射

自动配置

@ConfigurationProperties(prefix = "hello"):读取以hello为开头的配置,属性类使用

@Configuration:指名当前类为配置类

@EnableConfigurationProperties(Properties):指名配置属性类

@ConditionalOnClass(Condition.class):条件类,只有Condition.class存在,当前配置类才生效

Spring Boot在spring.factories配置了不少全限定名的配置类。

Netty架构

Redis

核心原理

经常使用数据类型

String:二进制安全,能够存任何数据,好比序列化的图片。最大长度位512M.

Hash:是KV对集合,本质是String类型的KV映射,适合存储对象。

List:简单字符串链表,能够在left、right两边插入,本质是双向链表。缓冲区也是用这个实现。

Set:String类型的无序集合,内部实现是一个 value永远为null的HashMap,实际就是经过计算hash的方式来快速排重的,这也是set能提供判断一个成员是否在集合内的缘由。

zset:有序集合,每一个元素会关联一个double类型的score,而后根据score进行排序。注意:元素不能重复,可是score是能够重复的。使用HashMap和跳跃表(SkipList)来保证数据的存储和有序,HashMap里放的是成员到score的映射,而跳跃表里存放的是全部的成员,排序依据是HashMap里存的score.

pub/sub:在Redis中,你能够设定对某一个key值进行消息发布及消息订阅,当一个key值上进行了消息发布后,全部订阅它的客户端都会收到相应的消息。

持久化

RDB:一种是手动执行持久化命令来持久化快照;另外一种是在配置文件中配置策略,来自动持久化。持久化命令有save、bgsave两种,bgsave会调用fork命令,产生子进程来进行持久化,而父进程继续处理数据,可是持久化的快照是fork那一刻的快照,所以这种策略可能会丢失一部分数据。特色:每次都记录全部数据,恢复快,子进程不影响父进程性能。

AOF:append only file,将每条操做命令都记录到appendonly.aof文件中,可是不会立马写入硬盘,咱们能够配置always(每有一个命令,都同步)、everysec(每秒同步一次)、no(没30秒同步一次)。每每everysec就够了。aof数据损失要比RDB小。特色:有序记录全部操做,数据丢失更少,会对操做作压缩优化,bgrewriteaof也会fork子进程,不影响父进程性能

事务

Transactions:不是严格的ACID的事务,可是这个Transactions仍是提供了基本的命令打包执行的功能(在服务器不出问题的状况下,能够保证一连串的命令是顺序在一块儿执行的,中间有会有其它客户端命令***来执行)。

Redis还提供了一个Watch功能,你能够对一个key进行Watch,而后再执行Transactions,在这过程当中,若是这个Watched的值进行了修改,那么这个Transactions会发现并拒绝执行。

KafKA

topic

broker

partition

consumer

producer

stream

存储机制

网络模型

注意:partition之间是无序的

消息队列的生产者消费者中消费者没有收到消息怎么办,消息有顺序好比1.2.3可是收到的倒是1.3.2怎么办?消息发过来的过程当中损坏或者出错怎么办

Spring security

拦截器栈

@PreAuthorize

@PostAuthorize

支持Expression Language

jvm原理

内存模型

垃圾收集器,CMS与G1是重点

垃圾收集算法

标记-清除(CMS)容易产生碎片,当碎片太多会提早触发Full GC

复制(年轻代基本用这个算法)会浪费一半的可能感受

标记-整理(serial Old、Parallel Old)

Serial:采用单线程stop-the-world的方式进行收集。当内存不足时,串行GC设置停顿标识,待全部线程都进入安全点(Safepoint)时,应用线程暂停,串行GC开始工做,采用单线程方式回收空间并整理内存。串行收集器特别适合堆内存不高、单核甚至双核CPU的场合。

ParNew

Parallel Scavenge

CMS:

初始标记(stop of world)

并行标记、预清理

从新标记(stop of world)

并行清理

重置

G1:将堆分红不少region,能够同时堆年轻代与老年代进行收集

初始标记(stop of world):初始标记(Initial Mark)负责标记全部能被直接可达的根对象(原生栈对象、全局对象、JNI对象)

并行标记:

从新标记(stop of world):

清理(stop of world):

重置:

Pause Prediction Model(停顿预测模型)

核心代码MAX2(seq->davg() + sigma() * seq->dsd(),seq->davg() * confidence_factor(seq->num()));其中seq->davg()表示衰减均值,sigma()返回一个系数,表示信赖度,dsd表示衰减标准误差,confidence_factor表示可信度相关系数。

gc触发条件

从年轻代分区拷贝存活对象时,没法找到可用的空闲分区,会触发Minor GC

从老年代分区转移存活对象时,没法找到可用的空闲分区,会触发Major GC

分配巨型对象时在老年代没法找到足够的连续分区,会触发Major GC

可达性分析:经过检查一块内存空间可否被root达到,来判断是否对其进行回收。

jdk不一样版本新增的部分特性

1.7

switch语句中支持使用字符串了

try catch支持捕获多个异常,竖线分割异常便可

try块中使用的资源能够不用手动在finally中关闭

支持 List tempList = new ArrayList<>()的声明方式,实际上是泛型实例化类型自动推断。

提供自定义关闭类的接口,实现AutoCloseable ,就能够在类销毁的时候自动关闭一些资源。

1.8

接口的默认方法

Lambda 表达式,@FunctionInterface注解

容许你使用 :: 关键字来传递方法或者构造函数引用

在包java.time下包含了一组全新的时间日期API。

jvm调优

VisualVM:JDK自带JVM可视化工具,能过对内存、gc、cpu、thread、class、变量等等信息进行可视化。

类加载

类加载器

Bootstrap ClassLoader:由c语言实现,用来加载JVM自身工做须要的类。这个类不在双亲委派体系中。

ExtClassLoader:用于加载java\jre\lib\ext目录下的jar

AppClassLoader:父类加载器为ExtClassLoader,会加载classpath下全部的类。

类加载方式

隐士加载:不经过代码里面调用ClassLoader来加载须要的类,而是经过JVM来自动加载须要的类到内存。

显示加载:经过调用ClassLoader.loadClass或Class.forName(),或本身实现ClassLoader的findClass方法来加载类。

自定义ClassLoader:父类加载器老是getSystemClassLoader()方法获取到的ClassLoader。由于无论调用哪一个父类加载器,建立对象最终都会调用getSystemClassLoader做为父加载器,在通常应用中getSystemClassLoader会获取AppClassLoader,但在tomcat中getSystemClassLoader()会返回StandardClassLoader。

流程:加载(调用findClass方法)->验证(各类检查)->准备(将静态属性用零值初始化)->解析(将符号引用替换成直接引用)->初始化(调用clinit方法)

双亲委派:记载一个类的时候,会先递归检查父类是否加载过,避免重加载。若是发生重加载,那原来的类与新加载的类 stanceof判断是false。

热部署:利用判断两个class是不是同一个,须要校验类名与类加载器是否同样的原理。热部署的类都是用完释放,每次使用都先new一个classLoader,而后用这个classLoader来加载这个类,这样生成的类虽然与以前的名称同样,可是实际上不是同一个。

javac编译器

读取源码

词法分析,从原文件的字符开始,按照java语法规范依次找出package、import、类定义、属性、方法、关键词等。

语法分析,造成一颗符合java规范的抽象语法树,它能将主要词法用一个结构化的形式去表达。

语义分析,将一些难懂的、复杂的语法转化为更加简单的语法。好比添加解除语法糖、默认构造方法、检查语句是否可达、检查变量类型是否匹配、检查checked exception 是否捕捉或抛出.

经过字节码生成器生成字节码

interface能够多继承;class只能单继承,多实现

String

没法被继承,由于它是final class,其被设计成final主要出于如下考虑:

字符串常量池的须要。字符串常量池的诞生是为了提高效率和减小内存分配。字符串重复的可能性很高,而且其不可变性可以方便常量池优化。

安全性考虑。正由于使用字符串的场景如此之多,因此设计成不可变能够有效的防止字符串被有意或者无心的篡改。(可是经过反射仍是能够入侵的)

做为HashMap、HashTable等hash型数据key的必要。由于不可变的设计,jvm底层很容易在缓存String对象的时候缓存其hashcode,这样在执行效率上会大大提高。

String.equals()是的实现是逐字符比较两个String对象的char,而==是比较引用。

String.intern()会获取在字符串常量池中的字符串对象,若是该字符串不在常量池中,那会将它假如常量池,而后再返回该对象。所以若是连个String的值同样,那么调用intern()方法返回的都是其再常量池中的对象,而常量池中同样的字符串只有一个对象,所以使用==比较也是true。

int的范围-2^32~2^32-1

序列化的底层实现

java深拷贝

实现Cloneable接口的clone方法

经过序列化实现

设计模式

单例

双重检查

静态内部类

枚举(jdk1.8以后支持)

观察者模式

装饰者模式:jdk中输入输出流用到了该模式

适配器模式:jdk中Reader、writer用到了该模式

***模式

静态***

JDK动态***

Cglib到动态***

生产者消费者模式

工厂模式

项目管理与运维工具

git+Jenkins

maven

K8S

pod:Pod是全部业务类型的基础,全部的容器均在Pod中运行,它是一个或多个容器的组合。每个Pod都会被指派一个惟一的Ip地址,在Pod中的每个容器共享网络命名空间,包括Ip地址和网络端口。Pod可以被指定共享存储卷的集合,在Pod中全部的容器可以访问共享存储卷,容许这些容器共享数据。

kubelet:kubelet负责管理pods和它们上面的容器,images镜像、volumes、etc。

kube-proxy:为Service提供cluster内部的服务发现和负载均衡;

etcd:全部master的持续状态都存在etcd的一个实例中。这能够很好地存储配置数据。由于有watch(观察者)的支持,各部件协调中的改变能够很快被察觉。

一旦一个Pod被建立,系统就会不停的监控Pod的健康状况以及Pod所在主机的健康状况,若是这个Pod由于软件缘由挂掉了或者所在的机器挂掉了,replication controller 会自动在一个健康的机器上建立一个一摸同样的Pod,来维持原来的Pod冗余状态不变,一个应用的多个Pod能够共享一个机器。

ingress,用于负载均衡

docker

docker与虚拟机的区别

数据结构

平衡二叉树AVL

高度log(n)

插入时间复杂度log(n)

红黑树

插入时间复杂度log(n)

查找时间复杂度log(n)

在查找是,红黑树虽然复杂度也是log(n),可是从效率上比要略低于AVL。可是其优点在于插入元素的时候,不会像AVL那样频繁地旋转。

B+Tree:只有叶子节点存值,非叶子节点只存key和child,所以一样大小的物理页上能存放更多的节点。每一层的节点数量越多,意味着层次越少,也就意味着IO次数越少,所以很是适合数据库以及文件系统。

大根堆:采用数组存储树,是一个彻底树。先插入到数组最后的位置上,而后采用上浮的思想,将该元素与比它小的父元素调换,直到parent>target,浮到root;而后将root与未排序的最后一个元素交换位置;重复以上步骤,直到全部元素都有序。插入如查找的复杂度都是log(n)。

优先队列PriorityQueue,Java中使用小根堆实现,非线程安全。

优先阻塞队列PriorityBlockQueue,线程安全。

算法

快排

时间复杂度O(nlog(n))

空间复杂度O(log(n))

堆排序

时间复杂度O(nlog(n))

空间复杂度O(1)

归并排序

时间复杂度O(nlog(n))

空间复杂度O(n)

跳表

时间复杂度O(log(n))

空间复杂度O(2n)

高度O(log(n))

分布式

cap理论

可用性

一致性

分区容忍性:对网络断开的容忍度,有点像鲁棒性

拜占庭将军问题

问题描述

拜占庭帝国即中世纪的土耳其,拥有巨大的财富,周围10个邻邦垂诞已久,但拜占庭高墙耸立,固若金汤,没有一个单独的邻邦可以成功入侵。任何单个邻邦入侵的都会失败,同时也有可能自身被其余9个邻邦入侵。拜占庭帝***御能力如此之强,至少要有十个邻邦中的一半以上同时进攻,才有可能攻破。然而,若是其中的一个或者几个邻邦自己答应好一块儿进攻,但实际过程出现背叛,那么入侵者可能都会被歼灭。因而每一方都当心行事,不敢轻易相信邻国。这就是拜占庭将军问题。这个问题的本质是要达成一致的共识。

Raft 算法

有leader、follower、candidate

选主流程:

在最初,尚未一个主节点的时候,全部节点的身份都是Follower。每个节点都有本身的计时器,当计时达到了超时时间(Election Timeout),该节点会转变为Candidate。

成为Candidate的节点,会首先给本身投票,而后向集群中其余全部的节点发起请求,要求你们都给本身投票。

其余收到投票请求且还未投票的Follower节点会向发起者投票,发起者收到反馈通知后,票数增长。

当得票数超过了集群节点数量的一半,该节点晋升为Leader节点。Leader节点会马上向其余节点发出通知,告诉你们本身才是老大。收到通知的节点所有变为Follower,而且各自的计时器清零。

注意:每一个节点的超时时间都是不同的。好比A节点的超时时间是3秒,B节点的超时时间是5秒,C节点的超时时间是4秒。这样一来,A节点将会最早发起投票请求,而不是全部节点同时发起。若是全部节点同时发起投票,必然会致使你们的票数差很少,造成僵局,谁也当不成老大。一旦Leader节点挂掉,发不出通知,那么计时达到了超时时间的Follower节点会转变为Candidate节点,发起选主投票,周而复始。

同步流程

由客户端提交数据到Leader节点。

由Leader节点把数据复制到集群内全部的Follower节点。若是一次复制失败,会不断进行重试。

Follower节点们接收到复制的数据,会反馈给Leader节点。

若是Leader节点接收到超过半数的Follower反馈,代表复制成功。因而提交本身的数据,并通知客户端数据提交成功。

由Leader节点通知集群内全部的Follower节点提交数据,从而完成数据同步流程。

zookeeper,参考博客1参考博客2

leader:复制进行投票的发起和决议,更新系统状态。

follower:接收client的请求并返回结果,在选主过程当中进行投票。

observer:接收client链接,并将请求转发给leader节点。在不参加投票,只是同步leader状态。

client:请求发起方。

Zab(Zookeeper Atomic Broadcast)协议,有两种模式,它们分别是恢复模式(选主)和广播模式(同步)。

选主:有两种算法:1. basic paxos;2. fast paxos(默认)

basicpaxos流程

当前Server担任***线程,其主要功能是对投票结果进行统计,并选出推荐的Server。

***线程首先向全部Server发起一次询问(包括本身);

***线程收到回复后,验证是不是本身发起的询问(验证zxid是否一致),而后获取对方的id(myid),并存储到当前询问对象列表中,最后获取对方提议的leader相关信息(id,zxid),并将这些信息存储到当次***的投票记录表中;

收到全部Server回复之后,就计算出zxid最大的那个Server,并将这个Server相关信息设置成下一次要投票的Server;

线程将当前zxid最大的Server设置为当前Server要推荐的Leader,若是此时获胜的Server得到n/2 + 1的Server票数, 设置当前推荐的leader为获胜的Server,将根据获胜的Server相关信息设置本身的状态,不然,继续这个过程,直到leader被***出来。

同步流程

leader等待server链接;

Follower链接leader,将最大的zxid发送给leader;

Leader根据follower的zxid肯定同步点;

完成同步后通知follower 已经成为uptodate状态;

Follower收到uptodate消息后,又能够从新接受client的请求进行服务了。

事务顺序一致性:采用了递增的事务id号(zxid)来标识事务。全部的提议(proposal)都在被提出的时候加上了zxid。

server的状态

LOOKING:当前Server不知道leader是谁,正在搜寻

LEADING:当前Server即为***出来的leader

FOLLOWING:leader已经***出来,当前Server与之同步

文件系统:zookeeper的通知机制、分布式锁、队列管理、配置管理都是基于文件系统的。文件系统中有一下几种节点:

PERSISTENT-持久化目录节点,客户端与zookeeper断开链接后,该节点依旧存在 。

PERSISTENT_SEQUENTIAL-持久化顺序编号目录节点,客户端与zookeeper断开链接后,该节点依旧存在,只是Zookeeper给该节点名称进行顺序编号。

EPHEMERAL-临时目录节点,客户端与zookeeper断开链接后,该节点被删除。

EPHEMERAL_SEQUENTIAL-临时顺序编号目录节点,客户端与zookeeper断开链接后,该节点被删除,只是Zookeeper给该节点名称进行顺序编号。

通知机制:客户端注册监听它关心的目录节点,当目录节点发生变化(数据改变、被删除、子目录节点增长删除)时,zookeeper会通知客户端。

配置管理:把这些配置所有放到zookeeper上去,保存在 Zookeeper 的某个目录节点中,而后全部相关应用程序对这个目录节点进行监听,一旦配置信息发生变化,每一个应用程序就会收到 Zookeeper 的通知,而后从 Zookeeper 获取新的配置信息应用到系统中。

分布式锁:有了zookeeper的一致性文件系统,锁的问题变得容易。锁服务能够分为两类,一个是保持独占,另外一个是控制时序。

独占锁:将zookeeper上的一个znode看做是一把锁,经过createznode的方式来实现。全部客户端都去建立 /distribute_lock 节点,最终成功建立的那个客户端也即拥有了这把锁。用完删除掉本身建立的distribute_lock 节点就释放出锁。

控制时序锁:/distribute_lock 已经预先存在,全部客户端在它下面建立临时顺序编号目录节点,和选master同样,编号最小的得到锁,用完删除。

队列管理,分为同步队列、非同步队列

同步队列,当一个队列的成员都聚齐时,这个队列才可用,不然一直等待全部成员到达。 在约定目录下建立临时目录节点,监听节点数目是不是咱们要求的数目。

队列按照 FIFO 方式进行入队和出队操做。和分布式锁服务中的控制时序场景基本原理一致,入列有编号,出列按编号。

数据复制的好处

容错:一个节点出错,不致于让整个系统中止工做,别的节点能够接管它的工做;

提升系统的扩展能力 :把负载分布到多个节点上,或者增长节点来提升系统的负载能力;

提升性能:让客户端本地访问就近的节点,提升用户访问速度。

数据复制集群系统分下面两种:

写主(WriteMaster) :对数据的修改提交给指定的节点。读无此限制,能够读取任何一个节点。这种状况下客户端须要对读与写进行区别,俗称读写分离;

写任意(Write Any):对数据的修改可提交给任意的节点,跟读同样。这种状况下,客户端对集群节点的角色与变化透明。

Broker模式

主要有这6个类:Client,Server,Client_Proxy,Server_Proxy,Broker,Bridge。

Server:就是咱们根据业务写的服务。

Client:请求发起方,Client发送请求到Broker,并从Broker上接收响应或异常。Client和Server只是逻辑上相关而已,实际上Client并不知道Server的确切位置。

Broker:成消息转发器。Broker也负责一些控制和管理操做。它可以定位服务端的位置,若发生异常,可以将异常捕获传给Client。Broker须要提供注册服务的接口给Server。

Client_Proxy:连系Client和Broker,这一层保证了通信的透明性,使Client调用远程服务就像调用本地的服务同样。

Server_Proxy:与Client_Proxy相对应的,它接受请求,解包消息,解析出参数并调用服务的实现接口。

Bridge:Bridge用来链接各个Broker,通常这个组件是可选的。

一致性hash算法原理

微服务

Spring cloud

网关:zuul

分布式\版本化配置 config

服务注册和发现:Eureka,配置时须要注意多久刷新列表一次,多久监测心跳等。

service-to-service 调用

负载均衡:Ribbon;在生成RestTemplate的bean时,经过@LoadBalanced注解可使得RestTemplate的调用

断路器:Hystrix

监控:spring admin。在启动类上加@EnableAdminServer注解。

java web

servlet工做原理

建立:若是load-on-startup>0,那就会在Context容器启动的时候实例化。一、Wrapper.loadServlet获取servletClass。二、传给InstanceManager建立对象。

初始化:即调用Servlet的init方法

tomcat工做原理,好文,强推

service,一个server有多个service,一个service有一个container与多个connector

connector,负责接受请求,并将请求封装成request,同时建立repsonse对象传给container。

container

engine

host,一个端口一个,或tomcat上面一个服务一个

context,管理多个wrapper,是servlet的运行环境

wrapper,一个servlet一个

linux

系统结构,讲得很好,强推

硬连接与软链接

硬连接:数据节点经过引用计数的方式来对指向它的硬连接计数,当计数为0就删除。

软链接:咱们能够把它当作是快捷方式,它只是记录了某个文件的硬连接的路径,若是咱们把源文件删除,再从新建立一个相同名字的文件,那么软链接指向的就是新建立的文件。

虚拟文件系统(VFS):文件系统是有不少实现的,好比ext二、ext三、FAT等等,而VFS则是存在于应用程序与文件系统中间,它封装了open、close、read、write等等操做文件系统的接口,为应用程序屏蔽掉不一样文件系统之间的差别。

VFS数据结构

其它

bitmap,大文件交集

Elasticsearch索引原理

从内存到屏幕经历了啥

高并发场景的限流,你怎么来肯定限流限多少,模拟场景和实际场景有区别怎么解决,

EMC面试

说一下redis与kafka,redis持久化策略

git中rebase与merge区别

docker底层原理,依赖操做系统的什么

ls -l | grep xxx的执行过程,尽量的细,是多进程仍是单进程?

两个有序数组求中位数

算法 3Sum、中序遍历非递归实现、循环打印矩阵

final、finally、finanize

jvm内存模型

垃圾回收器

Spring特色介绍下

Synchronize与ReentrantLock的区别、使用场景

CAS使用场景

聊了下git+jekins+K8S+docker实现自动化部署

innodb原理,使用场景,与MYISAM在场景上的区别

weakReference、softReference等

Hbase的原理,LSM Tree

Linux中,哪一种进程可使用管道

美团

权限模型

介绍下线程池,阻塞队列的用法,***队列真的***吗?

说一下redis

kafka存储模型与网络模型

zookeeper与redis实现分布式锁

乐观锁与悲观锁

算法:有n我的,给你ai与aj的身高关系,如ai比aj高,进行身高排序,若是条件不知足,则输出“不知足”

Spring boot的特性


有什么问题,欢迎留言沟通,在这里也祝你们都能找到一个合适的工做~

特别声明:本文素材来源于网络,仅做为分享学习之用,若有侵权,请联系删除!
相关文章
相关标签/搜索