跳至主要內容

大厂面试题

xw大约 44 分钟面试题面试题大全

大厂面试题

阿里二面——JVM:什么是类加载机制

类加载机制是Java虚拟机(JVM)的重要组成部分,它负责在运行时动态加载Java类并将类信息转化为可在JVM内部使用的运行时数据结构。类加载过程主要包含以下几个核心环节:

  1. 加载(Loading):
    • JVM通过类加载器(ClassLoader)找到.class文件,并读取其二进制数据。
    • 将这些数据加载到JVM内存的方法区内,创建方法区内的运行时类数据结构。
    • 在堆内存中为这个类创建一个java.lang.Class对象,作为方法区类数据的外部入口。
  2. 验证(Verification):
    • 确保加载的类信息符合Java虚拟机规范,没有安全方面的威胁,比如非法数据、不符合语义的字节码指令等。
  3. 准备(Preparation):
    • 分配类变量(静态变量)所需的内存空间,并且默认初始化为零值。
  4. 解析(Resolution):
    • 将符号引用转换为直接引用,比如将类引用、字段引用、方法引用转换为实际内存地址。
  5. 初始化(Initialization):
    • 执行类初始化的clinit()方法,初始化静态变量并执行静态初始化块,此时真正的初始值被赋予静态变量。
  6. 类加载器及其委托模型
    • JVM使用多层级的类加载器体系,其中最核心的是双亲委派模型。当一个类加载器收到加载请求时,首先委托父加载器加载,直到顶层启动类加载器。只有当父加载器无法加载时,子加载器才会尝试自己加载。
  7. 按需加载(Lazy Loading):
    • 类的加载并非一次性全部加载,而是按需加载,也就是在首次使用该类时才会触发加载动作。
  8. 缓存机制
    • 已加载过的类会被存储在缓存中,避免重复加载,提高性能。

阿里二面——多线程:线程池处理任务时,出现异常会发生什么?

在Java中,线程池是一种用于管理和复用线程的机制。当线程池执行任务时,如果任务发生异常,会有不同的处理方式,具体取决于你如何配置和处理异常。

当线程池中的线程执行任务时,如果任务抛出未捕获的异常,这个异常会传递给线程池的异常处理器(Thread.UncaughtExceptionHandler)。异常处理器是一个接口,可以自定义实现。如果没有显式地设置异常处理器,则会使用默认的处理器来处理异常。

**默认的异常处理器会打印异常堆栈跟踪信息,并终止抛出异常的线程。如果线程是由线程池创建的,线程池会注意到线程终止并从池中移除该线程,然后创建一个新的线程来替代它,以保持线程池中的线程数量不变。**以一段代码示例如下:

    public static void main(String[] args) throws InterruptedException {
        // 创建一个固定大小为2的线程池
        ExecutorService threadPoolExecutor = Executors.newFixedThreadPool(2);
        
        // 提交第一个任务到线程池执行
        threadPoolExecutor.execute(() -> {
            System.out.println("线程ID" + Thread.currentThread().getId());
        });
        
        // 提交第二个任务到线程池执行
        threadPoolExecutor.execute(() -> {
            System.out.println("线程ID" + Thread.currentThread().getId());
        });
        
        // 提交第三个任务到线程池执行,此任务试图进行除以0的操作,会抛出异常
        threadPoolExecutor.execute(() -> {
            System.out.println("线程ID" + Thread.currentThread().getId());
            System.out.println( 2 / 0);
        });
        
        // 暂停2秒,以便观察线程执行情况
        TimeUnit.SECONDS.sleep(2);
        
        // 继续提交任务到线程池,此时线程池可能仍在处理前三个任务
        threadPoolExecutor.execute(() -> {
            System.out.println("线程ID" + Thread.currentThread().getId());
        });
        threadPoolExecutor.execute(() -> {
            System.out.println("线程ID" + Thread.currentThread().getId());
        });
        
        // 程序暂停100000秒,主要用于测试和观察,实际应用中可能需要根据情况调整
        TimeUnit.SECONDS.sleep(10);
    }

输出结果如下所示,

image-20240408170911471

为了处理线程池中任务的异常,我们可以采取以下步骤:

1.自定义异常处理器

实现Thread.UncaughtExceptionHandler接口,并重写uncaughtException()方法来定义你自己的异常处理逻辑。例如,你可以记录异常日志、发送警报或采取其他适当的操作。

public class CustomExceptionHandler implements Thread.UncaughtExceptionHandler {
    @Override
    public void uncaughtException(Thread t, Throwable e) {
        // 自定义异常处理逻辑
        System.out.println("Exception occurred in thread: " + t.getName());
        e.printStackTrace();
        // 其他处理操作...
    }
}

2.在创建线程池时设置异常处理器

在创建线程池时,使用ThreadPoolExecutor的构造函数之一,并传递自定义的异常处理器。

Thread.UncaughtExceptionHandler exceptionHandler = new CustomExceptionHandler();
ExecutorService executorService = new ThreadPoolExecutor(
    corePoolSize, maxPoolSize, keepAliveTime, TimeUnit.SECONDS,
    new LinkedBlockingQueue<>(), exceptionHandler
);

这样,当线程池中的线程执行任务时发生异常,就会调用自定义的异常处理器进行处理。

3.在任务的执行体中捕获异常

如果我们的任务实现了Runnable接口或Callable接口,我们可以在任务的run()或call()方法中使用try-catch块来捕获异常,并在捕获到异常后进行适当的处理。这种方式可以防止异常传播到线程池的异常处理器中。

Runnable task = new Runnable() {
    @Override
    public void run() {
        try {
            // 任务执行代码
        } catch (Exception e) {
            // 异常处理逻辑
            e.printStackTrace();
            // 其他处理操作...
        }
    }
};

通过上述方式,我们可以自定义处理线程池中任务抛出的异常。这样可以确保我们对异常有完全的控制,并能采取适当的操作,如记录日志、处理错误、发送通知等。

阿里二面——多线程:ConcurrentHashMap的红黑树中为何会保留一套双向链表?

阿里二面——多线程:聊一下ConcurrentHashMap的扩容是怎么做的?

table数据转移到nextTable。扩容操作的核心在于数据的转移,把旧数组中的数据迁移到新的 数组。ConcurrentHashMap精华的部分是它可以利用多线程进行协同扩容,简单来说,它把table数 组当作多个线程之间共享的任务队列,然后通过维护一个指针来划分每个线程锁负责的区间,每个 线程通过区间逆向遍历来实现扩容,一个已经迁移完的Bucket会被替换为一个ForwardingNode节点, 标记当前Bucket已经被其他线程迁移完了。 (5)helpTransfer() ConcurrentHashMap鬼斧神工,并发添加元素时,如果正在扩容,其他线程会帮助扩容,也就 是多线程扩容。 第一次添加元素时,默认初期长度为16,当往table中继续添加元素时,通过哈希值跟数组长 度取余来决定放在数组的哪个Bucket位置,如果出现放在同一个位置时,就优先以链表的形式存放, 在同一个位置的个数又达到了8个以上,如果数组的长度还小于64时,就会扩容数组。如果数组的 长度大于等于64,就会将该节点的链表转换成树。 通过扩容数组的方式来把这些节点给分散开,然后将这些元素复制到扩容后的新数组中,同 一个Bucket中的元素通过哈希值的数组长度位来重新确定位置,可能还是放在原来的位置,也可能 放到新的位置。而且,在扩容完成之后,如果之前某个节点是树,但是现在该节点的“Key-Value 对”数又小于等于6个,就会将该树转为链表。 什么时候扩容?当前容量超过阈值,也就是链表中元素个数超过默认设置(8个)时,如果数 组table的大小还未超过64,此时就进行数组的扩容,如果超过就将链表转化成红黑树。

京东二面——多线程:详尽地对比下synchronized和ReentrantLock的异同?

synchronized实现原理

对象头由两部分组成

  • Mark Word:存储自身的运行时数据,例如 HashCode、GC 年龄、锁相关信息等内容。
  • Klass Pointer:类型指针指向它的类元数据的指针。

64 位虚拟机 Mark Word 是 64bit 其结构如下:

img

在 JDK 6 中虚拟机团队对锁进行了重要改进,优化了其性能引入了 偏向锁轻量级锁适应性自旋锁消除锁粗化等实现,其中 锁消除锁粗化本文不做详细讨论其余内容我们将对其进行逐一探究。

总体上来说锁状态升级流程如下:

img

详情流程见链接:synchronized 实现原理open in new window

synchronized和ReentrantLock都是Java中用于实现线程同步的机制,它们的主要目的是确保多个线程之间对共享资源的访问是安全的。下面是它们的异同点:

相同点:

  1. 线程同步: synchronized和ReentrantLock都可以用于线程同步,确保多个线程之间对共享资源的访问是安全的,避免竞态条件(race condition)和数据不一致问题。
  2. 可重入性: synchronized和ReentrantLock都支持可重入性,即线程可以多次获得同一把锁,而不会死锁。
  3. 阻塞等待: 当一个线程尝试获取锁而发现锁已经被其他线程持有时,它们都会被阻塞,直到锁可用。

不同点:

  1. 使用方式:
    • synchronized是Java语言级别的关键字,用于实现隐式锁。在使用时,直接在方法或代码块前加上synchronized关键字即可。
    • ReentrantLock是Java中的一个类,它提供了显式的锁机制。需要通过创建一个ReentrantLock对象,并在需要的时候手动调用lock()和unlock()方法来控制锁的获取和释放。
  2. 灵活性:
    • ReentrantLock相比synchronized更加灵活,它提供了一些高级功能,如可定时的锁等待、可轮询的锁等待、公平锁和非公平锁等,这些功能在一些特定场景下可能会更有用。
  3. 性能:
    • 在Java 5之前,synchronized的性能通常比ReentrantLock好,因为JVM可以对synchronized进行优化。但是在Java 5以后,ReentrantLock的性能得到了很大的提升,它的性能与synchronized已经相当甚至更好,在某些情况下甚至可以更加灵活和高效。
  4. 异常处理:
    • 使用synchronized时,如果在锁定的代码块中发生异常,JVM会自动释放锁。而使用ReentrantLock时,你需要手动在finally块中释放锁,否则可能会导致死锁或其他问题。

京东二面——多线程:那么请谈谈AQS框架是怎么回事儿?

概述

AQS的全称为(AbstractQueuedSynchronizer),这个类在java.util.concurrent.locks包下面。它是一个Java提高的底层同步工具类,比如CountDownLatch、ReentrantLock,Semaphore,ReentrantReadWriteLock,SynchronousQueue,FutureTask等等皆是基于AQS实现。AQS是一个抽象类,提供了并发的基础执行框架,过程如下图所示:

  1. 获取state同步状态,
  2. 成功加锁执行业务逻辑后释放锁,然后唤醒等待队列的节点。失败构建Node和封装线程,并将Node信息队列尾部,阻塞当前线程。

AQS有三种同步方式,独占式(ReentrantLock)、共享式(Semaphore)、组合(ReentrantReadWriteLock),AQS提供了底层支持,支持自由组装实现。

AQS核心组成:

AQS出于“分离变与不变”的原则,基于模板模式实现。AQS为锁获取、锁释放的排队和出 队过程提供了一系列的模板方法。由于JUC的显式锁种类丰富,因此AQS将不同锁的具体操作抽取 为钩子方法,供各种锁的子类(或者其内部类)去实现。

  1. 转态标志位

AQS中维持了一个单一的volatile修饰的状态信息state,AQS使用int类型的state标示锁的状态, 可以理解为锁的同步状态。由于setState()无法保证原子性,因此AQS给我们提供了compareAndSetState()方法利用底层 UnSafe的CAS机制 来实现原子性 。

 //同步状态,使用volatile保证线程可见 
 private volatile int state;
  1. 队列节点类

AQS是一个虚拟队列,不存在队列实例,仅存在节点之间的前后关系。节点类型通过内部类 Node定义。

  1. FIFO双向同步队列

AQS的内部队列是CLH队列的变种,每当线程通过AQS获取锁失败时,线程将被封装成一个Node 节点,通过CAS原子操作插入队列尾部。当有线程释放锁时,AQS会尝试让队首的后驱节点占用锁。 AQS是一个通过内置的FIFO双向队列来完成线程的排队工作,内部通过节点head和tail记录队 首和队尾元素,元素的节点类型为Node类型。

JUC 显式锁与 AQS 的关系

AQS是java.util.concurrent包的一个同步器,它实现了锁的基本抽象功能,支持独占锁与共享锁 两种方式。该类使用模板模式来实现的,成为构建锁和同步器的框架,使用该类可以简单且高效地 构造出应用广泛的同步器(或者等待队列)。 java.util.concurrent.locks包中的显式锁如ReentrantLock、ReentrantReadWriteLock,线程同步工具 如Semaphore,异步回调工具如FutureTask等,内部都使用了AQS作为等待队列。通过开发工具进行 AQS的子类导航会发现大量的AQS子类以内部类的形式使用

京东二面——多线程:Java中乐观锁的实现原理是什么?

主要有两种实现方式:CAS(Compare and Swap)和版本号控制。CAS是实现乐观锁的核心算法,它通过比较内存中的值是否和预期的值相等来判断是否存在冲突。如果存在,则返回失败;如果不存在,则执行更新操作。

美团二面——多线程:什么是可重入性,为什么说Synchronized是可重入锁?

可重入性是指在一个线程持有锁的情况下,可以再次获取同一个锁,而不会因为自己已经持有该锁而发生死锁。一个锁如果支持可重入性,那么同一个线程在持有锁的情况下,可以多次进入由该锁保护的代码块,而不会被阻塞。

在Java中,synchronized关键字是可重入锁的典型代表。当一个线程获得了一个对象的锁之后,如果该线程再次尝试获取这个锁,它仍然可以成功,因为Java的synchronized机制会记录锁的持有者和锁的计数器。在每次进入synchronized块时,计数器会递增;当线程退出synchronized块时,计数器会递减。只有当计数器归零时,锁才会完全释放。

这种机制使得同一个线程可以反复进入同步块,而不会被自己持有的锁所阻塞,确保了程序的正确性和线程安全性。因此,synchronized被称为可重入锁。

阿里二面——MySQL:如何优化大量数据插入的性能?

  • 一条SQL语句插入多条数据。SQL执行效率高的主要原因是合并后日志量(MySQL的binlog和innodb的事务让日志)减少了,降低日志刷盘的数据量和频率,从而提高效率。通过合并SQL语句,同时也能减少SQL语句解析的次数,减少网络传输的IO
  • 数据有序插入。于数据库插入时,需要维护索引数据,无序的记录会增大维护索引的成本。我们可以参照InnoDB使用的B+tree索引,如果每次插入记录都在索引的最后面,索引的定位效率很高,并且对索引调整较小;如果插入的记录在索引中间,需要B+tree进行分裂合并等处理,会消耗比较多计算资源,并且插入记录的索引定位效率会下降,数据量较大时会有频繁的磁盘操作。
  • 使用事务可以提高数据的插入效率,这是因为进行一个INSERT操作时,MySQL内部会建立一个事务,在事务内才进行真正插入处理操作。通过使用事务可以减少创建事务的消耗,所有插入都在执行后才进行提交操作。

腾讯二面——MySQL:MySQL如何避免死锁?

  • 在程序中,操作多张表时,尽量以相同的顺序来访问(避免形成等待环路);
  • 批量操作单张表数据的时候,先对数据进行排序(避免形成等待环路);
  • 申请足够级别的锁,如果要操作数据,就申请排它锁;
  • 尽量使用索引访问数据,避免没有 where 条件的操作,避免锁表;
  • 如果可以,大事务化成小事务;
  • 使用等值查询而不是范围查询查询数据,命中记录,避免间隙锁对并发的影响。

腾讯二面——MySQL:如何优化MySQL的表结构?

  • 尽量将表字段定义为NOT NULL约束,这时由于在MySQL中含有空值的列很难进行查询优化,NULL值会使索引以及索引的统计信息变得很复杂。
  • 对于只包含特定类型的字段,可以使用enum、set 等数据类型。
  • 数值型字段的比较比字符串的比较效率高得多,字段类型尽量使用最小、最简单的数据类型。例如IP地址可以使用int类型。
  • 尽量使用TINYINT、SMALLINT、MEDIUM_INT作为整数类型而非INT,如果非负则加上UNSIGNED。但对整数类型指定宽度,比如INT(11),没有任何用,因为指定的类型标识范围已经确定。
  • VARCHAR的长度只分配真正需要的空间。
  • 尽量使用TIMESTAMP而非DATETIME,但TIMESTAMP只能表示1970 - 2038年,比DATETIME表示的范围小得多,而且TIMESTAMP的值因时区不同而不同。
  • 单表不要有太多字段,建议在20以内。
  • 合理的加入冗余字段可以提高查询速度。
  • 使用区分度高的字段 作为索引

美团二面——MySQL:什么是执行计划?如何理解?

MySQL中的执行计划(Execution Plan)是一种详细描述MySQL服务器如何执行特定SQL查询的方式。当你在查询语句前加上关键字EXPLAIN时,MySQL不会真正执行该查询,而是返回一个执行计划,这个计划展示了MySQL查询优化器决定的执行步骤、访问表的顺序、使用的索引以及预期的行读取数量等信息。

执行计划的主要目的是帮助开发者和DBA理解查询的工作原理,包括但不限于以下几个关键点:

  1. id: 表示执行计划中查询的各个部分的执行顺序,同一组内的ID相同则一起执行。
  2. select_type: 描述查询的类型,如SIMPLE(简单查询)、PRIMARY(主查询)、SUBQUERY(子查询)等。
  3. table: 显示查询涉及到的表。
  4. partitions: 如果表有分区,则显示计划访问的分区信息。
  5. type: 表示表连接或访问类型,例如ALL(全表扫描)、INDEX(全索引扫描)、RANGE(索引范围扫描)、REF(使用非唯一索引或唯一索引的一部分做等值或范围查询)、EQ_REF(唯一索引等值查询)、CONST(常量表,即通过主键或唯一索引直接定位一行)等。
  6. possible_keys: 列出MySQL认为可能使用到的索引。
  7. key: 实际上选择使用的索引。
  8. key_len: 表示所选索引的长度。
  9. ref: 显示哪个列或常量与key一起被用于查找索引列的值。
  10. rows: 预估MySQL为了获取查询结果需要读取的行数。
  11. filtered: 表示按照表条件过滤后,能够返回结果的比例(%)。
  12. Extra: 提供其他重要信息,如是否使用了临时表、文件排序、全索引扫描、LIMIT优化等。

通过解读执行计划,你可以发现查询性能瓶颈,识别未正确使用或缺失的索引,判断是否进行了全表扫描或其他低效操作,并据此进行针对性的SQL优化和表结构改进。

字节二面——MySQL:什么是慢查询,如何避免?

MySQL中的慢查询是指那些执行时间较长、超出一定阈值的SQL查询语句。在MySQL中,默认情况下,当一条SQL语句的执行时间超过了long_query_time变量指定的秒数时,这条查询就会被认为是“慢查询”。MySQL提供了慢查询日志功能,允许管理员记录这些慢查询以供后续分析和优化。

避免MySQL慢查询的方法主要包括:

  1. 合理创建和使用索引

    • 分析查询语句,确保在WHERE、JOIN和ORDER BY等子句中经常用到的列上创建了适当的索引。
    • 使用覆盖索引(Covering Index),索引包含了查询所需的全部数据,从而避免回表查询。
  2. 优化查询语句

    • 避免全表扫描,特别是对大数据量的表,应当利用索引来加速查询。
    • 减少JOIN操作的数量,简化查询复杂度,或者优化JOIN条件和JOIN顺序。
    • 避免在WHERE子句中使用函数或计算表达式,这通常会使索引失效。
  3. 调整数据库参数

    • 调整long_query_time参数,使之更符合实际需求,尽早捕捉潜在的慢查询。
    • 设置合理的缓存策略,如查询缓存(Query Cache,但在MySQL 8.0之后已被弃用)或结果集缓存。
  4. 合理设计表结构

    • 数据库设计时遵循规范,减少冗余和数据碎片。
    • 分区表或分表策略,将大表分成小表以分散负载。
  5. 硬件和架构优化

    • 根据负载情况提升硬件配置,比如增大内存、使用更快的磁盘设备或启用SSD。
    • 分布式数据库设计,通过水平扩展缓解单台服务器的压力。
  6. 监控和分析

    • 使用诸如EXPLAIN命令分析查询执行计划,了解MySQL是如何执行查询的。
    • 启用慢查询日志并使用专门的工具(如Percona Toolkit中的pt-query-digest)进行分析,找出问题所在并针对性优化。
  7. 代码层面优化

    • 避免在应用程序中编写复杂的嵌套循环查询,尤其是在高并发环境下。
    • 对于批量操作,尽量采用批量插入或批处理更新、删除操作,减少网络交互次数。

总之,避免MySQL慢查询需要综合运用数据库设计、SQL优化、索引策略、服务器配置调整等多种手段,并结合实际业务场景不断监测和调优。

阿里二面——MySQL:MySQL的优化可以从哪些方面考虑?

阿里二面——MySQL:为什么MySQL选择B+树作为索引?

腾讯二面——MyBatis:谈谈你对MyBatis的整体理解

字节二面——MyBatis:谈谈MyBatis和Spring整合的原理

字节二面——MyBatis:谈谈你对MyBatis中的类型转换模块的理解

字节二面——MyBatis:谈谈你对MyBatis中的反射模块的理解

字节二面——MyBatis:谈谈你对Mapper接口的设计理解

字节二面——MyBatis:谈谈你对MyBatis中的事务模块的设计理解

字节二面——MyBatis:谈谈你对MyBatis中的数据源模块的设计理解

字节二面——MyBatis:谈谈你对MyBatis中记录SQL日志的原理理解

字节二面——MyBatis:谈谈你对MyBatis中日志模块的理解

阿里二面——MyBatis:MyBatis中如何实现多个参数传递

阿里二面——MyBatis:如何调整MyBatis中的执行器的类型

阿里二面——MyBatis:谈谈你对MyBatis中的Executor的理解

阿里二面——MyBatis:当属性名和字段名称不一致的情况怎么办?

阿里二面——MyBatis:谈谈MyBatis的编程步骤是怎么样的

字节二面——MyBatis:谈谈你对传统JDBC开发和MyBatis编程的区别

字节二面——MyBatis:谈谈你对MyBatis的架构设计的理解

字节二面——MyBatis:不同的Mapper映射文件中id是否可以相同

字节二面——MyBatis:谈谈MyBatis中如何获取自增的主键

阿里二面——MyBatis:谈谈MyBatis中的Mapper接口的使用规则

阿里二面——MyBatis:谈谈你对MyBatis中的拦截器的理解

阿里二面——MyBatis:谈谈你对MyBatis中的延迟加载的理解

腾讯二面——MyBatis:在Spring中是如何解决DefaultSqlSession的数据安全问题的

阿里二面——MyBatis:谈谈你对MyBatis中的分页的理解

阿里二面——MyBatis:谈谈你对MyBatis的理解

美团二面——MyBatis:谈谈你对SqlSession的理解

阿里二面——MyBatis:谈谈你对SqlSessionFactory的理解

阿里二面——MyBatis:MyBatis中对设计模式的理解

阿里二面——MyBatis:MyBatis中如何实现缓存的扩展

腾讯二面——MyBatis:MyBatis中缓存的理解

阿里二面——MyBatis:介绍下MyBatis的工作原理

阿里二面——RocketMQ:讲一讲RocketMQ中事务回查机制的实现

字节二面——RocketMQ:讲一讲RocketMQ中的分布式事务及实现

蚂蚁二面——RocketMQ:RocketMQ的总体架构,以及每个组件的功能?

字节二面——RocketMQ:使用RocketMQ过程中遇到过什么问题?

阿里二面——RocketMQ:什么是路由剔除?RocketMQ如何进行路由剔除?

字节二面——RocketMQ:什么是路由发现?RocketMQ如何进行路由发现?

阿里二面——RocketMQ:什么是路由注册?RocketMQ如何进行路由注册?

字节二面——RocketMQ:Rocketmq中Broker的刷盘策略有哪些?

字节二面——RocketMQ:Rocketmq中Broker的部署方式

字节二面——RocketMQ:有几百万消息持续积压几小时,说说怎么解决?

腾讯二面——RocketMQ:让你来设计一个消息队列,你会怎么设计?

蚂蚁二面——RocketMQ:RocketMq性能比较高的原因?

阿里二面——RocketMQ:RocketMq的存储机制了解吗?

字节二面——RocketMQ:Rocketmq如何保证高可用性?

美团二面——RocketMQ:如何解决重复消费?

字节二面——RocketMQ:Kafka为什么那么快?

阿里二面——RocketMQ:Kafka中是怎么做到消息顺序性的?

美团二面——RocketMQ:为什么Kafka不支持读写分离?

美团二面——RocketMQ:RabbitMQ中交换器4种类型?

美团二面——RocketMQ:kafka适合哪些场景?

腾讯二面——RocketMQ:RabbitMQ开启持久化机制,有什么要注意的点?

阿里二面——RocketMQ: 说一说RabbitMQ中的AMQP

美团二面——RocketMQ:kafka中,可以不用zookeeper么?

阿里二面——RocketMQ:说一说Kafka你熟悉的参数?

腾讯二面——RocketMQ:RabbitMQ上的一个queue中存放的message是否有数量限制?

阿里二面——RocketMQ:RabbitMQ中的vhost起什么作用?

字节二面——RocketMQ:Kafka的特性

腾讯二面——RocketMQ:常见消息队列的比较

京东二面——RocketMQ:消息队列有什么优点和缺点

京东二面——RocketMQ:为什么要使用消息队列?

阿里二面——分布式:什么是Read Write Through机制

阿里二面——分布式:什么是Cache Aside机制

阿里二面——分布式:认证和授权有什么区别

阿里二面——分布式:Ribbon的原理是什么

阿里二面——分布式:什么是最大努力通知方案

阿里二面——分布式:Spring Cloud和Dubbo如何选择

阿里二面——分布式:微服务设计的原则有哪些

阿里二面——分布式:你是如何进行服务划分的

阿里二面——分布式:如何提升系统的并发能力

阿里二面——分布式:熔断和降级的区别

美团二面——分布式:分布式系统中为什么引入熔断

阿里二面——分布式:谈谈你对RESTFul风格的理解

阿里二面——分布式:请说说注册中心有哪些操作

阿里二面——分布式:请说说注册中心的数据存储结构

阿里二面——分布式:RocketMQ在分布式事务中的应用

阿里二面——分布式:什么是可靠消息最终一致性方案

阿里二面——分布式:什么是BASE理论

阿里二面——分布式:什么是CAP定理

阿里二面——分布式:数据库如何处理大数据量

阿里二面——分布式:什么是令牌桶算法

阿里二面——分布式:什么是漏桶算法

阿里二面——分布式:什么是滑动时间窗口算法

阿里二面——分布式:什么是固定时间窗口限流算法

阿里二面——分布式:常用的负载均衡算法有哪些

阿里二面——分布式:分布式id的生成方案有哪些

阿里二面——分布式:消息队列和事件表实现分布式事务

阿里二面——分布式:什么是补偿性事务

阿里二面——分布式:什么是两阶段提交协议

阿里二面——分布式:说说那你对分布式事务的理解

美团二面——分布式:分布式幂等性如何设计

百度二面——Redis: Redis过期策略都有哪些?LRU算法知道吗?

蚂蚁金服二面——Redis:什么时候选择Redis,什么时候选择Memcached?

京东二面——Redis:什么情况下可能会导致Redis阻塞?

字节跳动二面——Redis:热点数据和冷数据是什么

美团二面——Redis:Redis常见性能问题和解决方案有哪些?

美团二面——Redis:Redis集群会有写操作丢失吗?为什么?

美团二面——Redis:说一说Redis哈希槽的概念?

蚂蚁金服二面——Redis:Redis集群方案什么情况下会导致整个集群不可用?

腾讯二面——Redis:Redis集群方案应该怎么做?

腾讯二面——Redis:如何保证缓存与数据库双写时的数据一致性

阿里二面——Redis:为什么Redis需要把所有数据放到内存中?

阿里二面——Redis:Redis持久化方式有哪些?有什么区别?

字节跳动二面——Redis:怎么提高缓存命中率?

蚂蚁金服二面——Redis:Redis如何解决key冲突?

美团二面——Redis:什么是bigkey?会有什么影响?

美团二面——Redis:怎么使用Redis实现消息队列?

字节跳动二面——Redis:使用Redis如何设计分布式锁?

蚂蚁金服二面——Redis:什么是缓存雪崩?如何避免?

阿里二面——Redis:什么是缓存穿透?如何避免?

京东二面——Redis:Redis的过期策略以及内存淘汰机制?

蚂蚁金服二面——Redis:怎么理解Redis中事务?

蚂蚁金服二面——Redis:Redis与memcached相对有哪些优势?

美团二面——Redis:Redis6.0之前为什么一直不使用多线程?

蚂蚁金服二面——Redis:为什么要用Redis?

阿里二面——Redis:Redis有哪些高级功能?

美团二面——Redis:Redis6.0为什么要引入多线程?

美团二面——Redis:Redis合适的应用场景?

京东二面——Redis:Redis为什么快?

阿里一面——SpringBoot:运行SpringBoot项目的方式

阿里一面——SpringBoot:我们如何连接一个像 MySQL 或者Orcale 一样的外部数据库?

阿里一面——SpringBoot:什么是SpringBoot

阿里一面——SpringBoot:什么是 Spring Boot Starter ?

阿里二面——SpringBoot:如何重新加载Spring Boot上的更改,而无需重新启动服务器?

阿里二面——SpringBoot:如何在 Spring Boot 启动的时候运行一些特定的代码?

阿里二面——SpringBoot:如何实现SpringBoot 应用程序的安全性

阿里二面——SpringBoot:你如何理解 Spring Boot 配置加载顺序?

阿里一面——SpringBoot:介绍几个常用的starter

阿里二面——SpringBoot:SpringBoot自动装配的流程是怎样的?

阿里二面——SpringBoot:SpringBoot自动装配的核心配置文件有哪些?

阿里二面——SpringBoot:SpringBoot中如何实现定时任务

阿里二面——SpringBoot:SpringBoot中如何配置log4j

阿里二面——SpringBoot:SpringBoot如何解决跨域问题

阿里二面——SpringBoot:SpringBoot的优点

阿里二面——SpringBoot:SpringBoot的run方法做了什么事情

阿里二面——SpringBoot:SpringBoot打成的jar和普通jar有什么区别

阿里二面——SpringBoot:SpringBoot 中的监视器是什么呢

阿里二面——SpringBoot:Spring Boot、Spring MVC 和 Spring 有什么区别?

阿里二面——SpringBoot:Spring Boot 支持哪些日志框架?推荐和默认的日志框架是哪个?

阿里二面——SpringBoot:Spring Boot 有哪几种读取配置的方式

阿里二面——SpringBoot:Spring Boot 需要独立的容器运行吗?

阿里二面——SpringBoot:Spring Boot 如何定义多套不同环境配置?

阿里二面——SpringBoot:Spring Boot 可以兼容老 Spring 项目吗,如何做?

阿里二面——SpringBoot:Spring Boot 的核心注解是哪个?它主要由哪几个注解组成的?

阿里二面——SpringBoot:RequestMapping 和 GetMapping 的不同之处在哪里?

阿里二面——SpringBoot:Import注解的三种用法

阿里一面——SpringBoot:bootstrap.yml的意义

美团一面——SpringBoot:@EnableAutoConfiguration注解是干什么的?

美团一面——SpringBoot:@ComponentScan注解是干什么的?

去哪儿网二面——SpringCloud:Zuul有几种过滤器类型,分别是什么

携程二面——SpringCloud:Apollo客户端设计

携程二面——SpringCloud:Apollo配置发布后的实时推送设计

携程二面——SpringCloud:Apollo的整体架构可靠性分析

携程二面——SpringCloud:Apollo的整体架构

拼多多二面——SpringCloud:从Eureka迁移到Nacos的解决方案

拼多多二面——SpringCloud:简述Eureka集群架构

拼多多二面——SpringCloud:简述Eureka自我保护机制

美团二面——SpringCloud:简述Seata的AT模式两阶段过程

美团二面——SpringCloud:请说一下CAP和BASE理论

阿里二面——SpringCloud:分布式事务应用的典型场景

字节二面——SpringCloud:Seata中xid怎样通过Feign进行全局传递

阿里二面——SpringCloud:请简述2PC流程以及优缺点

阿里二面——SpringCloud:Seata支持那些事务模式?

美团二面——SpringCloud:在Gateway中怎样实现服务平滑迁移?

美团二面——SpringCloud:谈谈Sentienl服务熔断过程

阿里二面——SpringCloud:谈谈Sentienl中使用的限流算法

拼多多二面——SpringCloud:Feign怎样实现认证的传递?

拼多多二面——SpringCloud:Feign的性能优化?

拼多多二面——SpringCloud:Ribbon的属性配置和类配置优先级

拼多多二面——SpringCloud:Ribbon底层怎样实现不同服务的不同配置

阿里二面——SpringCloud:Nacos2.x客户端探活机制?

阿里二面——SpringCloud:Nacos配置中心配置优先级?

美团二面——SpringCloud:Nacos1.x配置中心长轮询机制?

美团二面——SpringCloud:配置中心的技术选型

美团二面——SpringCloud:Nacos中的Distro协议

美团二面——SpringCloud:Nacos服务领域模型有哪些?

阿里二面——SpringCloud:Nacos1.x作为注册中心的原理?

美团二面——SpringCloud:如何设计一个注册中心?

阿里二面——Spring:谈谈你对循环依赖的理解

头条一面——Spring:Spring中的Bean单例对象是否是线程安全的

头条一面——Spring:介绍下Spring中的依赖注入

头条一面——Spring:有哪些通知类型(Advice)

头条一面——Spring:@Component, @Controller, @Repository,@Service 有何区别

头条一面——Spring:谈谈Indexed注解的作用

头条二面——Spring:如果要对属性文件中的账号密码加密如何实现?

头条二面——Spring:谈谈SpringBoot中的bootstrap.yml文件的作用

头条二面——Spring:谈谈你对DeferredImportSelector的理解

头条二面——Spring:谈谈你对Import注解的理解

头条二面——Spring:谈谈你对SpringBoot自动装配原理的理解

头条二面——Spring:谈谈你对DelegatingFilterProxy的理解

头条二面——Spring:谈谈Spring和SpringMVC的关系

头条二面——Spring:谈谈你对SpringMVC框架的理解

头条二面——Spring:谈谈你对BeanPostProcessor的理解

头条二面——Spring:谈谈你对BeanFactoryPostProcessor的理解

头条二面——Spring:谈谈你对BeanFactory和ApplicationContext的理解

头条二面——Spring:Spring中事务的本质

头条一面——Spring:Spring中事务的实现方式

头条一面——Spring:Spring中事务的隔离级别

头条一面——Spring:Spring中事务的隔离级别介绍

头条一面——Spring:Spring中支持的作用域有几种

头条二面——Spring:Spring中Bean对象的生命周期

阿里二面——Spring:Spring中的循环依赖为什么需要三级缓存

阿里二面——Spring:Spring中是如何解决构造注入的循环依赖问题的

阿里二面——Spring:Spring中是如何解决循环依赖问题的

阿里二面——Spring:谈谈Spring中常用的注解

阿里二面——Spring:谈谈Autowired和Resource两个注解的区别

阿里二面——Spring:Spring中应用到的设计模式有哪些

百度二面——Spring:谈谈你对Spring的理解

百度二面——MySQL:MySQL内部支持缓存查询吗

这个看mysql的版本,mysql5.7是支持的,但现在8.0已经把缓存查询功能删除了。 并且 即使是mysql5.7,缓存功能也是默认关闭的。

百度二面——MySQL:说一下 MySQL 执行一条查询语句的内部执行过程

查询语句执行流程

可以看到, MySQL 的架构共分为两层:Server 层和存储引擎层

  • Server 层负责建立连接、分析和执行 SQL。MySQL 大多数的核心功能模块都在这实现,主要包括连接器,查询缓存、解析器、预处理器、优化器、执行器等。另外,所有的内置函数(如日期、时间、数学和加密函数等)和所有跨存储引擎的功能(如存储过程、触发器、视图等。)都在 Server 层实现。
  • 存储引擎层负责数据的存储和提取。支持 InnoDB、MyISAM、Memory 等多个存储引擎,不同的存储引擎共用一个 Server 层。现在最常用的存储引擎是 InnoDB,从 MySQL 5.5 版本开始, InnoDB 成为了 MySQL 的默认存储引擎。我们常说的索引数据结构,就是由存储引擎层实现的,不同的存储引擎支持的索引类型也不相同,比如 InnoDB 支持索引类型是 B+树 ,且是默认使用,也就是说在数据表中创建的主键索引和二级索引默认使用的是 B+ 树索引。

好了,现在我们对 Server 层和存储引擎层有了一个简单认识,接下来,就详细说一条 SQL 查询语句的执行流程,依次看看每一个功能模块的作用。

第一步:连接器

如果你在 Linux 操作系统里要使用 MySQL,那你第一步肯定是要先连接 MySQL 服务,然后才能执行 SQL 语句,普遍我们都是使用下面这条命令进行连接:

# -h 指定 MySQL 服务得 IP 地址,如果是连接本地的 MySQL服务,可以不用这个参数;
# -u 指定用户名,管理员角色名为 root;
# -p 指定密码,如果命令行中不填写密码(为了密码安全,建议不要在命令行写密码),就需要在交互对话里面输入密码
mysql -h $ip -u $user -p

连接的过程需要先经过 TCP 三次握手,因为 MySQL 是基于 TCP 协议进行传输的,如果 MySQL 服务并没有启动,则会收到如下的报错:

img

如果 MySQL 服务正常运行,完成 TCP 连接的建立后,连接器就要开始验证你的用户名和密码,如果用户名或密码不对,就收到一个"Access denied for user"的错误,然后客户端程序结束执行。

img

如果用户密码都没有问题,连接器就会获取该用户的权限,然后保存起来,后续该用户在此连接里的任何操作,都会基于连接开始时读到的权限进行权限逻辑的判断。

所以,如果一个用户已经建立了连接,即使管理员中途修改了该用户的权限,也不会影响已经存在连接的权限。修改完成后,只有再新建的连接才会使用新的权限设置。

如何查看 MySQL 服务被多少个客户端连接了?

如果你想知道当前 MySQL 服务被多少个客户端连接了,你可以执行 show processlist 命令进行查看。

img

比如上图的显示结果,共有两个用户名为 root 的用户连接了 MySQL 服务,其中 id 为 6 的用户的 Command 列的状态为 Sleep ,这意味着该用户连接完 MySQL 服务就没有再执行过任何命令,也就是说这是一个空闲的连接,并且空闲的时长是 736 秒( Time 列)。

空闲连接会一直占用着吗?

当然不是了,MySQL 定义了空闲连接的最大空闲时长,由 wait_timeout 参数控制的,默认值是 8 小时(28880秒),如果空闲连接超过了这个时间,连接器就会自动将它断开。

mysql> show variables like 'wait_timeout';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wait_timeout  | 28800 |
+---------------+-------+
1 row in set (0.00 sec)

当然,我们自己也可以手动断开空闲的连接,使用的是 kill connection + id 的命令。

mysql> kill connection +6;
Query OK, 0 rows affected (0.00 sec)

一个处于空闲状态的连接被服务端主动断开后,这个客户端并不会马上知道,等到客户端在发起下一个请求的时候,才会收到这样的报错“ERROR 2013 (HY000): Lost connection to MySQL server during query”。

MySQL 的连接数有限制吗?

MySQL 服务支持的最大连接数由 max_connections 参数控制,比如我的 MySQL 服务默认是 151 个,超过这个值,系统就会拒绝接下来的连接请求,并报错提示“Too many connections”。

mysql> show variables like 'max_connections';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| max_connections | 151   |
+-----------------+-------+
1 row in set (0.00 sec)

MySQL 的连接也跟 HTTP 一样,有短连接和长连接的概念,它们的区别如下:

// 短连接
连接 mysql 服务(TCP 三次握手)
执行sql
断开 mysql 服务(TCP 四次挥手)

// 长连接
连接 mysql 服务(TCP 三次握手)
执行sql
执行sql
执行sql
....
断开 mysql 服务(TCP 四次挥手)

可以看到,使用长连接的好处就是可以减少建立连接和断开连接的过程,所以一般是推荐使用长连接。

但是,使用长连接后可能会占用内存增多,因为 MySQL 在执行查询过程中临时使用内存管理连接对象,这些连接对象资源只有在连接断开时才会释放。如果长连接累计很多,将导致 MySQL 服务占用内存太大,有可能会被系统强制杀掉,这样会发生 MySQL 服务异常重启的现象。

百度二面——MySQL:说说 MySQL 的主从复制

百度二面——MySQL:什么是分库分表 什么时候进行分库分表

百度二面——MySQL:count(列名)、count(1)和 count(星号)有什么区别

count(列名)

语法:count(column_name)

count(列名) 函数返回指定列中非空值的行数。例如,如果我们有一个名为 orders 的表,并且要计算 order_id 列中非空值的总数,则可以使用以下语句

count(1)

语法:count(1)

count(1) 函数返回表中的所有行数,无论是否存在open in new window空值。例如,如果我们要计算表 orders 的行数

count(*)

语法:count(*)

count(*) 函数是一种特殊的 count() 函数,它用于计算表中的所有行数,无论这些行是否包含空值。

总结

  • count(列名) 函数返回指定列中非空值的行数。
  • count(1) 函数返回表中的所有行数,无论是否存在空值。
  • count(*) 函数用于计算表中的所有行数,无论这些行是否包含空值。

这三种用法都有各自的优缺点。如果你只需要计算特定列的行数,则可以使用 count(列名) 函数。如果你需要计算所有列的行数,则应该使用 count(1)count(*) 函数。另外,由于 count(1)count(*) 函数计算表中所有行的总数,因此它们可能比 count(列名) 函数更慢。在涉及关联查询的情况下,count(列名)count(1) 函数可能会返回不正确的结果,因为它们只考虑指定的列或行。与之相反,count(*) 函数可以正确计算关联查询中的所有行数。

阿里二面——MySQL:MySQL线上修改大表结构有哪些风险

在MySQL中,对表进行修改操作时,会自动为这张表加锁,防止其他操作干扰。如果要修改大表,需要执行长时间的锁定操作,这就会导致其他用户无法访问该表,甚至会导致整个系统崩溃。因此,在进行大表结构修改操作前,需要考虑相关的锁定问题。

解决方案:

a. 在非高峰期进行修改操作,减少影响;
b. 使用在线DDL工具,如pt-online-schema-change,避免锁表问题;

阿里二面——MySQL:MySQL的binlog有几种日志格式 分别有什么区别

MySQL的binlog(二进制日志)是MySQL用于记录数据库的更改操作的一种机制,它记录了数据库中每个被修改的数据的更改情况。MySQL的binlog有三种格式,分别是Statement格式、Row格式和Mixed格式。它们的主要区别在于记录更改操作的方式不同。

  1. Statement格式:
    • Statement格式是将每个SQL语句记录到binlog中。当执行一条修改数据的SQL语句时,比如INSERT、UPDATE、DELETE,MySQL会将这条SQL语句记录到binlog中,而不是记录具体修改了哪些行。
    • 优点:相对简单,对于某些简单的SQL语句,记录量小,性能较好。
    • 缺点:对于一些非确定性的SQL语句,比如UPDATE语句中使用了NOW()函数,可能会导致主从复制不一致;无法记录一些行级别的操作,比如在触发器中的操作。
  2. Row格式:
    • Row格式是将每一行数据的变更记录到binlog中。无论一条SQL语句修改了多少行,都会将每一行的变更记录到binlog中。
    • 优点:更加精确,可以确保主从数据库的数据一致性;能够记录所有行级别的操作,不会受到SQL语句的影响。
    • 缺点:对于一些大数据量的表,记录的binlog可能会很大;性能消耗较大,因为需要记录每一行的变更。
  3. Mixed格式:
    • Mixed格式是Statement格式和Row格式的混合使用。MySQL根据具体的情况来选择使用哪种格式。
    • 优点:综合了Statement格式和Row格式的优点,可以在保证一定性能的同时,确保数据的一致性。
    • 缺点:相比于单一格式,实现起来更加复杂;可能会出现一些情况下无法选择最佳的格式的情况。

选择binlog格式取决于具体的业务需求和性能要求。通常情况下,Row格式是保证主从复制数据一致性的最佳选择,但在某些情况下,可以考虑使用Mixed格式以综合性能和数据一致性。

阿里二面——MySQL:bin log与undo log的区别

MySQL中的binlog(二进制日志)和undo log(回滚日志)是两种不同的日志,它们的作用和机制也有所不同。

  1. binlog(二进制日志):
    • binlog是MySQL用于记录数据库中的更改操作的一种日志,它记录了对数据库执行的SQL语句或数据行的更改。
    • binlog记录的是逻辑操作,即记录的是SQL语句的逻辑内容,比如INSERT、UPDATE、DELETE等操作。
    • binlog通常用于数据复制(主从复制)、恢复、数据备份和数据同步等场景。
    • binlog是在数据库引擎层之上记录的,与具体的存储引擎无关。
  2. undo log(回滚日志):
    • undo log是MySQL中用于实现事务的原子性和隔离性的一种日志,它记录了事务执行过程中对数据的修改。
    • undo log记录的是物理操作,即记录了事务对数据的具体修改,比如某个数据页上的哪些数据被修改了。
    • undo log主要用于实现事务的回滚(rollback)操作,在事务回滚时,可以根据undo log来撤销事务的修改操作。
    • undo log是在存储引擎层面实现的,不同的存储引擎可能有不同的undo log实现方式,比如InnoDB存储引擎使用undo log来支持事务的ACID特性。

主要区别:

  • 目的不同:binlog主要用于数据的复制、备份和同步等场景,而undo log主要用于支持事务的原子性和隔离性。
  • 记录内容不同:binlog记录的是逻辑操作(SQL语句级别),而undo log记录的是物理操作(数据修改的具体内容)。
  • 存储位置不同:binlog是在数据库引擎层之上记录的,而undo log是在存储引擎层面实现的。
  • 使用场景不同:binlog通常用于数据复制、备份和同步,而undo log主要用于事务的回滚操作。

总的来说,binlog和undo log在MySQL中扮演着不同的角色,分别用于记录不同类型的操作,并支持数据库的不同功能和特性。

阿里二面——MySQL:redo log与undo log的持久化策略

百度二面——MySQL:undo log、redo log、 bin log的作用是什么

百度二面——MySQL:介绍一下MySQL的体系架构

百度二面——MySQL:说一下MySQL死锁的原因和处理方法

百度二面——MySQL:说一下MVCC内部细节

百度二面——MySQL:并发事务会产生哪些问题

滴滴二面——MySQL:InnoDB 的行锁是怎么实现的

滴滴二面——MySQL:请说一下共享锁和排他锁

滴滴二面——MySQL:请说一下数据库锁的种类

百度二面——MySQL:Repeatable Read 解决了幻读问题吗

百度二面——MySQL:MySQL 的可重复读怎么实现的

百度二面——MySQL:介绍一下MySQL中事务的特性

美团二面——MySQL:什么是覆盖索引?

美团二面——MySQL:索引哪些情况下会失效?

美团二面——MySQL:如何进行JOIN优化?

美团二面——MySQL:什么是行溢出?

美团二面——MySQL:什么是写失效?

美团二面——MySQL:InnoDB IO线程相关参数优化了解过吗

美团二面——MySQL:InnoDB日志相关的参数优化了解过吗

美团二面——MySQL:说一下InnoDB内存相关的参数优化

美团二面——MySQL:Hash索引有哪些优缺点

美团二面——MySQL:如何做慢查询优化

百度二面——MySQL:如何进行分页查询优化

百度二面——MySQL:Extra有哪些主要指标,各自的含义是什么

百度二面——MySQL:type字段中有哪些常见的值

百度二面——MySQL:explain 用过吗,有哪些主要字段

百度二面——MySQL:一个B+树中大概能存放多少条索引记录?

百度二面——MySQL:B树和B+树的区别是什么

百度二面——MySQL:InnoDB与MyISAM的区别

百度二面——MySQL:自增还是UUID 数据库主键的类型该如何选择

阿里二面——MySQL:为什么LIKE以%开头索引会失效

阿里二面——MySQL:什么是自适应哈希索引

阿里二面——MySQL:什么是索引下推?

阿里二面——MySQL:介绍一下最佳左前缀法则

阿里二面——MySQL:索引有哪几种类型?

阿里二面——MySQL:说一下聚簇索引与非聚簇索引

阿里二面——MySQL:介绍一下Page页的结构

阿里二面——MySQL:使用索引一定可以提升效率吗

阿里二面——MySQL:MySQL为什么要改进LRU算法?

阿里二面——MySQL:为什么写缓冲区 仅适用于非唯一普通索引页?

阿里二面——MySQL:InnoDB引擎如何管理Page页?

阿里二面——MySQL:什么是BufferPool?