博客记录-day105-SpringCloud,SQL面试题

一、小林-SpringCloud面试题

1、了解SpringCloud吗,说一下他和SpringBoot的区别

Spring Boot是用于构建单个Spring应用的框架,而Spring Cloud则是用于构建分布式系统中的微服务架构的工具,Spring Cloud提供了服务注册与发现、负载均衡、断路器、网关等功能。

两者可以结合使用,通过Spring Boot构建微服务应用,然后用Spring Cloud来实现微服务架构中的各种功能。

2、用过哪些微服务组件?

微服务常用的组件:

  • 注册中心 :注册中心是微服务架构最核心的组件。它起到的作用是对新节点的注册与状态维护,解决了「如何发现新节点以及检查各节点的运行状态的问题」。微服务节点在启动时会将自己的服务名称、IP、端口等信息在注册中心登记,注册中心会定时检查该节点的运行状态。注册中心通常会采用心跳机制最大程度保证已登记过的服务节点都是可用的。
  • 负载均衡 :负载均衡解决了「如何发现服务及负载均衡如何实现的问题」,通常微服务在互相调用时,并不是直接通过IP、端口进行访问调用。而是先通过服务名在注册中心查询该服务拥有哪些节点,注册中心将该服务可用节点列表返回给服务调用者,这个过程叫服务发现,因服务高可用的要求,服务调用者会接收到多个节点,必须要从中进行选择。因此服务调用者一端必须内置负载均衡器,通过负载均衡策略选择合适的节点发起实质性的通信请求。
  • 服务通信 :服务通信组件解决了「服务间如何进行消息通信的问题」,服务间通信采用轻量级协议,通常是HTTP RESTful风格。但因为RESTful风格过于灵活,必须加以约束,通常应用时对其封装。例如在SpringCloud中就提供了Feign和RestTemplate两种技术屏蔽底层的实现细节,所有开发者都是基于封装后统一的SDK进行开发,有利于团队间的相互合作。
  • 配置中心 :配置中心主要解决了「如何集中管理各节点配置文件的问题」,在微服务架构下,所有的微服务节点都包含自己的各种配置文件,如jdbc配置、自定义配置、环境配置、运行参数配置等。要知道有的微服务可能可能有几十个节点,如果将这些配置文件分散存储在节点上,发生配置更改就需要逐个节点调整,将给运维人员带来巨大的压力。配置中心便由此而生,通过部署配置中心服务器,将各节点配置文件从服务中剥离,集中转存到配置中心。一般配置中心都有UI界面,方便实现大规模集群配置调整。
  • 集中式日志管理 :集中式日志主要是解决了「如何收集各节点日志并统一管理的问题」。微服务架构默认将应用日志分别保存在部署节点上,当需要对日志数据和操作数据进行数据分析和数据统计时,必须收集所有节点的日志数据。那么怎么高效收集所有节点的日志数据呢?业内常见的方案有ELK、EFK。通过搭建独立的日志收集系统,定时抓取各节点增量日志形成有效的统计报表,为统计和分析提供数据支撑。
  • 分布式链路追踪:分布式链路追踪解决了「如何直观的了解各节点间的调用链路的问题」。系统中一个复杂的业务流程,可能会出现连续调用多个微服务,我们需要了解完整的业务逻辑涉及的每个微服务的运行状态,通过可视化链路图展现,可以帮助开发人员快速分析系统瓶颈及出错的服务。
  • 服务保护 :服务保护主要是解决了「如何对系统进行链路保护,避免服务雪崩的问题」。在业务运行时,微服务间互相调用支撑,如果某个微服务出现高延迟导致线程池满载,或是业务处理失败。这里就需要引入服务保护组件来实现高延迟服务的快速降级,避免系统崩溃。

SpringCloud Alibaba实现的微服务架构:

  • SpringCloud Alibaba中使用Alibaba Nacos 组件实现注册中心,Nacos提供了一组简单易用的特性集,可快速实现动态服务发现、服务配置、服务元数据及流量管理。
  • SpringCloud Alibaba 使用Nacos服务端均衡实现负载均衡,与Ribbon在调用端负载不同,Nacos是在服务发现的同时利用负载均衡返回服务节点数据。
  • SpringCloud Alibaba 使用Netflix FeignAlibaba Dubbo 组件来实现服务通行,前者与SpringCloud采用了相同的方案,后者则是对自家的RPC 框架Dubbo也给予支持,为服务间通信提供另一种选择。
  • SpringCloud Alibaba 在API服务网关 组件中,使用与SpringCloud相同的组件,即:SpringCloud Gateway
  • SpringCloud Alibaba在配置中心组件中使用Nacos内置配置中心 ,Nacos内置的配置中心,可将配置信息存储保存在指定数据库
  • SpringCloud Alibaba在原有的ELK方案外,还可以使用阿里云日志服务(LOG)实现日志集中式管理。
  • SpringCloud Alibaba在分布式链路组件 中采用与SpringCloud相同的方案,即:Sleuth/Zipkin Server
  • SpringCloud Alibaba使用Alibaba Sentinel实现系统保护,Sentinel不仅功能更强大,实现系统保护比Hystrix更优雅,而且还拥有更好的UI界面。

3、负载均衡有哪些算法?

  • 简单轮询:将请求按顺序分发给后端服务器上,不关心服务器当前的状态,比如后端服务器的性能、当前的负载。
  • 加权轮询:根据服务器自身的性能给服务器设置不同的权重,将请求按顺序和权重分发给后端服务器,可以让性能高的机器处理更多的请求
  • 简单随机:将请求随机分发给后端服务器上,请求越多,各个服务器接收到的请求越平均
  • 加权随机:根据服务器自身的性能给服务器设置不同的权重,将请求按各个服务器的权重随机分发给后端服务器
  • 一致性哈希:根据请求的客户端 ip、或请求参数通过哈希算法得到一个数值,利用该数值取模映射出对应的后端服务器,这样能保证同一个客户端或相同参数的请求每次都使用同一台服务器
  • 最小活跃数:统计每台服务器上当前正在处理的请求数,也就是请求活跃数,将请求分发给活跃数最少的后台服务器

4、如何实现一直均衡给一个用户?

可以通过「一致性哈希算法」来实现,根据请求的客户端 ip、或请求参数通过哈希算法得到一个数值,利用该数值取模映射出对应的后端服务器,这样能保证同一个客户端或相同参数的请求每次都使用同一台服务器。

5、介绍一下服务熔断

服务熔断是应对微服务雪崩效应的一种链路保护机制,类似股市、保险丝

比如说,微服务之间的数据交互是通过远程调用来完成的。服务A调用服务,服务B调用服务c,某一时间链路上对服务C的调用响应时间过长或者服务C不可用,随着时间的增长,对服务C的调用也越来越多,然后服务C崩溃了,但是链路调用还在,对服务B的调用也在持续增多,然后服务B崩溃,随之A也崩溃,导致雪崩效应。

服务熔断是应对雪崩效应的一种微服务链路保护机制。例如在高压电路中,如果某个地方的电压过高,熔断器就会熔断,对电路进行保护。同样,在微服务架构中,熔断机制也是起着类似的作用。当调用链路的某个微服务不可用或者响应时间太长时,会进行服务熔断,不再有该节点微服务的调用,快速返回错误的响应信息。当检测到该节点微服务调用响应正常后,恢复调用链路。

所以,服务熔断的作用类似于我们家用的保险丝,当某服务出现不可用或响应超时的情况时,为了防止整个系统出现雪崩,暂时停止对该服务的调用。

在Spring Cloud框架里,熔断机制通过Hystrix实现。Hystrix会监控微服务间调用的状况,当失败的调用到一定阈值,缺省是5秒内20次调用失败,就会启动熔断机制。

6、介绍一下服务降级

服务降级一般是指在服务器压力剧增的时候,根据实际业务使用情况以及流量,对一些服务和页面有策略的不处理或者用一种简单的方式进行处理,从而释放服务器资源的资源以保证核心业务的正常高效运行。

服务器的资源是有限的,而请求是无限的。在用户使用即并发高峰期,会影响整体服务的性能,严重的话会导致宕机,以至于某些重要服务不可用。故高峰期为了保证核心功能服务的可用性,就需要对某些服务降级处理。可以理解为舍小保大

服务降级是从整个系统的负荷情况出发和考虑的,对某些负荷会比较高的情况,为了预防某些功能(业务场景)出现负荷过载或者响应慢的情况,在其内部暂时舍弃对一些非核心的接口和数据的请求,而直接返回一个提前准备好的fallback(退路)错误处理信息。这样,虽然提供的是一个有损的服务,但却保证了整个系统的稳定性和可用性。

二、小林-MySQL面试题

1、NOSQL和SQL的区别?

SQL数据库,指关系型数据库 - 主要代表:SQL Server,Oracle,MySQL(开源),PostgreSQL(开源)。

关系型数据库存储结构化数据。这些数据逻辑上以行列二维表的形式存在,每一列代表数据的一种属性,每一行代表一个数据实体。

NoSQL指非关系型数据库 ,主要代表:MongoDBRedis 。NoSQL 数据库逻辑上提供了不同于二维表的存储方式,存储方式可以是JSON文档、哈希表或者其他方式。

选择 SQL vs NoSQL,考虑以下因素。

ACID vs BASE

关系型数据库支持 ACID 即原子性,一致性,隔离性和持续性。相对而言,NoSQL 采用更宽松的模型 BASE , 即基本可用,软状态和最终一致性。

从实用的角度出发,我们需要考虑对于面对的应用场景,ACID 是否是必须的。比如银行应用就必须保证 ACID,否则一笔钱可能被使用两次;又比如社交软件不必保证 ACID,因为一条状态的更新对于所有用户读取先后时间有数秒不同并不影响使用。

对于需要保证 ACID 的应用,我们可以优先考虑 SQL。反之则可以优先考虑 NoSQL。

扩展性对比

NoSQL数据之间无关系,这样就非常容易扩展,也无形之间,在架构的层面上带来了可扩展的能力。比如 redis 自带主从复制模式、哨兵模式、切片集群模式。

相反关系型数据库的数据之间存在关联性,水平扩展较难 ,需要解决跨服务器 JOIN,分布式事务等问题。

2、数据库三大范式是什么?

第一范式(1NF):要求数据库表的每一列都是不可分割的原子数据项。

举例说明:

在上面的表中,"家庭信息"和"学校信息"列均不满足原子性的要求,故不满足第一范式,调整如下:

可见,调整后的每一列都是不可再分的,因此满足第一范式(1NF);

第二范式(2NF):在1NF的基础上,非码属性必须完全依赖于候选码(在1NF基础上消除非主属性对主码的部分函数依赖)

第二范式需要确保数据库表中的每一列都和主键相关,而不能只与主键的某一部分相关(主要针对联合主键而言)。

举例说明:

在上图所示的情况中,同一个订单中可能包含不同的产品,因此主键必须是"订单号"和"产品号"联合组成,

但可以发现,产品数量、产品折扣、产品价格与"订单号"和"产品号"都相关,但是订单金额和订单时间仅与"订单号"相关,与"产品号"无关,

这样就不满足第二范式的要求,调整如下,需分成两个表:

第三范式(3NF):在2NF基础上,任何非主属性 (opens new window)不依赖于其它非主属性(在2NF基础上消除传递依赖)

第三范式需要确保数据表中的每一列数据都和主键直接相关,而不能间接相关。

举例说明:

上表中,所有属性都完全依赖于学号,所以满足第二范式,但是"班主任性别"和"班主任年龄"直接依赖的是"班主任姓名",

而不是主键"学号",所以需做如下调整:

这样以来,就满足了第三范式的要求。

3、MySQL 怎么连表查询?

数据库有以下几种联表查询类型:

  1. 内连接 (INNER JOIN)
  2. 左外连接 (LEFT JOIN)
  3. 右外连接 (RIGHT JOIN)
  4. 全外连接 (FULL JOIN)

1. 内连接 (INNER JOIN)

内连接返回两个表中有匹配关系的行。示例:

sql 复制代码
SELECT employees.name, departments.name
FROM employees
INNER JOIN departments
ON employees.department_id = departments.id;

这个查询返回每个员工及其所在的部门名称。

2. 左外连接 (LEFT JOIN)

左外连接返回左表中的所有行 ,即使在右表中没有匹配的行。未匹配的右表列会包含NULL。示例:

sql 复制代码
SELECT employees.name, departments.name
FROM employees
LEFT JOIN departments
ON employees.department_id = departments.id;

这个查询返回所有员工及其部门名称,包括那些没有分配部门的员工。

3. 右外连接 (RIGHT JOIN)

右外连接返回右表中的所有行,即使左表中没有匹配的行。未匹配的左表列会包含NULL。示例:

sql 复制代码
SELECT employees.name, departments.name
FROM employees
RIGHT JOIN departments
ON employees.department_id = departments.id;

这个查询返回所有部门及其员工,包括那些没有分配员工的部门。

4. 全外连接 (FULL JOIN)

全外连接返回两个表中所有行,包括非匹配行,在MySQL中,FULL JOIN 需要使用 UNION 来实现,因为 MySQL 不直接支持 FULL JOIN。示例:

sql 复制代码
SELECT employees.name, departments.name
FROM employees
LEFT JOIN departments
ON employees.department_id = departments.id

UNION

SELECT employees.name, departments.name
FROM employees
RIGHT JOIN departments
ON employees.department_id = departments.id;

这个查询返回所有员工和所有部门,包括没有匹配行的记录。

4、MySQL如何避免重复插入数据?

方式一:使用UNIQUE约束

在表的相关列上添加UNIQUE约束,确保每个值在该列中唯一。例如:

sql 复制代码
CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    email VARCHAR(255) UNIQUE,
    name VARCHAR(255)
);

如果尝试插入重复的email,MySQL会返回错误。

方式二:使用INSERT ... ON DUPLICATE KEY UPDATE

这种语句允许在插入记录时处理重复键的情况。如果插入的记录与现有记录冲突,可以选择更新现有记录:

sql 复制代码
INSERT INTO users (email, name) 
VALUES ('example@example.com', 'John Doe')
ON DUPLICATE KEY UPDATE name = VALUES(name);

方式三:使用INSERT IGNORE: 该语句会在插入记录时忽略那些因重复键而导致的插入错误。例如:

sql 复制代码
INSERT IGNORE INTO users (email, name) 
VALUES ('example@example.com', 'John Doe');

如果email已经存在,这条插入语句将被忽略而不会返回错误。

选择哪种方法取决于具体的需求:

  • 如果需要保证全局唯一性,使用UNIQUE约束是最佳做法。
  • 如果需要插入和更新结合可以使用ON DUPLICATE KEY UPDATE
  • 对于快速忽略重复插入,INSERT IGNORE是合适的选择。

5、CHAR 和 VARCHAR有什么区别?

  • CHAR是固定长度的字符串类型,定义时需要指定固定长度,存储时会在末尾补足空格。CHAR适合存储长度固定的数据,如固定长度的代码、状态等,存储空间固定,对于短字符串效率较高。
  • VARCHAR是可变长度的字符串类型,定义时需要指定最大长度,实际存储时根据实际长度占用存储空间。VARCHAR适合存储长度可变的数据,如用户输入的文本、备注等,节约存储空间。

6、说一下外键约束

外键约束的作用是维护表与表之间的关系,确保数据的完整性和一致性。让我们举一个简单的例子:

假设你有两个表,一个是学生表,另一个是课程表,这两个表之间有一个关系,即一个学生可以选修多门课程,而一门课程也可以被多个学生选修。在这种情况下,我们可以在学生表中定义一个指向课程表的外键,如下所示:

sql 复制代码
CREATE TABLE students (
  id INT PRIMARY KEY,
  name VARCHAR(50),
  course_id INT,
  FOREIGN KEY (course_id) REFERENCES courses(id)
);

这里,students表中的course_id字段是一个外键,它指向courses表中的id字段。这个外键约束确保了每个学生所选的课程在courses表中都存在,从而维护了数据的完整性和一致性。

如果没有定义外键约束,那么就有可能出现学生选了不存在的课程或者删除了一个课程而忘记从学生表中删除选修该课程的学生的情况,这会破坏数据的完整性和一致性。因此,使用外键约束可以帮助我们避免这些问题。

7、MySQL的关键字in和exist

在MySQL中,INEXISTS 都是用来处理子查询的关键词,但它们在功能、性能和使用场景上有各自的特点和区别。

IN关键字

IN 用于检查左边的表达式是否存在于右边的列表或子查询的结果集中 。如果存在,则IN 返回TRUE,否则返回FALSE

语法结构:

sql 复制代码
SELECT column_name(s)
FROM table_name
WHERE column_name IN (value1, value2, ...);

sql 复制代码
SELECT column_name(s)
FROM table_name
WHERE column_name IN (SELECT column_name FROM another_table WHERE condition);

例子:

sql 复制代码
SELECT * FROM Customers
WHERE Country IN ('Germany', 'France');

EXISTS关键字

EXISTS 用于判断子查询是否至少能返回一行数据。它不关心子查询返回什么数据,只关心是否有结果。如果子查询有结果,则EXISTS 返回TRUE,否则返回FALSE

语法结构:

sql 复制代码
SELECT column_name(s)
FROM table_name
WHERE EXISTS (SELECT column_name FROM another_table WHERE condition);

例子:

sql 复制代码
SELECT * FROM Customers
WHERE EXISTS (SELECT 1 FROM Orders WHERE Orders.CustomerID = Customers.CustomerID);

区别与选择:

  • 性能差异 :在很多情况下,EXISTS 的性能优于 IN,特别是当子查询的表很大时。这是因为EXISTS 一旦找到匹配项就会立即停止查询,而IN可能会扫描整个子查询结果集。
  • 使用场景 :如果子查询结果集较小且不频繁变动,IN 可能更直观易懂。而当子查询涉及外部查询的每一行判断,并且子查询的效率较高时,EXISTS 更为合适。
  • NULL值处理IN 能够正确处理子查询中包含NULL值的情况,而EXISTS 不受子查询结果中NULL值的影响,因为它关注的是行的存在性,而不是具体值。

8、mysql中的一些基本函数,你知道哪些?

一、字符串函数

CONCAT(str1, str2, ...) :连接多个字符串,返回一个合并后的字符串。

sql 复制代码
SELECT CONCAT('Hello', ' ', 'World') AS Greeting;

LENGTH(str) :返回字符串的长度(字符数)。

sql 复制代码
SELECT LENGTH('Hello') AS StringLength;

SUBSTRING(str, pos, len) :从指定位置开始,截取指定长度的子字符串。

sql 复制代码
SELECT SUBSTRING('Hello World', 1, 5) AS SubStr;

REPLACE(str, from_str, to_str) :将字符串中的某部分替换为另一个字符串。

sql 复制代码
SELECT REPLACE('Hello World', 'World', 'MySQL') AS ReplacedStr;

二、数值函数

ABS(num) :返回数字的绝对值。

sql 复制代码
SELECT ABS(-10) AS AbsoluteValue;

POWER(num, exponent) :返回指定数字的指定幂次方。

sql 复制代码
SELECT POWER(2, 3) AS PowerValue;

三、日期和时间函数

NOW() :返回当前日期和时间。

sql 复制代码
SELECT NOW() AS CurrentDateTime;

CURDATE() :返回当前日期。

sql 复制代码
SELECT CURDATE() AS CurrentDate;

四、聚合函数

COUNT(column) :计算指定列中的非NULL值的个数。

sql 复制代码
SELECT COUNT(*) AS RowCount FROM my_table;

SUM(column) :计算指定列的总和。

sql 复制代码
SELECT SUM(price) AS TotalPrice FROM orders;

AVG(column) :计算指定列的平均值。

sql 复制代码
SELECT AVG(price) AS AveragePrice FROM orders;

MAX(column) :返回指定列的最大值。

sql 复制代码
SELECT MAX(price) AS MaxPrice FROM orders;

MIN(column) :返回指定列的最小值。

sql 复制代码
SELECT MIN(price) AS MinPrice FROM orders;

9、SQL查询语句的执行顺序是怎么样的?

所有的查询语句都是从FROM开始执行,在执行过程中,每个步骤都会生成一个虚拟表,这个虚拟表将作为下一个执行步骤的输入,最后一个步骤产生的虚拟表即为输出结果。

sql 复制代码
(9) SELECT 
(10) DISTINCT <column>,
(6) AGG_FUNC <column> or <expression>, ...
(1) FROM <left_table> 
    (3) <join_type>JOIN<right_table>
    (2) ON<join_condition>
(4) WHERE <where_condition>
(5) GROUP BY <group_by_list>
(7) WITH {CUBE|ROLLUP}
(8) HAVING <having_condtion>
(11) ORDER BY <order_by_list>
(12) LIMIT <limit_number>;

10、sql题:给学生表、课程成绩表,求不存在01课程但存在02课程的学生的成绩

可以使用SQL的子查询和LEFT JOIN或者EXISTS关键字来实现,这里我将展示两种不同的方法来完成这个查询。

假设我们有以下两张表:

  1. Student 表,其中包含学生的sid(学生编号)和其他相关信息。
  2. Score 表,其中包含sid(学生编号),cid(课程编号)和score(分数)。

方法1:使用LEFT JOIN 和 IS NULL

sql 复制代码
SELECT s.sid, s.sname, sc2.cid, sc2.score
FROM Student s
LEFT JOIN Score AS sc1 ON s.sid = sc1.sid AND sc1.cid = '01'
LEFT JOIN Score AS sc2 ON s.sid = sc2.sid AND sc2.cid = '02'
WHERE sc1.cid IS NULL AND sc2.cid IS NOT NULL;

方法2:使用NOT EXISTS

sql 复制代码
SELECT s.sid, s.sname, sc.cid, sc.score
FROM Student s
JOIN Score sc ON s.sid = sc.sid AND sc.cid = '02'
WHERE NOT EXISTS (
    SELECT 1 FROM Score sc1 WHERE sc1.sid = s.sid AND sc1.cid = '01'
);

11、给定一个学生表 student_score(stu_id,subject_id,score),查询总分排名在5-10名的学生id及对应的总分

可以使用以下 SQL 查询来检索总分排名在 5 到 10 名的学生 ID 及对应的总分。其中我们先计算每个学生的总分,然后为其分配一个排名,最后检索排名在 5 到 10 之间的记录。

sql 复制代码
WITH StudentTotalScores AS (
    SELECT 
        stu_id,
        SUM(score) AS total_score
    FROM 
        student_score
    GROUP BY 
        stu_id
),
RankedStudents AS (
    SELECT
        stu_id,
        total_score,
        RANK() OVER (ORDER BY total_score DESC) AS ranking
    FROM
        StudentTotalScores
)
SELECT
    stu_id,
    total_score
FROM
    RankedStudents
WHERE
    ranking BETWEEN 5 AND 10;

解释:

  1. 子查询 StudentTotalScores 中,我们通过对 student_score 表中的 stu_id 分组来计算每个学生的总分。
  2. 子查询 RankedStudents 中,我们使用 RANK() 函数为每个学生分配一个排名,按总分从高到低排序。
  3. 最后,我们在主查询中选择排名在 5 到 10 之间的学生。
相关推荐
冲鸭ONE36 分钟前
for循环优化方式有哪些?
后端·性能优化
兮动人38 分钟前
DBeaver连接OceanBase数据库
后端
刘鹏3781 小时前
深入浅出Java中的CAS:原理、源码与实战应用
后端
Lx3521 小时前
《从头开始学java,一天一个知识点》之:循环结构:for与while循环的使用场景
java·后端
fliter1 小时前
RKE1、K3S、RKE2 三大 Kubernetes 发行版的比较
后端
aloha_1 小时前
mysql 某个客户端主机在短时间内发起了大量失败的连接请求时
后端
程序员爱钓鱼1 小时前
Go 语言高效连接 SQL Server(MSSQL)数据库实战指南
后端·go·sql server
xjz18421 小时前
Java AQS(AbstractQueuedSynchronizer)实现原理详解
后端
Victor3561 小时前
Zookeeper(97)如何在Zookeeper中实现分布式协调?
后端
至暗时刻darkest1 小时前
go mod文件 项目版本管理
开发语言·后端·golang