admin管理员组

文章数量:1579445

美团面试题:

1.为什么要用SOA?有什么好处?

面向服务编程,是一种思想,一种方法论,一种分布式的服务架构,
SOA是⼀种软件架构,它⽤于构建由⼀组松耦合,⿊盒组件组成的商业应⽤。每个组件代表 一个独立服务。
优点:服务之间松耦合、组织和使用来自不同拥有者的服务能力。统一的方式去发布、发现、交互和调用服务、而不需要知道底层技术细节。、可组合的、可全局访问的功能。

用途:SOA解决多服务凌乱问题,SOA架构解决数据服务的复杂程度,同时SOA又有一个名字,叫做服务治理。让程序之间关系服务简单。

2.为什么进行模块化?粒度是多少?

模块化开发的另一个好处是如果dao的代码被修改,只需要重新build dao模块就可以了。web模块可以build成war,dao、service、util等可以build成jar,只需要配置好依赖关系,就可以实现模块间的解耦合。这样的设计才是遵循“高内聚,低耦合”设计原则的。
粒度似乎是根据项目模块划分的细致程度区分的,一个项目模块(或子模块)分得越多,每个模块(或子模块)越小,负责的工作越细,就说粒度越细,否则为粗粒度”。

3.为什么需要拆呢?根据什么进行拆分?

将一个大的复杂问题,变成很多个小问题解决。所以当一个系统复杂到一定程度,当维护一个系统的人数多到一定程度,解决问题的难度和沟通成本大大提高,因而需要拆成很多个工程,拆成很多个团队,分而治之。

5.SpringMVC和SpringBoot的关系?

spring mvc < spring <springboot。

6.服务之间,用Tomcat也能调用服务,为什么要用dubbo.

相同点:tomcat 是 http 服务器,基于 tcp 协议,dubbo 框架支持多种协议(dubbo, hessian 等),常用的 dubbo 协议也是基于 tcp 协议。即 dubbo 的 consumer 和 provider 首先要建立 tcp 连接,然后才能发送数据。
不同点:
(1)http 客户端如何发送请求?首先建立 tcp 连接,然后发送 http 请求报文,接着等待 http 响应报文,http 报文都是明文字符串。
dubbo 客户端如何发送请求呢?正常情况下,provider 会暴露服务,consumer 去 refer 服务获得代理,然后通过代理调用服务,这里有很长的一个调用栈,底层也是 consumer 发送 request,等待 provider 的 response,但是这里的 request 和 response 都是序列化的 java 对象。
(2)http 客户端发送请求,必然会收到对应的 http 响应,而 dubbo consumer 发送请求时可以设置为 oneway,即不需要响应,则 dubbo provider 不会发送响应,请求也可以设置为同步或者异步,不管同步还是异步都是有响应的

7.dubbo为什么性能比较高?

单一应用架构
当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。 此时,用于简化增删改查工作量的数据访问框架(ORM) 是关键。

垂直应用架构
当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成互不相干的几个应用,以提升效率。此时,用于加速前端页面开发的 Web框架(MVC) 是关键。

分布式服务架构
当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。此时,用于提高业务复用及整合的 分布式服务框架(RPC) 是关键。

流动计算架构
当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。
此时,用于提高机器利用率的 资源调度和治理中心(SOA) 是关键。
负载均衡:
负载均衡建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。
负载均衡(Load Balance)其意思就是分摊到多个操作单元上进行执行,例如Web服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。

Docker:之所以采用docker部署的形式,是考虑到微服务节点的部署,以及后续的集群扩展的便捷性。

8. Dubbo有哪些协议?

Dubbo 缺省协议采用单一长连接和 NIO 异步通讯,适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况。反之,Dubbo 缺省协议不适合传送大数据量的服务,比如传文件,传视频等,除非请求量很低。
http协议:走json序列化
rmi协议:走java二进制序列化,多个短连接,适合消费者和提供者数量差不多,适用于文件的传输,一般较少用。
9.何为HTTP 协议?HTTP协议在哪一层?
超文本传输协议:服务器传输超文本到本地浏览器的传送协议。

HTTP是属于短连接,适合新闻,订票信息等客户端发起请求,每一次请求结束,自动断开连接。

Socket是属于长连接,适合游戏,聊天等实时数据。

9.文本协议和二进制协议?那个效率更高?http属于那个?(基于文本)

文本协议:一般是由一串ACSII字符组成的数据,这些字符包括数字,大小写字母、百分号,还有回车(\r),换行(\n)以及空格等等。文本协议,直观、描述性强,容易理解,便于调试,缺点就是冗余数据较多,不适宜传输二进制文件(比如:图片等),解析复杂(需要进行字符串比较);

二进制协议就是一串字节流,通常包括消息头(header)和消息体(body),消息头的长度固定,并且消息头包括了消息体的长度。这样就能够从数据流中解析出一个完整的二进制数据,高效传输。

10.Mysql的数据库引擎?

InnoDB(默认):支持事务对于InnoDB每一条SQL语言都默认封装成事务,自动提交,(这样会影响速度)。InnoDB支持外键,支持事务,InnoDB是聚集索引。InnoDB支持行锁,

MyISAM:不支持事务,只支持表锁

11.事务隔离级别有几种?分别怎么实现的?比如可重复读怎么实现的?(加锁)

可读未提交:就是一个事务可以读取另一个未提交事务的数据。
可读已提交:就是一个事务要等另一个事务提交后才能读取数据。
可重复读:,就是在开始读取数据(事务开启)时,不再允许修改操作。
序列化:是最高的事务隔离级别,在该级别下,事务串行化顺序执行,可以避免脏读、不可重复读与幻读。

13.数据库索引?哪些地方用到了索引?

14.介绍下Websocket?它是什么原理?Websocket解决了什么问题?

Websocket是一个持久化的协议,相对于HTTP这种非持久的协议来说,首先Websocket是基于HTTP协议的,或者说借用了HTTP的协议来完成一部分握手。
在握手阶段是一样的WebSocket 是一种双向通信协议,在建立连接后,WebSocket 服务器和 Browser/Client Agent 都能主动的向对方发送或接收数据,就像 Socket 一样;Socket是属于长连接,适合游戏,聊天等实时数据。

15.为什么要用消息队列?

当系统中出现“生产“和“消费“的速度或稳定性等因素不一致的时候,就需要消息队列,作为抽象层,弥合双方的差异。提高系统响应速度,提高系统稳定性,异步化、解耦、消除峰值
“ 消息 ”是在两台计算机间传送的数据单位。消息可以非常简单,例如只包含文本字符串;也可以更复杂,可能包含嵌入对象。消息被发送到队列中,“ 消息队列 ”是在消息的传输过程中保存消息的容器 。

16.DataFormat是线程安全的吗?

不是

17.大概意思是起了好多线程去一个类的属性和方法,怎么保证它是线程安全的?

ThreadLocal:ThreadLocal的实例代表了一个线程局部的变量,每条线程都只能看到自己的值,并不会意识到其它的线程中也存在该变量。(JMM)
它采用采用空间来换取时间的方式,解决多线程中相同变量的访问冲突问题。

18.操作系统管理内存

分页和分段:
页是信息的物理单位,分页是为实现离散分配方式,以消减内存的外零头,提高内存的利用率;或者说,分页仅仅是由于系统管理的需要,而不是用户的需要。

段是信息的逻辑单位,它含有一组其意义相对完整的信息。分段的目的是为了能更好的满足用户的需要。

页的大小固定且由系统确定,把逻辑地址划分为页号和页内地址两部分,是由机器硬件实现的,因而一个系统只能有一种大小的页面。段的长度却不固定,决定于用户所编写的程序,通常由编辑程序在对源程序进行编辑时,根据信息的性质来划分。

分页的作业地址空间是一维的,即单一的线性空间,程序员只须利用一个记忆符,即可表示一地址。分段的作业地址空间是二维的,程序员在标识一个地址时,既需给出段名,又需给出段内地址。
19.一道算法题,站在根节点怎么输出它看到的节点?

菜鸟面试题:

1.String、StringBuffer、StringBuilder的区别,为什么StringBuilder的效率更高?

答:①String: 不可变的;底层final修饰的char数组;
StringBuffer: 可变;安全;(底层方法加锁Sy…);
StringBilder: 可变;不安全;效率高;长度16;扩容2倍+2。
②StringBuilder在append时并不是用String存储,而是放到一个value的char数组中,字符串是固定长度的,而数组是可以扩容的,这样就不需要不停创建对象了。而且只有当append是数据长度+value.count > value.length时才会扩容一次,不会每次都扩容去调用Arrays.copyof()。

2.重载和重写的区别?

重载:一个类中,多个同名方法同时存在,具有不同的参数个数或参数类型时。可以有不同的访问修饰符,可以抛出不同的异常,是一个类中多态性的一种表现。

重写:发生在父类和子类之间,子类重写父类的方法,重写要求:两个方法的参数列表必须相同,返回值类型必须相同,访问修饰符的权限一定要大于被重写的访问修饰符。

3.Java为什么不支持多继承?

多重继承:如果继承的两个父类中都有相同的方法或者变量时,在调用或引用时,不知道该用哪个。
Java使用接口以克服不使用多继承带来的不足。

4.HashMap和Hashtable(都是key-value型)

HashMap: 可为null,不安全,效率高 底层(数组+链表+红黑树)(初始size为16,扩容:newsize = oldsize2)
Hashtable:不可为null,安全,效率低,底层(数组+链表+红黑树)(初始size为11,扩容:newsize = oldsize
2+1)

5.创建线程的方式?创建线池有哪些方法?Executor中有哪些创建线程方法?有什么区别?为什么使用线程池?

有四种:
1.继承Thread类:(不建议,Java单一继承,如果继承了Thread类,就不能继承其他类)
2.实现Runnable接口:实现run方法。
3.实现Callable接口:用FutureTask来实现,实现call方法。这个类实现了Runnable。
4.线程池:
①通过Executors(工具类)提供四种线程池:
(1)newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
(2)newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
(3)newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
(4)newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
②通过ThreadPoolExecutor手写线程池:eg:
Executor executor = new ThreadPoolExecutor(7个参数)。
原因:
1.限定线程的个数,不会导致由于线程过多导致系统运行缓慢或崩溃。
2.线程池不需要每次都去创建或销毁,节约了资源。
3.线程池不需要每次都去创建,响应时间更快。

6.JVM内存模块?程序计数器主要干什么?堆和栈有什么区别?GC主要回收那块地方?在JVM中如何判断两个对象是相同的?

答:JVM内存模块:
(1)栈(方法栈):(线程独占)在执行每个方法时,都会创建,用来存储局部变量、方法出口等信息。
(2)本地方法栈:(线程独占)执行native方法时调用。
(3)程序计数栈:(线程独占)保存当前线程所执行字节码的位置(只服务于Java)
(4)堆:(线程共享)最大的一块,存放对象的实例。
(5)方法区:(线程共享)各个内存共享的区域,又叫非堆区,存:被虚拟机加载的 类信息,常量,静态常量。

GC经常发生的区域是堆区,堆区还可以细分为新生代、老年代,新生代还分为一个Eden区和两个Survivor区。

7.常见的Java设计模式(23种)

设计模式就是经过前人无数次的实践总结出的,设计过程中可以反复使用的、可以解决特定问题的设计方法。
创建型:
单例:一个类只有一个实例。(网站计数器、数据库连接池)。

工厂方法:定义一个创建产品对象的工厂接口,将对象的创建工作推迟到工厂类中。(创建-使用分离)优点:用户只需知道具体工厂的名称就能得到产品。SpringIOC用到了

结构型:
代理模式:由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。

适配器模式:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。

桥接模式:将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。

行为型:
模板方法:定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。它是一种类行为型模式。

命令模式:将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。这样两者之间通过命令对象进行沟通,这样方便将命令对象进行储存、传递、调用、增加与管理。(餐厅吃饭:点的餐:命令。服务员:请求者。厨师:调用者。)

责任链模式:为了避免请求发送者与多个请求处理者耦合在一起,将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。(请假审批)

观察者模式:指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式,它是对象行为型模式。(发布–订阅)贪吃蛇。

8.Spring中用到的设计模式?Spring的单例、工厂、代理在哪些类中用到了?AOP主要解决的问题?(在哪些场景下用到了AOP?)

1.第一种:简单工厂:
又叫做静态工厂方法(StaticFactory Method)模式,但不属于23种GOF设计模式之一。spring中的BeanFactory就是简单工厂模式的体现。

2.第二种:工厂方法:(BeanFactory 或 ApplicationContext 创建 bean 对象)
通常由应用程序直接使用new创建新的对象,为了将对象的创建和使用相分离。一般情况下,应用程序有自己的工厂对象来创建bean.如果将应用程序自己的工厂对象交给Spring管理,那么Spring管理的就不是普通的bean,而是工厂Bean。

3.第三种:单例模式:(Spring 通过 ConcurrentHashMap 实现单例注册表的特殊方式实现单例模式。)
Spring下默认的bean均为singleton,可以通过singleton=“true|false” 或者 scope=“?”来指定。

4.第四种:适配器:
在Spring的Aop中,使用的Advice(通知)来增强被代理类的功能。Spring实现这一AOP功能的原理就使用代理模式(1、JDK动态代理。2、CGLib字节码生成技术代理。)对类进行方法级别的切面增强,即,生成被代理类的代理类, 并在代理类的方法前,设置拦截器,通过执行拦截器重的内容增强了代理方法的功能,实现的面向切面编程。

5.第五种:包装器:
spring中用到的包装器模式在类名上有两种表现:一种是类名中含有Wrapper,另一种是类名中含有Decorator。基本上都是动态地给一个对象添加一些额外的职责。

6.第六种:代理:
为其他对象提供一种代理以控制对这个对象的访问。SpringAOP就是使用的动态代理。

7.第七种:观察者
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
spring中Observer模式常用的地方是listener的实现。如ApplicationListener。

8.第八种:策略
定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
spring中在实例化对象的时候用到Strategy模式。

9.第九种:模板方法
spring中的JdbcTemplate。

AOP解决的问题?

1.代码混乱:越来越多的非业务需求(日志和验证等)加入后, 原有的业务方法急剧膨胀。每个方法在处理核心逻辑的同时还必须兼顾其他多个关注点.

2.代码分散: 以日志需求为例, 只是为了满足这个单一需求, 就不得不在多个模块(方法)里多次重复相同的日志代码.如果日志需求发生变化, 必须修改所有模块。

9.IOC实现原理

IOC容器的设计与实现有两种:BeanFactory和ApplicationContext。
控制反转IoC(Inversion of Control)是说创建对象的控制权进行转移,以前创建对象的主动权和创建时机是由自己把控的,而现在这种权力转移到第三方。

10.Redis的优点?对比memoryCache、Redis过期策略?Redis的持久化有哪些方式?Redis缓存雪崩、击穿等常见问题?雪崩的解决?

特点:
1.内存数据库,速度快,也支持数据的持久化,可以将内存中的数据保存在磁盘
中,重启的时候可以再次加载进行使用。
2.Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
3.Redis支持数据的备份,即master-slave模式的数据备份。
4.支持事务。

优点:
1.性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。

2.丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。

3.原子 – Redis的所有操作都是原子性的,同时Redis还支持对几个操作合并后的原子性执行。(事务)

4.丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。

过期策略
Redis key过期的方式有三种:
1.被动删除:当读/写一个已经过期的key时,会触发惰性删除策略,直接删除掉这个过期key
2.主动删除:由于惰性删除策略无法保证冷数据被及时删掉,所以Redis会定期主动淘汰一批已过期的key
3.当前已用内存超过maxmemory限定时,触发主动清理策略
memoryCache过期策略:
从源码来说,MSCache提供了以下三种缓存过期的方式
1.绝对到期(指定在一个固定的时间点到期)
2.滑动到期(在一个时间长度内没有被命中则过期)
3.到期Token(自定义过期)

持久化方式:
RDB:持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是fork一个子进程,先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储。
AOF:持久化以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作记录。
Redis问题:
缓存穿透:key对应的数据在数据源并不存在,每次针对此key的请求从缓存获取不到,请求都会到数据源,从而可能压垮数据源。比如用一个不存在的用户id获取用户信息,不论缓存还是数据库都没有,若黑客利用此漏洞进行攻击可能压垮数据库。解决(暴力:如果一个查询返回的数据为空(不管是数据不存在,还是系统故障),我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。)
缓存击穿:key对应的数据存在,但在redis中过期,此时若有大量并发请求过来,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮。解决(使用互斥锁)
缓存雪崩:当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,也会给后端系统(比如DB)带来很大压力。解决(加锁排队、不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀、做二级缓存)

面试题:

TCP、UDP拥塞 流量控制

Java的深浅复制?

浅拷贝:创建一个新对象,然后将当前对象的非静态字段复制到该新对象,如果字段是值类型的,那么对该字段执行复制;如果该字段是引用类型的话,则复制引用但不复制引用的对象。因此,原始对象及其副本引用同一个对象。
深拷贝:创建一个新对象,然后将当前对象的非静态字段复制到该新对象,无论该字段是值类型的还是引用类型,都复制独立的一份。当你修改其中一个对象的任何内容时,都不会影响另一个对象的内容。

为什么双重检查锁在多线程下不安全?

存在指令重排。加Volatile关键字,禁止指令重排。

小米面试题:

1.微聊怎么实现的?

用WebSocket ,是HTML5一种新的协议。它实现了浏览器与服务器全双工通信(full-duplex)。一开始的握手需要借助HTTP请求完成。 WebSocket是真正实现了全双工通信的服务器向客户端推的互联网技术。 它是一种在单个TCP连接上进行全双工通讯协议。Websocket通信协议与2011年倍IETF定为标准RFC 6455,Websocket API被W3C定为标准。(是一种长连接。)

2.说一下你对dubbo的理解?

Dubbo是一款高性能Java RPC框架。是一个分布式服务框架,它最大的特点是按照分层的的方式来架构,使用这种方式可以使各个层之间解耦合(或者最大限度的松耦合)。使用缺省协议(dubbo)。Dubbo能处理掉负载均衡、超时重试等一系列问题。

3.说一下常用的注解。

@SpringBootApplication:是一个组合注解,用于快捷配置启动类。

@SpringBootConfiguration:用来声明当前类是一个配置类。

@Configuration:用来声明当前类是一个配置类。

@Controller:用来表示Spring某个类是否可以接收HTTP请求。
@RestController:用来表示Spring某个类是否可以接收HTTP请求。@RestController 是@Controller和@ResponseBody的结合体,两个标注合并起来的作用。

@PathVariable:是用来赋予请求url中的动态参数,即:将请求URL中的模板变量映射到接口方法的参数上。

@RequestBody:可以将请求体中的JSON字符串绑定到相应的bean上。
@ResponseBody:表示该方法的返回结果直接写入 HTTP response body 中。
@Transactional:当标于类前时, 标示类中所有方法都进行事物处理 ,
@EnableWebSecurity:,1: 加载了WebSecurityConfiguration配置类, 配置安全认证策略。2: 加载了AuthenticationConfiguration, 配置了认证信息。

4.Controller和RestContraller的区别?

@RestController注解相当于@ResponseBody + @Controller合在一起的作用。

  1. 如果只是使用@RestController注解Controller,则Controller中的方法无法返回jsp页面,或者html,配置的视图解析器 InternalResourceViewResolver不起作用,返回的内容就是Return 里的内容。

  2. 如果需要返回到指定页面,则需要用 @Controller配合视图解析器 InternalResourceViewResolver才行。如果需要返回JSON,XML或自定义mediaType内容到页面,则需要在对应的方法上加上@ResponseBody注解。

5.返回JSON的专门的注解?

@ResponseBody

6.MYSQL的隔离级别?

4种:
①:可读未提交:一个事务可以读取另一个事务未提交的数据。
②:可读已提交:一个事务要等另一个事务提交后才能读取数据。
③:可重复读:就是在开始读取数据(事务开启)时,不再允许修改操作。
④:串行化:事务顺序执行,事务隔离级别最高,性能很低,一般很少用。

7.MyBatis启动赋值的时候用到的 #{} 和 ${}的区别?

使用#{}传进来的参数,mybatis默认会将其当成字符串。可能在赋值给如id=#{id}和id=KaTeX parse error: Expected 'EOF', got '#' at position 32: …表名或字段参数时可以明显看出,#̲{}会转换成带双引号的。而{}不会。
#{}可以有效防止sql注入,${}则可能导致sql注入成功。

8.RocketMQ介绍一下。是点对点还是什么?还有一种方式是什么?

P2P(点对点):每个消息只有一个消费者,一旦被消费,即从消息队列中删除,如果希望每个消息都被成功处理,则应该使用P2P模型。
Pub/Sub(发布订阅):如果希望发送的消息可以不做任何处理,或者被一个或多个消费者消费,则应该采用Pub/Sub模型。

9.数据库的索引失效的写法?

a. 使用 <> 、not in 、not exist、!=
b. like “%_” 百分号在前(可采用在建立索引时用reverse(columnName)这种方法处理)。
c. 单独引用复合索引里非第一位置的索引列.应总是使用索引的第一个列,如果索引是建立在多个列上, 只有在它的第一个列被where子句引用时,优化器才会选择使用该索引。
d. 字符型字段为数字时在where条件里不添加引号.
e. 当变量采用的是times变量,而表的字段采用的是date变量时.或相反情况。

TCP和UDP的区别:

1) TCP提供面向连接的传输,通信前要先建立连接(三次握手机制); UDP提供无连接的传输,通信前不需要建立连接。
2) TCP提供可靠的传输(有序,无差错,不丢失,不重复); UDP提供不可靠的传输。
3) TCP面向字节流的传输,因此它能将信息分割成组,并在接收端将其重组; UDP是面向数据报的传输,没有分组开销。
4) TCP提供拥塞控制和流量控制机制; UDP不提供拥塞控制和流量控制机制。

进程与线程

线程是系统执行(调度)的最小单元,进程是系统资源分配的最小单元。

线程同步机制:
线程同步主要用于协调对临界资源的访问,临界资源可以是硬件设备(比如打印机)、磁盘(文件)、内存(变量、数组、队列等)。
线程同步有4种机制:
临界区:临界区是一段独占对某些共享资源访问的代码,在任意时刻只允许一个线程对共享资源进行访问。如果有多个线程试图同时访问临界区,那么在有一个线程进入后其他所有试图访问此临界区的线程将被挂起,并一直持续到进入临界区的线程离开。临界区在被释放后,其他线程可以继续抢占,并以此达到用原子方式操作共享资源的目的。PS:私人浴室(没有管理员)只有一间淋浴房,我想洗澡,我时不时来看下淋浴房空了没,空了我就去洗。

互斥量:功能上跟临界区类似,不过可用于不同进程间的线程同步。
PS:公共浴室(有管理员)只有一间淋浴房,我想洗澡,问了下管理员,有空的淋浴房么,如果有,管理员就让我洗,否则管理员就让我先去休息室睡一觉,等有空的淋浴房了叫醒我去洗澡。

事件:触发重置事件对象,那么等待的所有线程中将只有一个线程能唤醒,并同时自动的将此事件对象设置为无信号的;它能够确保一个线程独占对一个资源的访问。和互斥量的区别在于多了一个前置条件判定。

信号量:信号量用于限制对临界资源的访问数量,保证了消费数量不会大于生产数量。

进程常用的通信机制:

1.管道pipe:管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。

2.命名管道FIFO:有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。

3.消息队列MessageQueue:消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。

4.共享存储SharedMemory:共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号两,配合使用,来实现进程间的同步和通信。

5.信号量Semaphore:信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。

6.套接字Socket:套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同及其间的进程通信。

7.信号 ( sinal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。

I/O多路复用

一个线程,通过记录I/O流的状态来同时管理多个I/O,可以提高服务器的吞吐能力。

Mysql 存储过程和函数区别:

存储过程是procedure用户定义的一系列sql语句的集合,涉及特定表或其它对象的任务,用户可以调用存储过程,而函数通常是数据库已定义的方法,它接收参数并返回某种类型的值并且不涉及特定用户表。
1)一般来说,存储过程实现的功能要复杂一点,而函数的实现的功能针对性比较强。存储过程,功能强大,可以执行包括修改表等一系列数据库操作;用户定义函数不能用于执行一组修改全局数据库状态的操作。

2)对于存储过程来说可以返回参数,如记录集,而函数只能返回值或者表对象。函数只能返回一个变量;而存储过程可以返回多个。存储过程的参数可以有IN,OUT,INOUT三种类型,而函数只能有IN类~~存储过程声明时不需要返回类型,而函数声明时需要描述返回类型,且函数体中必须包含一个有效的RETURN语句。

3)存储过程,可以使用非确定函数,不允许在用户定义函数主体中内置非确定函数。

4)存储过程一般是作为一个独立的部分来执行( EXECUTE 语句执行),而函数可以作为查询语句的一个部分来调用(SELECT调用),由于函数可以返回一个表对象,因此它可以在查询语句中位于FROM关键字的后面。 SQL语句中不可用存储过程,而可以使用函数。

存储过程:可以进行增删查改dml操作,甚至可以进行建表等ddl操作;不能return返回值,可以用out参数返回值。用exec 过程名 的方法调用。
函数,可以return返回值;一般来说,只能进行select操作,不能进行增删改,也不能进行ddl操作。可以通过赋值的方式调用,也可以在sql语句中使用。
跨域问题:
服务端进行配置
添加@CrossOrigin注解的支持,表明该请求地址下都支持跨域。

JDK和JRE的区别:

JDK是整个JAVA的核心,包括了Java运行环境JRE,一堆Java工具和Java基 础的类库。通过JDK开发人员将源码文件(java文件)编译成字节码文件(class文 件)。JRE是Java运行环境,不含开发环境,即没有编译器和调试器。将class文件 加载到内存准备运行。

final关键字,抽象类可以使用final修饰吗?

1.用来修饰数据,包括成员变量和局部变量,该变量只能被赋值一次且它的 值无法被改变。对于成员变量来讲,必须在声明时或者构造方法中对它赋值;

2.修饰方法,表示该方法无法被重写;

3.修饰类,表示该类无法被继承。抽象类是被用于继承的,final修饰代表不可修改、不可继承的。所以不能用 final修饰抽象类。

JAVA怎么保证线程安全?锁在项目中具体怎么使用?线程安全在三个方面体现

1.原子性:提供互斥访问,同一时刻只能有一个线程对数据进行操作, (atomic,synchronized);

2.可见性:一个线程对主内存的修改可以及时地被其他线程看到, (synchronized,volatile);

3.有序性:一个线程观察其他线程中的指令执行顺序,由于指令重排序,该观察 结果一般杂乱无序,(happens-before原则)。

Java如何保证原子性 :锁和同步,常用的保证Java操作原子性的工具是锁和同步方法(或者同步代码块)。使用锁,可以保证同一时间只有一个线程能拿到锁,也就保证了同一时间只有一个 线程能执行申请锁和释放锁之间的代码。与锁类似的是同步方法或者同步代码块。使用非静态同步方法时,锁住的是 当前实例;使用静态同步方法时,锁住的是该类的Class对象;使用静态代码块 时,锁住的是synchronized关键字后面括号内的对象。无论使用锁还是synchronized,本质都是一样,通过锁来实现资源的排它 性,从而实际目标代码段同一时间只会被一个线程执行,进而保证了目标代码段 的原子性。这是一种以牺牲性能为代价的方法。
Java如何保证可见性 Java提供了volatile关键字来保证可见性。由于JMM是基于共享内存实现线 程通信的,所以会存在缓存一致性的问题。当使用volatile修饰某个变量时,它 会保证对该变量的修改会立即被更新到内存中,并且将其它缓存中对该变量的缓 存设置成无效,因此其它线程需要读取该值时必须从主内存中读取,从而得到最 新的值。

Java如何保证顺序性 编译器和处理器对指令进行重新排序时,会保证重新排序后的执行结果和代 码顺序执行的结果一致,所以重新排序过程并不会影响单线程程序的执行,却可 能影响多线程程序并发执行的正确性。Java中可通过volatile在一定程序上保证顺序性,另外还可以通过 synchronized和锁来保证顺序性。synchronized和锁保证顺序性的原理和保证原子性一样,都是通过保证同 一时间只会有一个线程执行目标代码段来实现的。除了从应用层面保证目标代码段执行的顺序性外,JVM还通过被称为 happens-before原则隐式地保证顺序性。两个操作的执行顺序只要可以通过 happens-before推导出来,则JVM会保证其顺序性,反之JVM对其顺序性不作 任何保证,可对其进行任意必要的重新排序以获取高效率。

有没有其他方法保证线程安全?

有。尽可能避免引起非线程安全的条件——共享变量。如果能从设计上避免共享变量的使用,即可避免非线程安全的发生,也就无须通过锁或者 synchronized以及volatile解决原子性、可见性和顺序性的问题。还有不可变对象 可以使用final修饰的对象保证线程安全,由于final修饰的引用型变量(除String外)不 可变是指引用不可变,但其指向的对象是可变的,所以此类必须安全发布,即不能对外提供 可以修改final对象的接口。锁在项目中使用场景?

ThreadLocal具体怎么使用?使用在什么场景?

当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供 独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其 它线程所对应的副本。从线程的角度看,目标变量就象是线程的本地变量,这也是类名 中“Local”所要表达的意思。ThreadLocal是如何做到为每一个线程维护变量的副本的呢?其实实现的思 路很简单:在ThreadLocal类中有一个Map,用于存储每一个线程的变量副本, Map中元素的键为线程对象,而值对应线程的变量副本。ThreadLocal则从另一个角度来解决多线程的并发访问。ThreadLocal会为每 一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因 为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象,在编写多线程代码时,可以把不安全 的变量封装进ThreadLocal。个人理解:每一个ThreadLocal内部有一个静态内部 类:ThreadLocalMap,Map里面存储线程本地线程对象(key)和线程的变量副 本(value)但是,Thread内部的Map是由ThreadLocal维护的,由 ThreadLocal负责向map获取和设置线程的变量值。所以对于不同的线程,每次 获取副本值时,别的线程并不能获取到当前线程的副本值,形成了副本的隔离, 互不干扰。

场景:每个线程分配一个 JDBC 连接 Connection。这样就可以保证每个线程的都在各自的 Connection 上进行数据库的操作,不会出现 A 线程关了 B线程正在使用的 Connection; 还有 Session 管理 等问题。

了解反射吗?怎么用?用在哪里?

Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属 性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它 的属性。总结说:反射就是把java类中的各种成分映射成一个个的Java对象,并 且可以进行操作。
Java反射的原理:java类的执行需要经历以下过程:
编译:.java文件编译后生成.class字节码文件
加载:类加载器负责根据一个类的全限定名来读取此类的二进制字节流到JVM 内部,并存储在运行时内存区的方法区,然后将其转换为一个与目标类型对应的java.lang.Class对象实例
链接
验证:格式(class文件规范) 语义(final类是否有子类) 操作
准备:静态变量赋初值和内存空间,final修饰的内存空间直接赋 原值,此处不是用户指定的初值。
解析:符号引用转化为直接引用,分配地址
初始化:根据程序员通过程序指定的主观计划去初始化类变量和其他资源, 或者可以从另一个角度来表达:初始化阶段是执行类构造器()方法的过 程。执行静态方法代码块为静态变量赋值。
Java的反射就是利用上面第二步加载到jvm中的.class文件来进行操作的。
.class文件中包含java类的所有信息,当你不知道某个类具体信息时,可以使用反射获取class,然后进行各种操作。

怎么用:1、通过class.forName(),加载某个类。
2.在运行时构造任意一个类的对象。
①Class cls = Class.forName(“com.jdk”);
②jdk jdkobj = cls.newInstance();
3.在运行时判断任意一个类所具有的成员变量和方法。
①Class cls = Class.forName(“com.jdk”);
②Methods methods[]= cls.getDecliedMethod();
③Fields fields[] = cls.getDeclieredFields();

使用场景:Class.forName();数据库注册驱动的时候。编译器智能提示该类有哪些方法可供调用。AOP动态代理。经典的就是在xml文件或者properties里面写好了配置,然后在Java类里面解析xml或properties里面的内容,得到一个字符串,然后用反射机制,根据这个字符串获得某个类的Class实例,这样就可以动态配置一些东西,不用每一次都要在代码里面去new或者做其他的事情,以后要改的话直接改配置文件,代码维护起来就很方便了,同时有时候要适应某些需求,Java类里面不一定能直接调用另外的方法,这时候也可以通过反射机制来实现。注解(Annontation)是Java5引入的一种代码辅助工具,它的核心作用是对类、方法、变 量、参数和包进行标注,通过反射来访问这些标注信息,以此在运行时改变所注解对象的行为。

设计模式中简单工厂和抽象工厂的区别?

简单工厂模式:虽然某种程度不符合开闭原则,但是实际实用很多。工厂方法模式:不修改已有类的情况下,通过增加新的工厂类实现扩展。但是容易导致工厂 类泛滥。抽象工厂模式:不可以增加产品,可以增加产品族。增加新产品需要修改很多地方。

异常类型,常见的异常?

HTTP状态码?3XX和4XX区别,404是啥?

3XX重定向:客户端需要做些额外工作才能得到所需要的资源。它们通常用于 GET请求。他们通常告诉客户端需要向另一个URI发送GET请求,才能得到所需 的表示。那个URI就包含在Location响应报头里。
301:永久重定向,比如更换了新的IP,服务端就就告诉客户端以后你访问我的新IP
302:暂时重定向
4XX客户端错误:这些响应代码表明客户端出现错误。不是认证信息有问题,就 是表示格式或HTTP库本身有问题。客户端需要自行改正。
400: 包含语法错误,无法被服务器解析
403: 服务器已经接收请求,但是拒绝执行
404: 请求失败,请求所希望得到的资源未在服务器上发现

5XX服务端错误:这些响应代码表明服务器端出现错误。一般来说,这些代码意 味着服务器处于不能执行客户端请求的状态,此时客户端应稍后重试。
500: 服务器内部错误,无法处理请求

数据库为什么建立索引?如何编程实现数据库抢锁?为什么要创建索引呢?

这是因为,创建索引可以大大提高系统的性能,优点:
第一,通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。
第二,可以大大加快数据的检索速度,这也是创建索引的最主要的原因。
第三,可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别 有意义。
第四,在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组 和排序的时间。
第五,通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。

增加索引有如此多的优点,为什么不对表中的每一个列创建一个索引呢?

这种想法固然有其合理性,然而也有其片面性。虽然,索引有许 多优点,但是,为表中的每一个列都增加索引,是非常不明智的。这是因为,增加索引也有许多不利的一个方面, 缺点:
第一,创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。
第二,索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一 定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。
第三,当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这 样就降低了数据的维护速度。
哪些适合建立索引哪些不适合?
适合的:经常需要搜索的列上,经常需要范围查询的,主键等。
不适合的:经常不用来查询的,大字段的比如text段等。
如何编程实现数据库抢锁?
行锁的释放是需要事务提交之后自动释放。
共享锁:SELECT … LOCK IN SHARE MODE; 解释:MySQL会对查询结果集中每行都添加共享锁。锁申请前提:当前没有线程对该结果集中的任何行使用排他锁,否则申请会阻塞。

排他锁:SELECT … FOR UPDATE; MySQL会对查询结果集中每行都添加排他锁,在事物操作中,任何对记录的更新与删除操 作会自动加上排他锁。
锁申请前提:当前没有线程对该结果集中的任何行使用排他锁或共享锁,否则申请会阻塞。表锁:lock tables … read/write 释放表锁:对应线程执行 unlock tables 即可。

Redis数据结构基础?

项目中具体怎么用的?如果把数据都存储在Redis中会不会丢失数据?Redis分布式锁了解吗?

单机Redis会丢失,集群的话不会。
分布式锁一般有三种实现方式:
1.数据库乐观锁;
2.基于Redis的分布式锁;
edis.set(String key, String value, String nxxx, String expx, int time),这个set()方法一共有五个形参:

第一个为key,我们使用key来当锁,因为key是唯一的。

第二个为value,我们传的是requestId,很多童鞋可能不明白,有key作为锁不就够了吗,为什么还要用到value?原因就是我们在上面讲到可靠性时,分布式锁要满足第四个条件解铃还须系铃人,通过给value赋值为requestId,我们就知道这把锁是哪个请求加的了,在解锁的时候就可以有依据。requestId可以使用UUID.randomUUID().toString()方法生成。

第三个为nxxx,这个参数我们填的是NX,意思是SET IF NOT EXIST,即当key不存在时,我们进行set操作;若key已经存在,则不做任何操作;

第四个为expx,这个参数我们传的是PX,意思是我们要给这个key加一个过期的设置,具体时间由第五个参数决定。

第五个为time,与第四个参数相呼应,代表key的过期时间。

总的来说,执行上面的set()方法就只会导致两种结果:1. 当前没有锁(key不存在),那么就进行加锁操作,并对锁设置个有效期,同时value表示加锁的客户端。2. 已有锁存在,不做任何操作。
3.基于ZooKeeper的分布式锁。

分库分表如何实现?具体分几个库几个表?

常用的分库分表的策略
HASH取模
假设有用户表user,将其分成3个表user0,user1,user2.路由规则是对3取模,当uid=1时,对应到的是user1,uid=2时,对应的是user2.

范围分片

从1-10000一个表,10001-20000一个表。

地理位置分片

华南区一个表,华北一个表。

时间分片(常见方案)

按月分片,按季度分片等等,可以做到冷热数据。

分库分表后引入的问题

分布式事务问题

1.跨库join的问题

2.横向扩容的问题

3.结果集合并、排序的问题

使用分库分表中间件

1.Mycat

2.Sharding-JDBC

3。淘宝的TDDL,支付宝的OneProxy,360的Atlas等。

大数据问题:

硬盘里一个50G大小的文件和另一个100G文件,里面存储着不同的名 字,如何在一个内存很小的电脑上实现两个文件的交集运算。
方法一:分桶+组内Hash索引或者组内使用位图 O(n) 使用哈希切分的方法,将一个大文件里的数据使用一个哈希函数进行切分为 许多小的文件,这样相同的数据一定会进入同一个文件当中去,并进行文件编 号。对另外一个文件也是用相同的哈希函数进行切分为相同数目的小文件,这样 我们只需要将相同编号里的文件进行比较。这样其时间复杂度就会降低为 O(n)。相同的文件查找时可以先对一个文件建立hash索引(桶+链表),然后对另 一个文件依次按照索引进行查找。若hash值相同在进行进一步比较即可。
方法二:位图 O(n) 这有个前提是文件中必须存储的是数字。那么根据位图,我们可以将第一个 文件中所有数据映射到位图中去。然后再不断导入第二个文件,如果发现某个数 字已经存储在位图中,就说明这是两个文件的交集。
方法三:近似解-布隆过滤器 O(n) 将A文件每个数据经过多个Hash函数映射到一个位图上,然后第二个文件同 样的做法,如果全部命中,说明相同。否则说明不存在。但是这个有一定的错误 率。
方法四:多路归并排序 Onlog(n)+O(n) 先将文件划分为很多等量的小文件。然后对每个小文件导入内存进行内部排 序。这样就有了很多有序的小文件。然后对很多有序的小文件进行多路归并排序,然后不断写入大文件即可。(Onlog(n))最终就得到了一个有序的大文件。最后对两个有序的大文件进行 查找相同的值即可(O(n))。

大数据问题:

BBS上很多帖子,发帖最多的人被删除掉了,剩下3个人的帖子数目均超 过1/4,如何找出这三个人?

1.首先统计出数据出现的次数。这个可以采用hash。然后用最小堆便可以求出 出现次数最高的N个数。
2.如果这个文件非常大。可以采取分治法。假设此文件大小为n。而内存中能处 理的为k。则分m次读取。m=n/k+1。每次读取k大小。然后采用1的方法可以 得出k大小中的N个频率最高的。m次后得到m个堆。将此m个堆合并。便可得 到频率最高的N个。
3.堆的维护的代价为lgN;我想还是比较快的。思路大致如下:每一个帖子和用户是一一对应的关系。先根据HashMap<用户ID,帖子数 目>遍历每一个帖子,得到每个用户的发帖子的数目。假设此时用户数目为m, 即Map的大小。然后进行堆排序,由于我们只需要排名前三的人,所有只需维 护一个大小为3的小顶堆即可。时间复杂度:遍历所有帖子时间复杂度为O(n), 堆排序时间复杂度为O(mlog3)。由于三个人的帖子数目均超过了总帖子的 1/4。可以认为m的数目远远小于n。最终复杂度约等于O(n)。

1000亿的大数据,找出其中最大的十万个数

Hash分成小文件,每个小文件进行Hash统计,取出前十万大的数字。然后维护一个十万大 小的堆,多个文件得出最大的十万个数。

1000亿的大数据,全排序

Hash分成小文件,每个小文件内部进行快排,得到多个有序小文件,然后多路归并排序。

软中断和硬中断区别,种类,缺页中断是什么中断?

硬中断:

  1. 硬中断是由硬件产生的,比如,像磁盘,网卡,键盘,时钟等。每个设备或设备集都有 它自己的IRQ(中断请求)。基于IRQ,CPU可以将相应的请求分发到对应的硬件驱动上 (注:硬件驱动通常是内核中的一个子程序,而不是一个独立的进程)。

  2. 处理中断的驱动是需要运行在CPU上的,因此,当中断产生的时候,CPU会中断当前正 在运行的任务,来处理中断。在有多核心的系统上,一个中断通常只能中断一颗CPU(也有一种特殊的情况,就是在大型主机上是有硬件通道 的,它可以在没有主CPU的支持下, 可以同时处理多个中断。)。

  3. 硬中断可以直接中断CPU。它会引起内核中相关的代码被触发。对于那些需要花费一些 时间去处理的进程,中断代码本身也可以被其他的硬中断中断。

  4. 对于时钟中断,内核调度代码会将当前正在运行的进程挂起,从而让其他的进程来运 行。它的存在是为了让调度代码(或称为调度器)可以调度多任务。软中断:

软中断的处理非常像硬中断。然而,它们仅仅是由当前正在运行的进程所产生的。

  1. 通常,软中断是一些对I/O的请求。这些请求会调用内核中可以调度I/O发生的程序。对 于某些设备,I/O请求需要被立即处理,而磁盘I/O请求通常可以排队并且可以稍后处理。根据I/O模型的不同,进程或许会被挂起直到I/O完成,此时内核调度器就会选择另一个进 程去运行。I/O可以在进程之间产生并且调度过程通常和磁盘I/O的方式是相同。

  2. 软中断仅与内核相联系。而内核主要负责对需要运行的任何其他的进程进行调度。一些 内核允许设备驱动的一些部分存在于用户空间,并且当需要的时候内核也会调度这个进程去 运行。

4.软中断并不会直接中断CPU。也只有当前正在运行的代码(或进程)才会产生软中断。这种中断是一种需要内核为正在运行的进程去做一些事情(通常为I/O)的请求。有一个特 殊的软中断是Yield调用,它的作用是请求内核调度器去查看是否有一些其他的进程可以运行。

SpringMVC的UML时序图:


一个请求匹配前端控制器 DispatcherServlet 的请求映射路径(在 web.xml中指定), WEB 容器将该请求转交给 DispatcherServlet 处理
DispatcherServlet 接收到请求后, 将根据 请求信息 交给 处理器映射器 (HandlerMapping)
HandlerMapping 根据用户的url请求 查找匹配该url的 Handler,并返回一个执行链。
DispatcherServlet 再请求 处理器适配器(HandlerAdapter) 调用相应的 Handler 进行处理并返回 ModelAndView 给 DispatcherServlet
DispatcherServlet 将 ModelAndView 请求 ViewReslover(视图解析器)解析,返回具体 View
DispatcherServlet 对 View 进行渲染视图(即将模型数据填充至视图中)
DispatcherServlet 将页面响应给用户

第一范式

https://blog.csdn/xidianliuy/article/details/51566576
所谓第一范式,就是数据表的列不可再分。

第二范式

第二范式是指,首先满足第一范式,并且表中非主键列不存在对主键的部分依赖。

第三范式

第三范式定义是,满足第二范式,并且表中的列不存在对非主键列的传递依赖。

Mysql 中 MyISAM 和 InnoDB 的区别有哪些?

区别:

  1. InnoDB支持事务,MyISAM不支持,对于InnoDB每一条SQL语言都默认封装成事务,自动提交,这样会影响速度,所以最好把多条SQL语言放在begin和commit之间,组成一个事务;
  2. InnoDB支持外键,而MyISAM不支持。对一个包含外键的InnoDB表转为MYISAM会失败;
  3. InnoDB是聚集索引,数据文件是和索引绑在一起的,必须要有主键,通过主键索引效率很高。但是辅助索引需要两次查询,先查询到主键,然后再通过主键查询到数据。因此,主键不应该过大,因为主键太大,其他索引也都会很大。而MyISAM是非聚集索引,数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的。
  4. InnoDB不保存表的具体行数,执行select count(*) from table时需要全表扫描。而MyISAM用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快;
  5. Innodb不支持全文索引,而MyISAM支持全文索引,查询效率上MyISAM要高;
    如何选择:
  6. 是否要支持事务,如果要请选择innodb,如果不需要可以考虑MyISAM;
  7. 如果表中绝大多数都只是读查询,可以考虑MyISAM,如果既有读写也挺频繁,请使用InnoDB。
  8. 系统奔溃后,MyISAM恢复起来更困难,能否接受;
  9. MySQL5.5版本开始Innodb已经成为Mysql的默认引擎(之前是MyISAM),说明其优势是有目共睹的,如果你不知道用什么,那就用InnoDB,至少不会差。

数据库索引的实现原理

数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库表中数据。索引的实现通常使用B树及其变种B+树。

算法://快速排序

 private static void quickSort(int[] arr, int left, int right) {

     int l = left;
     int r = right;
     int pivot = arr[(left + right) / 2];
     int temp = 0;

     while (l < r) {
         while (arr[l] < pivot) {
             l += 1;
         }
         while (arr[r] > pivot) {
             r -= 1;
         }
         if (l >= r) {
             break;
         }

         temp = arr[l];
         arr[l] = arr[r];
         arr[r] = temp;

         if (arr[l] == pivot) {
             r -= 1;
         }
         if (arr[r] == pivot) {
             l += 1;
         }
     }
     if (l == r) {
         l += 1;
         r -= 1;
     }
     if (left < r) {
         quickSort(arr, left, r);
     }
     if (right > l) {
         quickSort(arr, l, right);
     }

 }

本文标签: 菜鸟小米面试题点评更新中