面试 — 每日六问 「3」

一、MySQL 三种常见的存储引擎是什么?

MySQL — 存储引擎

MySQL 常用的引擎有 InnoDB、MyISAM、Memory,默认是 InnoDB。

InnoDB: 支持事务处理,支持外键,支持崩溃修复能力和并发控制。如果需要对事务的完整性要求比较高(比如银行),要求实现并发控制(比如售票),那选择InnoDB有很大的优势。如果需要频繁的更新、删除操作的数据库,也可以选择InnoDB,因为支持事务的提交(commit)和回滚(rollback)。

缺点:读写效率相对 MyISAM 较差,占用的磁盘空间比较大。

MyISAM: 插入数据快,空间和内存使用比较低。如果表主要是用于插入新记录和读出记录,那么选择 MyISAM 能实现处理高效率。如果应用的完整性、并发性要求比较低,也可以使用。

缺点:不支持事务的完整性和并发性。

MEMORY: 所有的数据都在内存中,数据的处理速度快,但是安全性不高。如果需要很快的读写速度,对数据的安全性要求较低,可以选择MEMOEY。它对表的大小有要求,不能建立太大的表。所以,这类数据库只使用在相对较小的数据库表。

二、Redis 的 Hash 算法是什么?

一致性 Hash 算法。

MururHash。

三、NoSQL 为什么比 SQL 快?

Nosql 是非关系型数据库,因为不需要满足关系数据库数据一致性等复杂特性所以速度快;SQL 是关系型数据库,功能强大,但是效率上有瓶颈。

四、什么是索引?为啥 NoSQL 没索引?

MySQL - 索引

索引(Index)是帮助 MySQL 高效获取数据的数据结构。

底层基本使用 B+ - Tree 数据结构实现。

在 MySQL 中,索引分为两大类:聚簇索引和非聚簇索引。

InnoDB 使用的是聚簇索引,聚簇索引是按照数据存放的物理位置为顺序的,将行数据存储到叶子节点上。有主键时,根据主键创建聚簇索引;没有主键时,会用一个唯一且不为空的索引列做为主键,成为此表的聚簇索引。

MyISAM 使用的是非聚簇索引,非聚簇索引叶子节点存储的不是数据本身,而是存放数据的地址。

在这两大类的索引类型下,还可以将索引分成四个小类:

  1. 普通索引:最基本的索引,没有任何限制。

  2. 唯一索引:索引列的值必须唯一,但允许有空值。

  3. 全文索引:仅可以适用于 MyISAM 引擎的数据表,用于查找文本中的关键词,而不是直接比较是否相等。

  4. 组合索引:将几个列作为一条所以进行检索,使用最左匹配原则。

NoSQL 有索引!

五、B+ 树和 B 树的区别?

MySQL - 索引

B 树的非叶子节点存储实际记录的指针,而 B+ 树的叶子节点存储实际记录的指针。

B+ 树的叶子节点通过指针连起来了, 适合扫描区间和顺序查找。

六、有没有了解 Spring 的原理?AOP 和 IOC 的原理?

(1). IoC(Inversion of Control)是指容器控制程序对象之间的关系,而不是传统实现中,由程序代码直接操控。控制权由应用代码中转到了外部容器,控制权的转移是所谓反转。对于Spring而言,就是由Spring来控制对象的生命周期和对象之间的关系;IoC还有另外一个名字——“依赖注入(Dependency Injection)”。从名字上理解,所谓依赖注入,即组件之间的依赖关系由容器在运行期决定,即由容器动态地将某种依赖关系注入到组件之中。  

(2). 在Spring的工作方式中,所有的类都会在spring容器中登记,告诉spring这是个什么东西,你需要什么东西,然后spring会在系统运行到适当的时候,把你要的东西主动给你,同时也把你交给其他需要你的东西。所有的类的创建、销毁都由 spring来控制,也就是说控制对象生存周期的不再是引用它的对象,而是spring。对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被spring控制,所以这叫控制反转。

(3). 在系统运行中,动态的向某个对象提供它所需要的其他对象。  

(4). 依赖注入的思想是通过反射机制实现的,在实例化一个类时,它通过反射调用类中set方法将事先保存在HashMap中的类属性注入到类中。 总而言之,在传统的对象创建方式中,通常由调用者来创建被调用者的实例,而在Spring中创建被调用者的工作由Spring来完成,然后注入调用者,即所谓的依赖注入or控制反转。 注入方式有两种:依赖注入和设置注入; IoC的优点:降低了组件之间的耦合,降低了业务对象之间替换的复杂性,使之能够灵活的管理对象。

AOP(Aspect Oriented Programming)

(1). AOP面向方面编程基于IoC,是对OOP的有益补充;

(2). AOP利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了 多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,即方面。所谓“方面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的 逻辑或责任封装起来,比如日志记录,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。

(3). AOP代表的是一个横向的关 系,将“对象”比作一个空心的圆柱体,其中封装的是对象的属性和行为;则面向方面编程的方法,就是将这个圆柱体以切面形式剖开,选择性的提供业务逻辑。而剖开的切面,也就是所谓的“方面”了。然后它又以巧夺天功的妙手将这些剖开的切面复原,不留痕迹,但完成了效果。

(4). 实现AOP的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。

(5). Spring实现AOP:JDK动态代理和CGLIB代理 JDK动态代理:其代理对象必须是某个接口的实现,它是通过在运行期间创建一个接口的实现类来完成对目标对象的代理;其核心的两个类是InvocationHandler和Proxy。 CGLIB代理:实现原理类似于JDK动态代理,只是它在运行期间生成的代理对象是针对目标类扩展的子类。CGLIB是高效的代码生成包,底层是依靠ASM(开源的java字节码编辑类库)操作字节码实现的,性能比JDK强;需要引入包asm.jar和cglib.jar。     使用AspectJ注入式切面和@AspectJ注解驱动的切面实际上底层也是通过动态代理实现的。

(6). AOP使用场景:                      Authentication 权限检查         Caching 缓存         Context passing 内容传递         Error handling 错误处理         Lazy loading 延迟加载         Debugging  调试       logging, tracing, profiling and monitoring 日志记录,跟踪,优化,校准         Performance optimization 性能优化,效率检查         Persistence  持久化         Resource pooling 资源池         Synchronization 同步         Transactions 事务管理     另外Filter的实现和struts2的***的实现都是AOP思想的体现