【后端开发面试题】每日 3 题(三)
✍个人博客:Pandaconda-CSDN博客
📣专栏地址:https://blog.csdn.net/newin2020/category_12903849.html
📚专栏简介:在这个专栏中,我将会分享后端开发面试中常见的面试题给大家~
❤️如果有收获的话,欢迎点赞👍收藏📁,您的支持就是我创作的最大动力💪
1. 在 MySQL 中,如何优化慢查询?
- 查询分析
- 使用EXPLAIN关键字:在 SQL 查询语句前加上EXPLAIN,可以查看查询的执行计划,包括表的读取顺序、使用的索引、数据读取类型等信息,从而找出可能存在的性能瓶颈。
- 分析慢查询日志:开启 MySQL 的慢查询日志功能,它会记录执行时间超过指定阈值的查询语句。通过分析这些日志,可以找出经常出现的慢查询。
- 索引优化
- 创建合适的索引:根据查询条件和排序字段,在经常用于WHERE子句、JOIN子句和ORDER BY子句的列上创建索引。例如,对于经常根据用户 ID 查询订单信息的场景,可以在订单表的用户 ID 列上创建索引。
- 避免过多索引:索引虽然可以提高查询速度,但会增加写操作的开销,并且过多的索引会占用更多的磁盘空间。因此,只创建必要的索引。
- 使用复合索引:当多个列经常一起用于查询条件时,可以创建复合索引。例如,(col1, col2)的复合索引可以同时优化基于col1和col1 AND col2的查询。
- 查询语句优化
- 避免使用SELECT *:只选择需要的列,减少数据传输量。
- 优化子查询:尽量将子查询转换为JOIN查询,因为JOIN查询通常比子查询性能更好。
- 避免在WHERE子句中使用函数或表达式:这会导致索引失效,例如WHERE YEAR(create_time) = 2024,可以改为WHERE create_time BETWEEN ‘2024-01-01’ AND ‘2024-12-31’。
- 数据库配置优化
- 调整缓冲区大小:根据服务器的硬件资源,调整innodb_buffer_pool_size、key_buffer_size等参数,以提高数据库的缓存效率。
- 优化查询缓存:对于一些不经常变化的数据查询,可以开启查询缓存,但要注意查询缓存可能会带来额外的开销,需要根据实际情况进行调整。
2. 在 Java 中,synchronized关键字和ReentrantLock有什么区别?
- 语法层面
- synchronized:是 Java 的关键字,是内置的语言实现。它可以修饰方法或代码块,使用起来比较简洁。例如:
public synchronized void method() {
// 同步代码
}
public void method() {
synchronized (this) {
// 同步代码
}
}
- ReentrantLock:是java.util.concurrent.locks包下的一个类,需要手动创建实例并调用lock()和unlock()方法来加锁和解锁。例如:
import java.util.concurrent.locks.ReentrantLock;
public class LockExample {
private final ReentrantLock lock = new ReentrantLock();
public void method() {
lock.lock();
try {
// 同步代码
} finally {
lock.unlock();
}
}
}
- 锁的获取和释放
- synchronized:是隐式获取和释放锁的,当进入同步方法或同步代码块时自动获取锁,退出时自动释放锁。如果发生异常,也会自动释放锁。
- ReentrantLock:需要手动调用lock()方法获取锁,unlock()方法释放锁。为了确保锁一定会被释放,通常将unlock()方法放在finally块中。
- 锁的特性
- 可中断性:synchronized的锁是不可中断的,一旦线程获取到锁,其他线程只能等待。而ReentrantLock可以通过lockInterruptibly()方法实现可中断的锁获取,在等待锁的过程中可以响应中断。
- 公平性:synchronized是非公平锁,即线程获取锁的顺序是不确定的。ReentrantLock可以通过构造函数指定是否为公平锁,公平锁会按照线程请求锁的顺序依次获取锁。
- 锁的条件:ReentrantLock可以通过newCondition()方法创建多个Condition对象,实现更灵活的线程等待和唤醒机制,而synchronized只能使用wait()、notify()和notifyAll()方法,功能相对单一。
3. 请简述微服务架构的优缺点
优点
- 可扩展性:每个微服务可以独立进行扩展,根据业务需求对不同的服务进行水平或垂直扩展,而不会影响其他服务。例如,对于一个电商系统中的订单服务和商品服务,如果订单服务的访问量突然增加,可以只对订单服务进行扩展。
- 技术多样性:不同的微服务可以使用不同的技术栈,开发团队可以根据服务的特点选择最适合的技术。比如,对于计算密集型的服务可以使用 Go 语言,对于数据处理和分析的服务可以使用 Python。
- 独立部署:微服务可以独立开发、测试和部署,一个服务的更新和部署不会影响其他服务,提高了开发和部署的效率。例如,开发团队可以快速迭代某个微服务的功能,而不需要重新部署整个系统。
- 团队协作:将一个大型项目拆分成多个微服务后,不同的团队可以负责不同的服务开发,提高了团队之间的并行开发能力,减少了团队之间的沟通成本。
- 容错性:如果某个微服务出现故障,不会影响整个系统的运行,其他服务可以继续正常工作。同时,可以通过熔断、限流等机制对故障服务进行隔离和处理。
缺点
- 复杂度增加:微服务架构涉及多个服务之间的通信和协调,系统的复杂度大大增加。需要处理服务之间的调用关系、数据一致性、分布式事务等问题。
- 运维成本高:每个微服务都需要独立的运维管理,包括服务器配置、监控、日志管理等。此外,还需要考虑服务之间的网络通信和负载均衡等问题。
- 服务间通信开销:微服务之间的通信需要通过网络进行,会带来一定的延迟和通信开销。如果服务之间的调用频繁,会影响系统的性能。
- 分布式系统问题:微服务架构是一个分布式系统,会面临分布式系统的各种问题,如数据一致性、服务发现、容错等。解决这些问题需要额外的技术和工具支持。