坚持7天,短期内快速完成C++后端面试突击。每天10题,弥补后端八股知识缺漏,熟练掌握后端的高频考点,后端面试更有把握。
1. InnoDB 和 MyISAM 的比较?
-
事务支持:
- InnoDB 支持事务(ACID特性),可以实现事务的原子性、一致性、隔离性和持久性,适合于对数据完整性要求较高的应用场景。
- MyISAM 不支持事务,因此不具备事务的特性,对于简单的读写操作和非事务性的应用场景性能可能更好。
-
并发控制:
- InnoDB 支持行级锁(row-level locking),可以实现高并发的读写操作,提高多用户并发访问的性能。
- MyISAM 使用表级锁(table-level locking),对于大量并发的读写操作会存在锁竞争,性能可能受到影响。
-
索引支持:
- InnoDB 支持聚簇索引(clustered index),可以将数据行与索引行存储在一起,提高查询性能和范围查询的效率。
- MyISAM 不支持聚簇索引,因此对于范围查询等操作可能性能较差。
-
数据完整性:
- InnoDB 支持外键约束、行级锁和事务,可以保证数据的完整性和一致性。
- MyISAM 不支持外键约束和事务,对数据完整性的保证相对较弱。
-
崩溃恢复:
- InnoDB 支持崩溃恢复和故障恢复,具有更好的可靠性和容错性。
- MyISAM 在发生崩溃时,可能会导致表损坏或数据丢失,需要手动修复。
-
表级别锁定:
- InnoDB 使用行级锁定,可以在更高并发的情况下实现更好的性能。
- MyISAM 使用表级别锁定,可能会导致性能瓶颈。
2. 谈谈你对水平切分和垂直切分的理解?
水平切分(Horizontal Partitioning)和垂直切分(Vertical Partitioning)是在数据库设计中常用的两种数据切分策略,用于将大型数据库分割成更小、更容易管理的部分。它们的主要区别在于切分的方向和切分的依据:
-
水平切分:
- 水平切分是将数据按照行的方式进行划分,即将数据按照某种规则分割成多个数据集,每个数据集包含一部分行数据。
- 水平切分通常根据某个字段(如用户ID、时间戳等)的取值范围或者哈希值来进行划分,使得相同类型的数据分散存储在不同的数据集中。
- 水平切分适用于数据量较大、单表查询压力较大的场景,可以通过分散存储和并行处理提高系统的扩展性和性能。
-
垂直切分:
- 垂直切分是将数据按照列的方式进行划分,即将数据表中的列按照某种规则分割成多个数据集,每个数据集包含一部分列。
- 垂直切分通常根据数据表中的列的关联性和访问频率来进行划分,将不同的列存储在不同的数据集中,以减少数据冗余和提高数据访问效率。
- 垂直切分适用于表中包含大量的列,但不同列的访问频率和关联性不同的场景,可以根据实际需求将列划分到不同的数据集中,实现数据的精细化管理。
3. 主从复制中涉及到哪三个线程?
在MySQL的主从复制(Master-Slave Replication)中,涉及到以下三个线程:
-
Binlog Dump 线程:
- Binlog Dump 线程是在从服务器(Slave)上运行的一个线程,它负责从主服务器(Master)获取二进制日志(Binary Log)的内容,并将这些日志内容应用到从服务器上,实现数据的复制。
-
I/O 线程:
- I/O 线程是在从服务器上运行的一个线程,它负责与主服务器建立连接,并从主服务器上读取二进制日志的内容,将读取的二进制日志内容写入到从服务器上的中继日志(Relay Log)中。
-
SQL 线程:
- SQL 线程是在从服务器上运行的一个线程,它负责读取从主服务器上的中继日志(Relay Log)中的内容,并在从服务器上执行这些日志内容,实现主服务器上的操作在从服务器上的重放,从而实现数据的复制。
这三个线程协作工作,实现了主从复制的功能。Binlog Dump 线程负责向主服务器请求二进制日志,I/O 线程负责从主服务器读取二进制日志,并写入到从服务器的中继日志,而SQL 线程则负责读取中继日志中的内容,并在从服务器上执行这些日志,实现数据的复制。
4. 主从同步的延迟原因及解决办法?
主从同步的延迟可能由多种原因引起,常见的包括:
-
网络延迟:主从服务器之间的网络连接存在延迟,导致二进制日志传输的延迟。
-
主服务器负载高:主服务器的负载过高,导致主服务器处理二进制日志的速度变慢,进而影响了主从同步的速度。
-
从服务器负载高:从服务器的负载过高,导致从服务器处理中继日志的速度变慢,也会影响主从同步的速度。
-
复制线程阻塞:复制线程(例如I/O线程、SQL线程)在执行过程中发生阻塞,导致数据复制的延迟。
-
复制过滤:从服务器上设置了复制过滤规则,导致某些更新操作未被复制,引起主从同步延迟。
针对主从同步的延迟问题,可以采取以下一些解决办法:
-
优化网络连接:确保主从服务器之间的网络连接稳定,并尽量减少网络延迟,可以考虑使用更高带宽的网络连接或者优化网络路由。
-
调整服务器配置:对于负载高的情况,可以调整服务器配置,增加硬件资源(CPU、内存、磁盘等),以提高处理能力。
-
优化复制线程:对于复制线程阻塞的情况,可以识别并解决复制线程阻塞的原因,例如优化查询、减少锁等。
-
监控和报警:建立监控系统,定期监控主从同步延迟情况,并设置报警机制,及时发现并解决延迟问题。
-
调整复制配置:对于复制过滤的情况,可以检查并调整从服务器的复制规则,确保需要同步的更新操作被正确复制。
-
使用半同步复制:半同步复制可以提高主从同步的可靠性,降低延迟,可以考虑使用半同步复制来减少主从同步延迟。
5. MySQL 默认的隔离级别是什么?
MySQL 默认的隔离级别是可重复读(Repeatable Read)。在可重复读隔离级别下,事务可以看到其它事务已提交的数据,但不会看到其它事务未提交的数据,从而实现了事务的隔离性。MySQL 中的 InnoDB 存储引擎默认采用可重复读隔离级别,这也是大多数情况下推荐的隔离级别,因为它可以避免幻读等并发问题,并且适用于大多数应用场景。
6. InnoDB 存储引擎的锁的算法有哪些?
InnoDB 存储引擎在实现事务隔离级别时使用了多种锁的算法,主要包括以下几种:
-
共享锁(S锁,Shared Lock):
- 共享锁是一种读取锁,多个事务可以同时持有共享锁,用于防止其他事务对数据的修改操作,但允许其他事务对同一数据进行读取操作。
-
排他锁(X锁,Exclusive Lock):
- 排他锁是一种写入锁,事务持有排他锁时,其他事务无法同时持有共享锁或排他锁,用于防止其他事务对数据的读取或修改操作。
-
意向锁(Intention Lock):
- 意向锁用于表示事务打算对某一数据行或数据表进行何种类型的锁定操作,包括意向共享锁(IS锁)和意向排他锁(IX锁)。事务在请求行级锁或表级锁之前,需要先获取相应的意向锁。
-
记录锁(Record Lock):
- 记录锁是针对数据行的锁,用于在事务对数据行进行修改时保护数据完整性。在 InnoDB 存储引擎中,通过锁定索引记录来实现记录锁。
-
间隙锁(Gap Lock):
- 间隙锁用于锁定两个索引记录之间的空隙,防止其他事务在该空隙中插入新的记录,从而防止幻读问题的发生。
-
Next-Key锁:
- Next-Key锁是记录锁和间隙锁的组合,用于实现范围查询时的锁定策略,既可以锁定满足条件的索引记录,也可以锁定索引记录之间的间隙,从而保证事务隔离性。
以上这些锁的算法是 InnoDB 存储引擎在实现事务隔离级别时使用的关键技术,通过合理使用这些锁,可以保证事务的隔离性和数据的完整性。
7. Redis 为什么这么快?
Redis 之所以快速,主要归因于以下几个方面的设计和优化:
-
基于内存的数据存储:
- Redis 是基于内存的数据存储系统,数据存储在内存中,因此具有非常快的读写速度。与传统的磁盘存储相比,内存存储可以大大减少数据访问的延迟。
-
单线程模型:
- Redis 使用单线程模型,即主线程负责处理所有的客户端请求。虽然单线程在多核系统中无法充分利用多核资源,但单线程模型可以避免多线程间的锁竞争和上下文切换开销,从而提高了系统的性能。
-
非阻塞 I/O:
- Redis 使用了非阻塞 I/O 模型,主线程在处理客户端请求时不会被阻塞,可以继续处理其他请求,提高了系统的并发能力和响应速度。
-
高效的数据结构:
- Redis 提供了丰富而高效的数据结构,包括字符串、哈希表、列表、集合、有序集合等。这些数据结构经过优化和精心设计,可以在内存中高效地存储和操作数据,提高了系统的性能。
-
事件驱动机制:
- Redis 使用事件驱动机制处理网络请求和定时任务,通过事件循环机制实现对事件的异步处理。这种机制可以降低系统的负载和延迟,提高系统的响应速度。
-
持久化机制:
- Redis 提供了多种持久化机制,包括快照(Snapshot)和日志(Append-only File)方式。持久化机制可以保证数据的安全性和可靠性,同时也通过异步方式进行,不影响系统的性能。
8. 什么是缓存雪崩?怎么解决?
缓存雪崩是指在缓存系统中,大量的缓存数据同时失效或者被清除,导致大量的请求直接落到数据库或者后端系统上,从而造成系统的压力骤增,甚至导致系统崩溃的现象。缓存雪崩通常发生在缓存中的大量数据同时失效或者清除的情况下,可能是由于缓存服务器故障、数据同步问题、大规模的系统升级或者重启等原因引起。
为了解决缓存雪崩问题,可以采取以下几种方法:
-
缓存数据的过期时间随机化:
- 将缓存数据的过期时间设置为随机值,避免大量的缓存数据在同一时间点失效。通过将缓存数据的过期时间分散在不同的时间段,可以减少缓存雪崩的发生概率。
-
使用多级缓存:
- 使用多级缓存架构,将缓存数据分布在不同的缓存层中,例如本地缓存、分布式缓存、CDN 缓存等。当某一级缓存发生故障或者数据失效时,可以从其他级别的缓存中获取数据,从而降低系统的压力。
-
实时监控和报警:
- 建立监控系统,实时监控缓存系统的状态和性能指标,及时发现异常情况和潜在风险,并设置报警机制,及时通知运维人员进行处理。
-
热点数据预热:
- 在缓存失效之前,提前将热点数据加载到缓存中,避免在数据失效时大量的请求直接落到后端系统上。通过定时任务或者预热策略,可以确保缓存中始终包含热门数据,减少缓存雪崩的发生。
-
限流和降级策略:
- 在系统高峰期或者缓存失效时,可以通过限流和降级等策略,控制请求的流量并临时关闭部分功能,以保护后端系统的稳定性和可用性。
9. 什么是缓存穿透?该如何解决?
缓存穿透是指恶意请求或者无效请求导致缓存无法命中,从而直接落到后端系统进行查询,最终导致数据库或者后端系统压力过大的问题。通常情况下,缓存穿透发生在查询一个不存在的数据或者无效的数据时,由于缓存不命中而导致请求直接访问数据库或者后端系统。
解决缓存穿透问题可以采取以下几种方法:
-
使用布隆过滤器(Bloom Filter):
- 布隆过滤器是一种高效的数据结构,用于快速判断一个元素是否存在于集合中。可以在查询之前使用布隆过滤器进行过滤,将查询过程中不存在的数据直接拦截,从而避免缓存穿透的发生。
-
空对象缓存:
- 在查询结果为空时,也将空结果缓存起来,设置一个较短的过期时间。这样可以防止频繁的查询请求落到后端系统上,降低了对数据库的压力,但需要注意避免缓存过多无效的数据。
-
使用快速失败机制:
- 在查询请求发生时,先进行快速的判断,如果请求参数不合法或者是明显无效的请求,则可以直接拒绝并返回错误码,避免落到后端系统进行处理。
-
热点数据预热:
- 针对热点数据,可以提前将其加载到缓存中,使得这些数据在被频繁查询时能够命中缓存,从而降低了缓存穿透的发生概率。
-
限流和降级策略:
- 在系统高峰期或者频繁发生缓存穿透时,可以通过限流和降级等策略,控制请求的流量并临时关闭部分功能,以保护后端系统的稳定性和可用性。
10. 请说明信号处理的方式有哪些?
信号处理是操作系统中用于处理异步事件的一种机制,常见的信号处理方式包括以下几种:
-
默认处理方式:
- 对于每个信号,操作系统都定义了默认的处理方式。例如,对于 SIGINT(中断信号),操作系统的默认处理方式是终止进程;对于 SIGTERM(终止信号),默认处理方式也是终止进程。如果不对信号进行特殊处理,进程将按照默认方式处理信号。
-
忽略信号:
- 进程可以选择忽略某些信号,即在收到该信号时不做任何处理。这通常用于处理某些不需要关注的信号,或者在特定情况下需要屏蔽某些信号的场景。
-
捕获信号并处理:
- 进程可以注册信号处理函数,在收到信号时执行特定的处理逻辑。通过调用
signal
函数或者使用sigaction
结构体,可以将信号和处理函数进行绑定。
- 进程可以注册信号处理函数,在收到信号时执行特定的处理逻辑。通过调用
-
阻塞信号:
- 进程可以将某些信号阻塞,使得在阻塞期间收到的信号被暂时挂起,直到解除阻塞后才会执行对应的处理逻辑。可以使用
sigprocmask
函数来设置信号的阻塞集合。
- 进程可以将某些信号阻塞,使得在阻塞期间收到的信号被暂时挂起,直到解除阻塞后才会执行对应的处理逻辑。可以使用
-
多线程信号处理:
- 对于多线程程序,每个线程都有自己的信号处理函数。线程可以选择接收或者忽略某些信号,也可以选择在收到信号时执行特定的处理逻辑。
-
信号排队:
- 在一些情况下,如果同一种信号被连续发送多次,操作系统会将这些信号排队,并在处理完上一个信号后按顺序处理下一个信号。这种机制可以确保不会丢失重复的信号。