互联网大厂必问之MySQL、Redis、Spring三大块,面试必备技术栈

242 阅读15分钟

前言
怎么样是不是感觉面试很难,而且快到了“金三银四”跳槽涨薪高峰季了,不管是实习生还是有想要跳槽的大佬们即将进入找工作的高峰期,在任何Java面试当中MySQL、Redis、Spring方面的问题都是必不可少的一部分。所以这篇文章是我最新整理的面试题答案以及总结,希望对想进BAT的同学有帮助,由于篇幅较长,建议收藏后细看~

MySQL查询字段区不区分大小写?

答案是不区分

如何解决需要区分英文大小写的场景

例如登录用户为admin,此时填写ADMIN也能登录,如果用户名需要区分大小写,你的做法是什么?

解决方案一

MySQL默认的字符检索策略:utf8_general_ci,表示不区分大小写。

可以使用utf8_general_cs,表示区分大小写,也可以使用utf8_bin,表示二进制比较,同样也区分大小写 。

注意:在Mysql5.6.10版本中,不支持utf8_genral_cs

创建表时,直接设置表的collate属性为utf8_general_cs或者utf8_bin;如果已经创建表,则直接修改字段的Collation属性为utf8_general_cs或者utf8_bin。

-- 创建表:
CREATE TABLE testt(
id INT PRIMARY KEY,
name VARCHAR(32) NOT NULL
) ENGINE = INNODB COLLATE =utf8_bin;

-- 修改表结构的Collation属性
ALTER TABLE TABLENAME MODIFY COLUMN COLUMNNAME VARCHAR(50) BINARY CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL;

解决方案二

直接修改sql语句,在要查询的字段前面加上binary关键字

-- 在每一个条件前加上binary关键字
select * from user where binary username = 'admin' and binary password = 'admin';

-- 将参数以binary('')包围
select * from user where username like binary('admin') and password like binary('admin');

MySQL innodb的事务与日志的实现方式

有多少种日志

  • 错误日志:记录出错信息,也记录一些警告信息或者正确的信息。
  • 查询日志:记录所有对数据库请求的信息,不论这些请求是否得到了正确的执行。
  • 慢查询日志:设置一个阈值,将运行时间超过该值的所有SQL语句都记录到慢查询的日志文件中。
  • 二进制日志:记录对数据库执行更改的所有操作。
  • 中继日志:中继日志也是二进制日志,用来给slave 库恢复
  • 事务日志:重做日志redo和回滚日志undo

事物的4种隔离级别

  • 读未提交(RU)
  • 读已提交(RC)
  • 可重复读(RR)
  • 串行

事务是如何通过日志来实现的,说得越深入越好

事务日志是通过redo和innodb的存储引擎日志缓冲(Innodb log buffer)来实现的,当开始一个事务的时候,会记录该事务的lsn(log sequence number)号;

当事务执行时,会往InnoDB存储引擎的日志的日志缓存里面插入事务日志;

当事务提交时,必须将存储引擎的日志缓冲写入磁盘(通过innodb_flush_log_at_trx_commit来控制),也就是写数据前,需要先写日志。这种方式称为“预写日志方式”

MySQL binlog的几种日志录入格式以及区别

Statement:每一条会修改数据的sql都会记录在binlog中。

优点: 不需要记录每一行的变化,减少了binlog日志量,节约了IO,提高性能。

相比row能节约多少性能 与日志量,这个取决于应用的SQL情况,正常同一条记录修改或者插入row格式所产生的日志量还小于Statement产生的日志量,但是考虑到如果带条件的update操作,以及整表删除,alter表等操作,ROW格式会产生大量日志,因此在考虑是否使用ROW格式日志时应该根据应用的实际情况,其所 产生的日志量会增加多少,以及带来的IO性能问题。

缺点: 由于记录的只是执行语句,为了这些语句能在slave上正确运行,因此还必须记录每条语句在执行的时候的一些相关信息,以保证所有语句能在slave得到和在master端执行时候相同的结果。

另外mysql 的复制,像一些特定函数功能,slave可与master上要保持一致会有很多相关问题(如sleep()函数, last_insert_id(),以及user-defined functions(udf)会出现问题).

使用以下函数的语句也无法被复制:

LOAD_FILE()

UUID()

USER()

FOUND_ROWS()

SYSDATE() (除非启动时启用了 --sysdate-is-now 选项)

同时在INSERT …SELECT 会产生比 RBR 更多的行级锁

Row:不记录sql语句上下文相关信息,仅保存哪条记录被修改。

优点: binlog中可以不记录执行的sql语句的上下文相关的信息,仅需要记录那一条记录被修改成什么了。

所以rowlevel的日志内容会非常清楚的记录下 每一行数据修改的细节。而且不会出现某些特定情况下的存储过程,或function,以及trigger的调用和触发无法被正确复制的问题

缺点: 所有的执行的语句当记录到日志中的时候,都将以每行记录的修改来记录,这样可能会产生大量的日志内容。

比如一条update语句,修改多条记录,则binlog中每一条修改都会有记录,这样造成binlog日志量会很大,特别是当执行alter table之类的语句的时候,由于表结构修改,每条记录都发生改变,那么该表每一条记录都会记录到日志中。

Mixedlevel: 以上两种level的混合使用。

一般的语句修改使用statment格式保存binlog,如一些函数,statement无法完成主从复制的操作,则采用row格式保存binlog,MySQL会根据执行的每一条具体的sql语句来区分对待记录的日志形式,也就是在Statement和Row之间选择一种。

新版本的MySQL中对row level模式也被做了优化,并不是所有的修改都会以row level来记录,像遇到表结构变更的时候就会以statement模式来记录。至于update或者delete等修改数据的语句,还是会记录所有行的变更。

MySQL 面试题

1、MySQL 中有哪几种锁?

2、MySQL 中有哪些不同的表格?

3、简述在 MySQL 数据库中 MyISAM 和 InnoDB 的区别?

4、MySQL 中 InnoDB 支持的四种事务隔离级别名称,以及逐级之间的区别?

5、CHAR 和 VARCHAR 的区别?

6、主键和候选键有什么区别?

7、myisamchk 是用来做什么的?

8、如果一个表有一列定义为 TIMESTAMP,将发生什么?

9、你怎么看到为表格定义的所有索引?

10、LIKE 声明中的%和_是什么意思?

11、列对比运算符是什么?

12、BLOB 和 TEXT 有什么区别?

13、MySQL_fetch_array 和 MySQL_fetch_object 的区别是什么?

答;以下是 MySQL_fetch_array 和 MySQL_fetch_object 的区别:

(1)MySQL_fetch_array() – 将结果行作为关联数组或来自数据库的常规数组返回。

(2)MySQL_fetch_object – 从数据库返回结果行作为对象。

14、MyISAM 表格将在哪里存储,并且还提供其存储格式?

15、MySQL 如何优化 DISTINCT?

16、如何显示前 50 行?

17、可以使用多少列创建索引?

18、NOW()和 CURRENT_DATE()有什么区别?

19、什么是非标准字符串类型?

20、什么是通用 SQL 函数?

21、MySQL 支持事务吗?

22、MySQL 里记录货币用什么字段类型好

23、MySQL 有关权限的表都有哪几个?

24、列的字符串类型可以是什么?

25、MySQL 数据库作发布系统的存储,一天五万条以上的增量,预计运维三年,怎么优化?

26、锁的优化策略

27、索引的底层实现原理和优化

28、什么情况下设置了索引但无法使用

(1)以“%”开头的 LIKE 语句,模糊匹配。

(2)OR 语句前后没有同时使用索引。

(3)数据类型出现隐式转化(如 varchar 不加单引号的话可能会自动转换为 int 型)。

Redis字符串的实现

Redis虽然是用C语言写的,但却没有直接用C语言的字符串,而是自己实现了一套字符串。目的就是为了提升速度,提升性能,可以看出Redis为了高性能也是煞费苦心。

Redis构建了一个叫做简单动态字符串(Simple Dynamic String),简称SDS

1.SDS 代码结构

struct sdshdr{
    //  记录已使用长度
    int len;
    // 记录空闲未使用的长度
    int free;
    // 字符数组
    char[] buf;
};

SDS ?什么鬼?可能对此陌生的朋友对这个名称有疑惑。只是个名词而已不必在意,我们要重点欣赏借鉴Redis的设计思路。下面画个图来说明,一目了然。

Redis的字符串也会遵守C语言的字符串的实现规则,即最后一个字符为空字符。然而这个空字符不会被计算在len里头。

2.SDS 动态扩展特点

SDS的最厉害最奇妙之处在于它的Dynamic。动态变化长度。举个例子

如上图所示刚开始s1 只有5个空闲位子,后面需要追加' world' 6个字符,很明显是不够的。那咋办?Redis会做以下三个操作:

  1. 计算出大小是否足够
  2. 开辟空间至满足所需大小
  3. 开辟与已使用大小len相同长度的空闲free空间(如果len < 1M)开辟1M长度的空闲free空间(如果len >= 1M)

看到这儿为止有没有朋友觉得这个实现跟Java的列表List实现有点类似呢?看完后面的会觉得更像了。

Redis字符串的性能优势

  • 快速获取字符串长度
  • 避免缓冲区溢出
  • 降低空间分配次数提升内存使用效率

1.快速获取字符串长度

再看下上面的SDS结构体:

struct sdshdr{
    //  记录已使用长度
    int len;
    // 记录空闲未使用的长度
    int free;
    // 字符数组
    char[] buf;
};

由于在SDS里存了已使用字符长度len,所以当想获取字符串长度时直接返回len即可,时间复杂度为O(1)。如果使用C语言的字符串的话它的字符串长度获取函数时间复杂度为O(n),n为字符个数,因为他是从头到尾(到空字符'\0')遍历相加。

2.避免缓冲区溢出

对一个C语言字符串进行strcat追加字符串的时候需要提前开辟需要的空间,如果不开辟空间的话可能会造成缓冲区溢出,而影响程序其他代码。如下图,有一个字符串s1="hello" 和 字符串s2="baby",现在要执行strcat(s1,"world"),并且执行前未给s1开辟空间,所以造成了缓冲区溢出。

而对于Redis而言由于每次追加字符串时都会检查空间是否够用,所以不会存在缓冲区溢出问题。每次追加操作前都会做如下操作:

  1. 计算出大小是否足够
  2. 开辟空间至满足所需大小

3.降低空间分配次数提升内存使用效率

字符串的追加操作会涉及到内存分配问题,然而内存分配问题会牵扯内存划分算法以及系统调用所以如果频繁发生的话影响性能,所以对于性能至上的Redis来说这是万万不能忍受的。所以采取了以下两种优化措施

  • 空间与分配
  • 惰性空间回收

1. 空间预分配

对于追加操作来说,Redis不仅会开辟空间至够用而且还会预分配未使用的空间(free)来用于下一次操作。至于未使用的空间(free)的大小则由修改后的字符串长度决定。

当修改后的字符串长度len < 1M,则会分配与len相同长度的未使用的空间(free)

当修改后的字符串长度len >= 1M,则会分配1M长度的未使用的空间(free)

有了这个预分配策略之后会减少内存分配次数,因为分配之前会检查已有的free空间是否够,如果够则不开辟了~

2. 惰性空间回收

与上面情况相反,惰性空间回收适用于字符串缩减操作。比如有个字符串s1="hello world",对s1进行sdstrim(s1," world")操作,执行完该操作之后Redis不会立即回收减少的部分,而是会分配给下一个需要内存的程序。当然,Redis也提供了回收内存的api,可以自己手动调用来回收缩减部分的内存。

Redis 面试题

1、什么是 Redis?

2、Redis 的数据类型?

3、使用 Redis 有哪些好处?

4、Redis 相比 Memcached 有哪些优势?

5、Memcache 与 Redis 的区别都有哪些?

6、Redis 是单进程单线程的?

7、一个字符串类型的值能存储最大容量是多少?

8、Redis 的持久化机制是什么?各自的优缺点?

9、Redis 常见性能问题和解决方案:

10、redis 过期键的删除策略?

11、Redis 的回收策略(淘汰策略)?

12、为什么 edis 需要把所有数据放到内存中?

13、Redis 的同步机制了解么?

答:Redis 可以使用主从同步,从从同步。第一次同步时,主节点做一次 bgsave,并同时将后续修改操作记录到内存 buffer,待完成后将 rdb 文件全量同步到复制节点,复制节点接受完成后将 rdb 镜像加载到内存。加载完成后,再通知主节点将期间修改的操作记录同步到复制节点进行重放就完成了同步过程。

14、Pipeline 有什么好处,为什么要用 pipeline?

15、是否使用过 Redis 集群,集群的原理是什么?

16、Redis 集群方案什么情况下会导致整个集群不可用?

17、Redis 支持的 Java 客户端都有哪些?官方推荐用哪个?

18、Jedis 与 Redisson 对比有什么优缺点?

19、Redis 如何设置密码及验证密码?

20、说说 Redis 哈希槽的概念?

21、Redis 集群的主从复制模型是怎样的?

22、Redis 集群会有写操作丢失吗?为什么?

23、Redis 集群之间是如何复制的?

24、Redis 集群最大节点个数是多少?

25、Redis 集群如何选择数据库?

26、怎么测试 Redis 的连通性?

27、怎么理解 Redis 事务?

28、Redis 事务相关的命令有哪几个?

答:异步复制


Spring 面试题

1、一般问题

1.1、不同版本的 Spring Framework 有哪些主要功能?

1.2、什么是 Spring Framework?

1.3、列举 Spring Framework 的优点。

由于 Spring Frameworks 的分层架构,用户可以自由选择自己需要的组件。Spring Framework 支持 POJO(Plain Old Java Object) 编程,从而具备持续集成和可测试性。由于依赖注入和控制反转,JDBC 得以简化。它是开源免费的。

1.4、Spring Framework 有哪些不同的功能?

1.5、Spring Framework 中有多少个模块,它们分别是什么?

1.6、什么是 Spring 配置文件?

1.7、Spring 应用程序有哪些不同组件?

1.8、使用 Spring 有哪些方式?

2、依赖注入(Ioc)

2.1、什么是 Spring IOC 容器?

Spring 框架的核心是 Spring 容器。容器创建对象,将它们装配在一起,配置它们并管理它们的完整生命周期。Spring 容器使用依赖注入来管理组成应用程序的组件。容器通过读取提供的配置元数据来接收对象进行实例化,配置和组装的指令。该元数据可以通过 XML,Java 注解或 Java 代码提供。

2.2、什么是依赖注入?

2.3、可以通过多少种方式完成依赖注入?

2.4、区分构造函数注入和 setter 注入。

2.5、spring 中有多少种 IOC 容器?

2.6、区分 BeanFactory 和 ApplicationContext。

2.7、列举 IoC 的一些好处。

2.8、Spring IoC 的实现机制。

3、Beans

3.1、什么是 spring bean?

3.2、spring 提供了哪些配置方式?

3.3、spring 支持集中 bean scope?

3.4、spring bean 容器的生命周期是什么样的?

3.5、什么是 spring 的内部 bean?

3.6、什么是 spring 装配

3.7、自动装配有哪些方式?

3.8、自动装配有什么局限?

4、注解

4.1、什么是基于注解的容器配置

4.2、如何在 spring 中启动注解装配?

4.3、@Component, @Controller, @Repository, @Service 有何区别?

4.4、@Required 注解有什么用?

4.5、@Autowired 注解有什么用?

4.6、@Qualifier 注解有什么用?

4.7、@RequestMapping 注解有什么用?

5、数据访问

5.1、spring DAO 有什么用?

5.2、列举 Spring DAO 抛出的异常。

5.3、spring JDBC API 中存在哪些类?

5.4、使用 Spring 访问 Hibernate 的方法有哪些?

5.5、列举 spring 支持的事务管理类型

5.6、spring 支持哪些 ORM 框架

6、AOP

6.1、什么是 AOP?

6.2、什么是 Aspect?

6.3、什么是切点(JoinPoint)

6.4、什么是通知(Advice)?

6.5、有哪些类型的通知(Advice)?

6.6、指出在 spring aop 中 concern 和 cross-cutting concern 的不同之处。

6.7、AOP 有哪些实现方式?

6.8、Spring AOP and AspectJ AOP 有什么区别?

6.9、如何理解 Spring 中的代理?

6.10、什么是编织(Weaving)?

7、MVC

7.1、Spring MVC 框架有什么用?

7.2、描述一下 DispatcherServlet 的工作流程

7.3、介绍一下 WebApplicationContext

结论
****     选择一份更好的工作,是对自己负责也是对他人的负责,当然面试一家好的公司也是需要自身日积月累知识的积累,俗话说:不打无准备之仗!最近我针对互联网公司面试问到的知识点,总结出了Java程序员面试涉及到的绝大部分面试题及答案分享给大家,希望能帮助到你面试前的复习且找到一个好的工作,也节省你在网上搜索资料的时间来学习。

内容涵盖:Java、MyBatis、ZooKeeper、Dubbo、Elasticsearch、Memcached、Redis、MySQL、Spring、SpringBoot、SpringCloud、RabbitMQ、Kafka、Linux等技术栈。希望能够帮助到有需要的小伙伴们!已经为大家打包好,有需要的小伙伴可以自行领取一下!完整版Java面试题地址:JAVA后端面试题整合