写点什么

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

作者:钟奕礼
  • 2022-11-25
    湖南
  • 本文字数:6238 字

    阅读完需:约 20 分钟

前言怎么样是不是感觉面试很难,而且快到了“年底”跳槽涨薪高峰季了,不管是实习生还是有想要跳槽的大佬们即将进入找工作的高峰期,在任何 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 等技术栈。希望能够帮助到有需要的小伙伴们!资料已整理成文档,需要获取的小伙伴可以+ VX: mxk6072




用户头像

钟奕礼

关注

还未添加个人签名 2021-03-24 加入

还未添加个人简介

评论

发布
暂无评论
互联网大厂必问之MySQL、Redis、Spring三大块,面试必备技术栈_Java_钟奕礼_InfoQ写作社区