企业面试题综合(1)

文章目录

一、BigDecimal 底层实现与数据精确性

  1. 底层实现

    • 使用 int[] val 数组存储数字的每一位。
    • int scale 表示小数点位置(如 scale=2 表示两位小数)。
    • 支持任意精度计算,避免浮点数精度丢失。
  2. 数据精确性保障

    • 避免二进制浮点数误差(如 0.1 + 0.2 != 0.3)。
    • 提供 addsubtractmultiply 等精确运算方法。
    • 可指定舍入模式(如 ROUND_HALF_UP 四舍五入)。

二、float 和 double 底层原理

  • IEEE 754 标准
    • float:32位(1符号位 + 8指数位 + 23尾数位)。
    • double:64位(1符号位 + 11指数位 + 52尾数位)。
  • 精度问题
    • 无法精确表示某些十进制小数(如 0.1)。
    • 适合科学计算,但金融场景需使用 BigDecimal

三、分布式锁实现方式

实现方式原理缺陷
Redis SET NX原子性设置键值需处理死锁、节点故障
ZooKeeper临时顺序节点依赖第三方服务
数据库乐观锁更新时判断版本号性能较低
etcd分布式一致性存储部署复杂

四、JVM 内存模型(线程共享 vs 私有)

区域是否共享说明
方法区存储类元数据、常量池(JDK8后移至元空间)
存放对象实例
虚拟机栈存储局部变量、方法调用栈
本地方法栈服务 Native 方法
程序计数器记录当前线程执行指令地址

五、JVM 调优

  1. 参数调整
    • -Xms/-Xmx:设置堆内存初始/最大值。
    • -XX:NewSize/-XX:MaxNewSize:新生代大小。
    • -XX:+UseG1GC:启用 G1 垃圾回收器。
  2. 监控工具
    • jstat:查看 GC 状态。
    • jmap:生成堆转储文件。
    • VisualVM:可视化内存和线程分析。

六、volatile 关键字

  • 特性
    • 内存可见性:写入后立即刷新到主内存。
    • 禁止指令重排序:防止编译器优化。
  • 适用场景:状态标志、DCL(双重检查锁定)。

七、JMM 内存模型与共享变量

  • JMM 模型
    • 主内存:所有线程共享的变量存储。
    • 工作内存:线程私有的缓存副本。
  • 关联关系
    • 共享变量(如 static 字段)在主内存中存储。
    • 线程操作变量需从主内存读取并写回。

八、反射获取类对象与实例

// 获取类对象
Class<?> clazz = Class.forName("com.example.MyClass");

// 获取实例
Object instance = clazz.getDeclaredConstructor().newInstance();

九、String、StringBuffer、StringBuilder 区别

类型线程安全可变性性能
String不可变最低
StringBuffer可变中等
StringBuilder可变最高

十、SQL 执行顺序与 where/having 区别

  1. 执行顺序
    FROM -> WHERE -> GROUP BY -> HAVING -> SELECT -> ORDER BY
    
  2. where vs having
    • where:过滤行(作用于原始数据)。
    • having:过滤分组(作用于聚合结果)。

十一、数据库连接类型

类型说明示例
内连接 (INNER JOIN)返回匹配行SELECT * FROM A INNER JOIN B ON A.id = B.id
左外连接 (LEFT JOIN)返回左表全量,右表匹配行SELECT * FROM A LEFT JOIN B ON A.id = B.id
右外连接 (RIGHT JOIN)返回右表全量,左表匹配行SELECT * FROM A RIGHT JOIN B ON A.id = B.id

十二、Spring 事务原理

  • 基于 AOP 实现
    • 通过 @Transactional 注解标记事务边界。
    • 底层使用 TransactionInterceptor 拦截方法调用。
  • 事务管理器PlatformTransactionManager 接口实现(如 DataSourceTransactionManager)。

十三、Redis 分布式锁缺陷

  1. 问题
    • 死锁:未设置过期时间。
    • 节点故障:主从切换导致锁失效。
  2. 改进方案
    • 使用 RedLock 算法(多节点加锁)。
    • Redisson 客户端封装分布式锁。

十四、JVM 优化参数

参数说明
-Xms初始堆内存
-Xmx最大堆内存
-XX:+UseG1GC使用 G1 垃圾回收器
-XX:MaxMetaspaceSize设置元空间最大值

十五、MVCC 核心机制

  • 多版本并发控制
    • 每个事务看到的数据快照不同(通过 Read View)。
    • 通过 undo log 保存历史版本数据。
  • 应用场景:InnoDB 引擎的可重复读隔离级别。

十六、Spring 注解注入对象

注解作用
@Component自动扫描注册 Bean
@Service标识业务层组件
@Repository标识数据访问层组件
@Configuration标识配置类
@Bean在配置类中定义 Bean

十七、线程安全问题与解决方案

  • 产生原因:多个线程同时修改共享资源。
  • 解决方式
    • 锁机制synchronizedReentrantLock
    • 原子类AtomicIntegerAtomicReference
    • 不可变对象final 字段、String

十八、== 与 equals 区别

比较方式说明
==比较对象引用地址(或基本类型值)
equals默认比较引用地址(可重写为内容比较,如 String

十九、跨域问题与解决

  • 原因:浏览器的同源策略限制。
  • 解决方式
    • CORS:服务器设置响应头(如 Access-Control-Allow-Origin)。
    • JSONP:仅支持 GET 请求。
    • Nginx 反向代理:将请求转发到同源地址。

二十、常见非检查异常

异常说明
NullPointerException空指针访问
ArrayIndexOutOfBoundsException数组越界
NumberFormatException类型转换失败
ConcurrentModificationException集合迭代时被修改

二十一、Redis Zset 使用场景

  • 典型应用
    • 排行榜(如游戏积分排名)。
    • 时间序列数据(如消息队列按时间排序)。
  • 底层结构:跳跃表 + 哈希表,支持 O(log N) 插入/查询。

二十二、订单支付后的智能推荐

  • Redis 应用
    • Zset:存储用户购买历史的评分。
    • Hash:存储商品特征标签。
    • Stream:实时推送推荐结果。

二十三、代码性能优化方向

  1. 算法优化:选择更高效的算法(如归并排序 vs 冒泡排序)。
  2. 减少 IO:批量读写、使用缓存。
  3. 并发编程:合理使用线程池、异步编排。
  4. 内存管理:避免内存泄漏、对象复用。

二十四、JDBC 与 MyBatis 流程

  1. JDBC
    • 加载驱动 → 建立连接 → 创建 Statement → 执行 SQL → 处理结果。
  2. MyBatis
    • 解析 XML/注解 → 生成 Mapper 接口 → 动态代理执行 SQL → 映射结果集。

二十五、Git 冲突解决流程

  1. 拉取最新代码git pull origin dev
  2. 解决冲突:手动编辑冲突文件(标记为 <<<<<<<, =======, >>>>>>>)。
  3. 提交合并结果git commit

二十六、HTTP 状态码分类

类别说明常见状态码
1xx信息性100 Continue
2xx成功200 OK
3xx重定向301 Moved Permanently
4xx客户端错误404 Not Found
5xx服务器错误500 Internal Server Error

二十七、TCP 与 UDP 区别

特性TCPUDP
面向连接
可靠传输
有序性
适用场景文件传输、网页浏览视频通话、DNS 查询

二十八、Spring AOP 应用场景

场景示例
日志记录方法调用日志
权限校验拦截敏感操作
事务管理控制事务边界
性能监控统计方法执行时间

二十九、常见数据结构

数据结构特点应用场景
数组连续存储,随机访问快缓存、固定大小数据
链表动态扩容,插入删除快LRU 缓存
哈希表O(1) 查找字典、缓存
二叉树层次结构文件系统、搜索树

二十九、常见数据结构(续)

数据结构特点应用场景
后进先出(LIFO)原则表达式求值和语法解析、撤销操作
队列先进先出(FIFO)原则任务调度、消息队列
完全二叉树的一种形式,分为最大堆和最小堆实现优先级队列、图算法如Dijkstra’s shortest path
节点通过边连接形成的集合社交网络分析、路由算法
Trie(前缀树)字典树,用于快速检索字符串自动完成、拼写检查
B树/B+树平衡多路搜索树,适用于磁盘存储数据库索引、文件系统

常见非检查异常

常见的非检查异常包括:

  • NullPointerException:尝试访问一个 null 对象的方法或属性。
  • ArrayIndexOutOfBoundsException:数组下标越界。
  • ArithmeticException:算术错误(如除以零)。
  • ClassCastException:类型转换错误。
  • IllegalArgumentException:非法参数。
  • NumberFormatException:字符串转换为数字时格式错误。

示例代码

public class NonCheckedExceptionExample {
    public static void main(String[] args) {
        // NullPointerException
        String str = null;
        System.out.println(str.length()); // 抛出 NullPointerException

        // ArrayIndexOutOfBoundsException
        int[] arr = {1, 2, 3};
        System.out.println(arr[3]); // 抛出 ArrayIndexOutOfBoundsException

        // ArithmeticException
        int result = 10 / 0; // 抛出 ArithmeticException
    }
}

XXL-JOB 用来做什么?

XXL-JOB 是一个分布式任务调度平台,主要用于:

  • 分布式任务管理:支持任务在多个节点上调度和执行。
  • 任务动态配置:无需重启服务即可修改任务参数。
  • 任务失败重试:支持任务失败后的重试策略。
  • 可视化界面:提供 Web 管理界面,方便监控和管理任务。

为什么选择 XXL-JOB 而不是 Spring 自带的调度

  • 分布式支持:Spring 自带的 @Scheduled 不适合分布式环境。
  • 动态扩展:XXL-JOB 支持动态添加/删除任务,而 Spring 需要重启服务。
  • 高可用性:XXL-JOB 提供任务失败重试和故障转移机制。

版本控制常用工具

常用工具

  • Git:分布式版本控制系统,支持分支管理、代码协作。
  • SVN(Subversion):集中式版本控制系统,适合中小型团队。
  • Mercurial:轻量级分布式工具,适合快速开发。
  • TFS(Team Foundation Server):微软的版本控制和项目管理工具。

Git 常用命令

  • git init:初始化仓库。
  • git add .:添加所有文件到暂存区。
  • git commit -m "message":提交更改。
  • git push:推送代码到远程仓库。
  • git pull:拉取远程仓库的最新代码。
  • git merge:合并分支。
  • git branch:管理分支。

解决冲突

  1. 使用 git merge 合并分支时,若发生冲突,Git 会标记冲突文件。
  2. 手动编辑冲突文件,保留需要的代码。
  3. 使用 git add <file> 标记冲突已解决。
  4. 最后执行 git commit 完成合并。

为什么不把登录信息存入 Cookie,而是使用 Redis?

原因

  1. 安全性:Cookie 存储在客户端,易被窃取;Redis 存储在服务端,更安全。
  2. 存储容量:Cookie 有大小限制(通常 4KB),而 Redis 可存储更大数据。
  3. 会话共享:在分布式系统中,Cookie 无法跨服务共享,而 Redis 可作为集中式会话存储。
  4. 自动续期:Redis 可通过设置过期时间(TTL)和刷新机制实现会话自动续期。

实现登录自动续期

  • 用户登录后,生成 Token 并存入 Redis,设置较短的过期时间。
  • 每次请求时,若 Token 有效,则刷新其过期时间。
  • 使用 EXPIREPEXPIRE 命令更新 Redis 中的 Token 过期时间。

数据查询慢的排查

排查步骤

  1. 查看执行计划:使用 EXPLAIN 分析 SQL 查询的执行路径。
  2. 索引优化:确保查询字段有合适的索引。
  3. 减少 JOIN:避免不必要的表连接。
  4. 分页优化:使用 LIMITOFFSET,但注意偏移量过大时的性能问题。
  5. 数据库配置:调整数据库连接池、缓存参数。
  6. 硬件资源:检查服务器 CPU、内存、磁盘 I/O 是否充足。

SQL 调优方向

  1. 索引优化
    • 添加缺失的索引。
    • 避免过度索引(索引越多,写入性能越低)。
  2. 查询优化
    • 避免 SELECT *,只查询需要的字段。
    • 使用 WHERE 子句缩小查询范围。
  3. 表结构优化
    • 拆分大表为小表(垂直分表)。
    • 使用分区表(Partitioning)。
  4. 缓存
    • 使用 Redis 缓存高频查询结果。
    • 使用数据库的查询缓存(如 MySQL 的 Query Cache)。
  5. 锁优化
    • 减少事务持有锁的时间。
    • 使用乐观锁或悲观锁策略。

什么是跨域?如何实现跨域?

跨域(Cross-Origin)是指浏览器出于安全考虑,阻止网页从一个不同源(协议、域名、端口)请求资源。

实现跨域的方法

  1. CORS(Cross-Origin Resource Sharing)

    • 在服务器响应头中添加 Access-Control-Allow-Origin
    • 支持预检请求(Preflight Request)。
    • 示例:
      Access-Control-Allow-Origin: *
      Access-Control-Allow-Methods: GET, POST
      
  2. JSONP(JSON with Padding)

    • 通过 <script> 标签加载跨域资源,但仅支持 GET 请求。
  3. 代理服务器

    • 前端请求同源的代理服务器,由代理服务器转发请求到目标服务器。

@Autowired@Resource 的区别

特性@Autowired@Resource
来源Spring 框架JSR-250 标准
注入方式按类型注入按名称注入(默认)
适用场景适用于 Spring 项目适用于 Java EE 项目
必须配合 @Component

示例

@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;

    @Resource(name = "userDao")
    private UserDao userDao;
}

#{}${} 的区别

在 MyBatis 中:

  • #{}预编译占位符,防止 SQL 注入,适用于参数绑定。
  • ${}字符串替换,直接拼接 SQL,可能导致 SQL 注入,适用于动态表名或列名。

示例

<!-- 安全:使用 #{} -->
<select id="getUser" resultType="User">
    SELECT * FROM users WHERE id = #{id}
</select>

<!-- 风险:使用 ${} -->
<select id="getUserByColumn" resultType="User">
    SELECT * FROM users WHERE ${column} = #{value}
</select>

乐观锁和悲观锁

乐观锁

  • 假设数据不会冲突,提交时检查版本号或时间戳。
  • 适用于读多写少的场景。
  • 实现方式:使用版本号(version 字段)或时间戳。

悲观锁

  • 假设数据会冲突,操作前加锁。
  • 适用于写多读少的场景。
  • 实现方式:使用 SELECT ... FOR UPDATE 或数据库锁机制。

示例(乐观锁):

UPDATE users SET balance = balance - 100, version = version + 1 
WHERE id = 1 AND version = #{version};

Redis 实现分布式锁及缺陷

实现方式

  1. SETNX 命令

    SETNX lock_key 1
    
    • 如果 lock_key 不存在,则设置成功,表示获取锁。
  2. RedLock 算法

    • 在多个 Redis 实例上尝试加锁,确保一致性。

缺陷

  • 网络分区:如果 Redis 节点不可达,可能无法释放锁。
  • 死锁:如果客户端异常退出,锁未释放。
  • 性能开销:频繁的锁操作可能影响性能。

改进方案

  • 使用 Redisson 等客户端库,自动处理锁的续期和释放。
  • 设置合理的锁过期时间(TTL)。

数据库三大范式

  1. 第一范式(1NF)

    • 属性不可再分。
    • 示例:拆分 address 字段为 street, city, state
  2. 第二范式(2NF)

    • 在 1NF 基础上,消除部分依赖。
    • 要求所有非主属性完全依赖主键。
  3. 第三范式(3NF)

    • 在 2NF 基础上,消除传递依赖。
    • 非主属性之间不能相互依赖。

JVM 优化参数

常用参数

  • 堆内存
    • -Xms:初始堆大小。
    • -Xmx:最大堆大小。
  • 新生代
    • -Xmn:新生代大小。
    • -XX:SurvivorRatio:Eden 区与 Survivor 区的比例。
  • GC 策略
    • -XX:+UseG1GC:启用 G1 垃圾收集器。
    • -XX:+UseParallelGC:启用并行垃圾收集器。

示例

java -Xms512m -Xmx2g -XX:+UseG1GC -jar myapp.jar

索引失效场景

  1. 全模糊查询

    SELECT * FROM users WHERE name LIKE '%Tom%';
    
  2. 类型不匹配

    SELECT * FROM users WHERE id = '1'; -- id 是整数
    
  3. 使用函数

    SELECT * FROM users WHERE YEAR(create_time) = 2023;
    
  4. OR 条件

    SELECT * FROM users WHERE id = 1 OR name = 'Tom';
    

CAS(比较与交换)

原理
CAS 是一种无锁算法,通过比较当前值与预期值,若相等则更新为新值。

Java 中的实现

AtomicInteger atomicInt = new AtomicInteger(0);
int expectedValue = atomicInt.get();
boolean success = atomicInt.compareAndSet(expectedValue, expectedValue + 1);

优点

  • 避免线程阻塞,提高并发性能。
  • 适用于低竞争场景。

缺点

  • ABA 问题:值被修改后又改回原值,CAS 会误判。
  • 高竞争场景下,CAS 可能导致循环开销。

Nacos 配置文件存储位置

Nacos 配置存储

  1. 本地文件

    • 默认存储在 conf 目录下的 application.properties 文件中。
  2. 数据库

    • 可配置使用 MySQL 存储配置信息,需在 application.properties 中指定数据库连接。
  3. 云存储

    • 支持与阿里云、AWS 等云服务集成,存储配置信息。

事务的隔离级别

隔离级别描述问题
Read Uncommitted允许读取未提交的数据脏读
Read Committed只能读取已提交的数据不可重复读
Repeatable Read确保多次读取结果一致幻读
Serializable完全隔离,性能最差无并发问题

Redis Zset 的使用场景

Zset(有序集合) 是 Redis 提供的一种数据结构,支持按分数排序。

应用场景

  1. 排行榜

    ZADD leaderboard 100 user1
    ZRANGE leaderboard 0 -1 WITHSCORES
    
  2. 延迟队列

    • 使用 ZRANGEBYSCORE 获取超时任务。
  3. 去重计数

    • 结合 ZCARD 统计唯一用户。

缓存雪崩、击穿、穿透

  1. 缓存雪崩

    • 现象:大量缓存同时失效,导致数据库压力激增。
    • 解决方案
      • 随机过期时间。
      • 热点数据永不过期。
  2. 缓存击穿

    • 现象:某个热点 Key 失效,大量请求直接访问数据库。
    • 解决方案
      • 使用互斥锁(Mutex)。
      • 使用空值缓存。
  3. 缓存穿透

    • 现象:请求的 Key 不存在,直接访问数据库。
    • 解决方案
      • 使用布隆过滤器(Bloom Filter)。
      • 缓存空值。

开发文档维护与保存

维护方式

  1. 工具

    • Swagger:自动生成 API 文档。
    • Markdown:编写技术文档。
    • GitBook:构建在线文档。
  2. 版本控制

    • 将文档纳入 Git 管理,确保历史版本可追溯。
    • 使用分支管理文档的开发和发布。
  3. 存储

    • 私有仓库:使用 GitLab、GitHub Enterprise 存储敏感文档。
    • 云存储:使用 Notion、Confluence 等在线文档工具。

登录自动续期实现

实现步骤

  1. 生成 Token

    • 用户登录后生成 JWT 或 UUID 作为 Token。
    • 设置较短的过期时间(如 30 分钟)。
  2. 刷新 Token

    • 每次请求时,若 Token 有效,则生成新的 Token 并更新 Redis 中的过期时间。
  3. 存储 Token

    • 使用 Redis 存储 Token,设置 TTL(Time To Live)。

代码示例

public String refreshToken(String oldToken) {
    String newToken = UUID.randomUUID().toString();
    redisTemplate.opsForValue().set("token:" + newToken, "user123", 30, TimeUnit.MINUTES);
    return newToken;
}

为什么要使用线程池和 CompletableFuture 异步编排

线程池

  • 优点
    • 提高资源利用率,避免频繁创建和销毁线程。
    • 控制并发线程数,防止资源耗尽。
  • 核心参数
    • corePoolSize:核心线程数。
    • maxPoolSize:最大线程数。
    • keepAliveTime:空闲线程存活时间。
    • workQueue:任务队列。

CompletableFuture

  • 优点
    • 支持异步编排,简化多线程任务的组合。
    • 提供 thenApplythenAcceptthenRun 等方法链式调用。
  • 示例
    CompletableFuture.supplyAsync(() -> "Hello")
        .thenApply(s -> s + " World")
        .thenAccept(System.out::println);
    

JVM 内存结构

内存区域

  1. 堆(Heap)

    • 存储对象实例和数组。
    • 分为年轻代(Young Generation)和老年代(Old Generation)。
  2. 栈(Stack)

    • 存储局部变量和方法调用。
    • 每个线程私有。
  3. 方法区(Metaspace)

    • 存储类信息、常量池、静态变量。
    • Java 8 以后使用 Metaspace 替代永久代(PermGen)。
  4. 程序计数器

    • 记录当前线程执行的字节码行号。

左连接(LEFT JOIN)查询

定义
左连接返回左表的所有记录,即使右表没有匹配的行。

示例

SELECT users.id, orders.amount
FROM users
LEFT JOIN orders ON users.id = orders.user_id;

查询事务隔离级别

SELECT @@transaction_isolation;

Spring 常用注解(Controller 层)

注解作用
@RestController标记为 RESTful 控制器,返回值直接写入 HTTP 响应体。
@RequestMapping映射 HTTP 请求到方法。
@GetMapping / @PostMapping映射 GET/POST 请求。
@PathVariable从 URL 中提取变量。
@RequestBody接收 JSON/XML 请求体。
@RequestParam从查询参数中获取值。
@Autowired自动注入依赖。

多线程工作原理

线程生命周期

  1. 新建(New):创建线程对象。
  2. 就绪(Runnable):等待 CPU 调度。
  3. 运行(Running):执行 run() 方法。
  4. 阻塞(Blocked):等待资源(如锁)。
  5. 终止(Terminated):执行完毕或异常退出。

上下文切换

  • 当线程阻塞或时间片用尽时,CPU 会切换到其他线程,保存当前线程的状态,并恢复下一个线程的状态。

Git 常用命令及冲突解决

常用命令

  • git clone <url>:克隆远程仓库。
  • git add .:添加所有修改到暂存区。
  • git commit -m "message":提交更改。
  • git push:推送代码到远程仓库。
  • git pull:拉取远程仓库的最新代码。
  • git branch:查看分支。
  • git checkout -b <branch>:创建并切换分支。
  • git merge <branch>:合并分支。

解决冲突

  1. 执行 git merge 后,Git 会标记冲突文件。
  2. 打开冲突文件,找到 <<<<<<<, =======, >>>>>>> 标记。
  3. 手动选择保留的代码。
  4. 使用 git add <file> 标记冲突已解决。
  5. 最后执行 git commit 完成合并。

Docker 打包和运行 JAR 镜像

步骤

  1. 编写 Dockerfile

    FROM openjdk:8-jdk-alpine
    COPY myapp.jar app.jar
    ENTRYPOINT ["java", "-jar", "/app.jar"]
    
  2. 构建镜像

    docker build -t myapp .
    
  3. 运行容器

    docker run -d -p 8080:8080 myapp
    

对 Docker 容器做存储

  • 数据卷(Volume)

    docker run -v /host/path:/container/path myapp
    
  • 绑定挂载(Bind Mount)

    docker run -v /host/path:/container/path myapp
    

Nginx 的作用及负载均衡

Nginx 的作用

  1. 反向代理:将客户端请求转发到后端服务器。
  2. 负载均衡:将流量分配到多个后端服务器。
  3. 静态资源服务:高效提供静态文件(HTML、CSS、JS)。
  4. 限流和缓存:限制请求频率,缓存响应内容。

负载均衡配置示例

upstream backend {
    server 192.168.1.101:8080;
    server 192.168.1.102:8080;
    server 192.168.1.103:8080;
}

server {
    listen 80;
    location / {
        proxy_pass http://backend;
    }
}

百万级表连表查询优化

优化策略

  1. 索引优化

    • 为主键和外键添加索引。
    • 使用复合索引覆盖查询条件。
  2. 分页处理

    • 使用 LIMITOFFSET,但注意偏移量过大时的性能问题。
    • 使用游标分页(Cursor-based Pagination)。
  3. 缓存

    • 使用 Redis 缓存高频查询结果。
    • 使用数据库的查询缓存(如 MySQL 的 Query Cache)。
  4. 数据库分片

    • 将大表水平拆分到多个数据库实例中。
  5. 减少 JOIN

    • 避免不必要的表连接,或使用物化视图。

RabbitMQ 的优点和缺点

优点

  • 高可用性:支持集群部署,确保消息不丢失。
  • 消息持久化:消息可持久化到磁盘,避免重启丢失。
  • 灵活的路由:支持多种消息模式(Direct、Topic、Fanout)。
  • 分布式系统解耦:生产者和消费者无需直接通信。

缺点

  • 性能瓶颈:在高吞吐量场景下,可能成为性能瓶颈。
  • 消息堆积:消费者处理速度慢时,可能导致消息堆积。
  • 运维复杂度:需要维护 RabbitMQ 集群和监控系统。

主要作用

  • 异步处理:解耦生产者和消费者。
  • 流量削峰:平滑突发流量。
  • 消息广播:向多个消费者发送消息。

Oracle 与 MySQL 的区别

特性OracleMySQL
事务处理支持 ACID,适合金融系统支持 ACID,但默认引擎 InnoDB
锁机制更复杂的锁粒度(行锁、表锁)行锁为主
性能高性能,适合大型企业应用轻量级,适合中小型应用
查询语法支持 PL/SQL,语法复杂支持标准 SQL,语法简单
存储过程强大的存储过程支持有限的存储过程支持

查询区别

  • 分页

    • Oracle:使用 ROWNUM
    • MySQL:使用 LIMIT
  • 字符串连接

    • Oracle:使用 ||
    • MySQL:使用 CONCAT()

前端技术配合调试

定位前端错误的步骤

  1. 查看控制台(Console)

    • 检查报错信息(如 Uncaught TypeError)。
    • 查看网络请求(Network Tab)。
  2. 使用断点调试

    • 在 Chrome DevTools 中设置断点,逐步执行代码。
  3. 检查网络请求

    • 查看请求的 URL、参数、响应状态码。
    • 检查 CORS 错误或 404/500 错误。
  4. 代码审查

    • 检查 JavaScript 语法错误。
    • 检查 HTML/CSS 是否正确嵌套。

static 关键字

可以修饰的对象

  1. 变量:类变量,属于类,所有实例共享。
  2. 方法:类方法,可以直接通过类名调用。
  3. 代码块:静态代码块,用于初始化类。
  4. 内部类:静态内部类,不依赖外部类实例。

特性

  • 静态变量:在类加载时初始化,生命周期与类相同。
  • 静态方法:不能访问非静态成员,不能使用 this
  • 静态代码块:只执行一次,用于初始化静态资源。

示例

public class Example {
    static int count = 0;

    static {
        System.out.println("Static block executed");
    }

    public static void main(String[] args) {
        System.out.println(count);
    }
}

对集合的理解

Java 集合框架

类型接口实现类特点
ListListArrayList, LinkedList有序,允许重复
SetSetHashSet, TreeSet无序,不允许重复
MapMapHashMap, TreeMap键值对,键唯一

线程安全集合

  • ConcurrentHashMap:线程安全的 HashMap。
  • CopyOnWriteArrayList:线程安全的 List,适合读多写少的场景。

线程池的核心参数和工作原理

核心参数

  1. corePoolSize:核心线程数。
  2. maximumPoolSize:最大线程数。
  3. keepAliveTime:空闲线程存活时间。
  4. workQueue:任务队列。
  5. threadFactory:线程工厂。
  6. handler:拒绝策略。

工作原理

  1. 提交任务
    • 如果线程数 < corePoolSize,创建新线程。
    • 如果线程数 >= corePoolSize 且队列未满,将任务加入队列。
    • 如果队列满且线程数 < maximumPoolSize,创建新线程。
    • 如果队列满且线程数 >= maximumPoolSize,执行拒绝策略。

线程安全性

  • 线程池本身是线程安全的,但任务中的共享资源需要手动同步。

多线程实现方式

  1. 继承 Thread

    public class MyThread extends Thread {
        public void run() {
            System.out.println("Thread running");
        }
    }
    
  2. 实现 Runnable 接口

    public class MyRunnable implements Runnable {
        public void run() {
            System.out.println("Runnable running");
        }
    }
    
  3. 使用 CallableFuture

    public class MyCallable implements Callable<String> {
        public String call() {
            return "Result";
        }
    }
    

synchronizedReentrantLock 的区别

特性synchronizedReentrantLock
可重入性支持支持
公平性不支持支持(可选)
条件变量不支持支持(Condition
中断响应不支持支持(tryLock()
性能低竞争下性能较好高竞争下性能更好

示例

// synchronized
synchronized (this) {
    // critical section
}

// ReentrantLock
ReentrantLock lock = new ReentrantLock();
lock.lock();
try {
    // critical section
} finally {
    lock.unlock();
}

MyBatis 大致流程

  1. 加载配置

    • 读取 mybatis-config.xml 和映射文件。
    • 构建 SqlSessionFactory
  2. 创建会话

    • 通过 SqlSessionFactory 创建 SqlSession
    • SqlSession 提供数据库操作方法(select, insert 等)。
  3. 执行 SQL

    • 根据 Mapper 接口或 XML 映射文件生成 SQL。
    • 参数绑定和结果映射。
  4. 返回结果

    • 将数据库结果集映射为 Java 对象。

charvarchar 的区别

类型存储方式空间占用适用场景
char(n)定长始终占用 n 个字符空间固定长度字符串,如性别
varchar(n)变长实际存储长度 + 1~2 字节可变长度字符串,如用户名

临时表

临时表 是数据库中用于临时存储中间结果的表,通常在会话结束后自动删除。

使用场景

  1. 复杂查询

    • 将中间结果存储在临时表中,简化复杂查询。
    • 示例:
      CREATE TEMPORARY TABLE temp_users AS SELECT * FROM users WHERE status = 'active';
      
  2. 性能优化

    • 对临时表进行索引优化,提高查询性能。

Linux 常见命令

命令功能
ls列出目录内容
cd切换目录
mkdir创建目录
rm删除文件或目录
cp复制文件
mv移动或重命名文件
ps查看进程
top实时监控系统资源
grep查找文本
find查找文件

Spring 注解放入 IOC 容器

常用注解

注解作用
@Component通用组件注解
@Service标记为业务层组件
@Repository标记为数据访问层组件
@Controller标记为控制层组件
@Configuration标记为配置类
@Bean在配置类中定义 Bean

MyBatis 缓存问题

一级缓存

  • 范围SqlSession 级别。
  • 特点:默认开启,缓存查询结果,避免重复查询。

二级缓存

  • 范围Mapper 级别。
  • 特点:需要手动配置,适合读多写少的场景。

问题

  • 数据一致性:缓存可能导致数据不一致。
  • 内存占用:缓存数据过多可能导致内存溢出。

100 万个字符串查找

推荐数据结构

  1. 哈希表(HashMap)

    • 时间复杂度 O(1),适合查找和插入。
    • 适用于无序数据。
  2. Trie 树

    • 适合前缀匹配和字符串查找。
    • 适用于自动补全、拼写检查。
  3. 布隆过滤器(Bloom Filter)

    • 用于判断元素是否存在于集合中。
    • 优点:空间效率高,查询速度快。
    • 缺点:存在误判率。

Lua 脚本在 Redis 中的作用

作用

  1. 原子操作

    • Lua 脚本在 Redis 中是原子执行的,避免竞态条件。
  2. 复杂逻辑

    • 实现复杂的业务逻辑,如分布式锁、计数器。

示例

-- 实现计数器
local current = redis.call("GET", KEYS[1])
if current then
    current = tonumber(current)
    current = current + 1
    redis.call("SET", KEYS[1], current)
    return current
else
    redis.call("SET", KEYS[1], 1)
    return 1
end

Redis Hash 在项目中的用法

应用场景

  1. 存储对象

    • 将用户信息存储为 Hash,字段对应属性。
    • 示例:
      HSET user:1001 name "Alice" age 25
      
  2. 减少内存占用

    • Hash 结构比多个 String 更节省内存。
  3. 批量操作

    • 使用 HMSETHMGET 批量设置和获取字段。

MyBatis 不用 #{} 防止 SQL 注入

方法

  1. 使用拦截器(Interceptor)

    • 自定义拦截器,过滤 SQL 中的危险字符。
  2. 使用 AOP

    • 在 Service 层使用 AOP 拦截 SQL 参数,进行合法性校验。
  3. 白名单校验

    • 对输入参数进行白名单校验,拒绝非法字符。

SQL 调优案例

案例 1:添加索引

  • 问题:查询用户表时,WHERE username = 'Tom' 很慢。
  • 优化:为 username 字段添加索引。

案例 2:减少 JOIN

  • 问题:查询涉及多个表连接,导致性能下降。
  • 优化:将部分数据冗余到主表,减少 JOIN。

案例 3:分页优化

  • 问题:分页查询时,LIMIT 10000, 10 很慢。
  • 优化:使用游标分页(Cursor-based Pagination)。

# 技术问题整理笔记

## Java实现阻塞队列
- **核心实现**:基于数组或链表的循环队列,结合线程同步机制(如`ReentrantLock`和`Condition`)。
- **关键组件**:
  - 数组/链表存储元素
  - `head`和`tail`指针管理队列头尾
  - `count`计数器记录队列大小
- **线程安全**:
  - 使用`put`和`take`方法实现阻塞操作
  - `ArrayBlockingQueue`通过`ReentrantLock`控制并发,支持公平锁
- **示例代码**(伪代码):
  ```java
  public class MyBlockingQueue<T> {
      private final T[] items;
      private int head, tail, count;
      private final ReentrantLock lock = new ReentrantLock();
      private final Condition notEmpty = lock.newCondition();
      private final Condition notFull = lock.newCondition();

      public MyBlockingQueue(int capacity) {
          items = (T[]) new Object[capacity];
      }

      public void put(T elem) throws InterruptedException {
          lock.lock();
          try {
              while (count == items.length) {
                  notFull.await();
              }
              items[tail] = elem;
              tail = (tail + 1) % items.length;
              count++;
              notEmpty.signal();
          } finally {
              lock.unlock();
          }
      }

      public T take() throws InterruptedException {
          lock.lock();
          try {
              while (count == 0) {
                  notEmpty.await();
              }
              T elem = items[head];
              items[head] = null;
              head = (head + 1) % items.length;
              count--;
              notFull.signal();
              return elem;
          } finally {
              lock.unlock();
          }
      }
  }

数组快速排序

  • PHP实现
    function quickSort($arr) {
        if (count($arr) <= 1) return $arr;
        $pivot = $arr[0];
        $left = $right = [];
        for ($i = 1; $i < count($arr); $i++) {
            if ($arr[$i] < $pivot) $left[] = $arr[$i];
            else $right[] = $arr[$i];
        }
        return array_merge(quickSort($left), [$pivot], quickSort($right));
    }
    
  • 优化策略
    • 随机选择pivot(避免最坏情况O(n²))
    • 三数取中法
    • 小数组切换插入排序

T1/T2/T3线程顺序执行

  • 解决方案
    1. 使用join()
      Thread t1 = new Thread(() -> System.out.println("T1"));
      Thread t2 = new Thread(() -> {
          try { t1.join(); } catch (InterruptedException e) {}
          System.out.println("T2");
      });
      Thread t3 = new Thread(() -> {
          try { t2.join(); } catch (InterruptedException e) {}
          System.out.println("T3");
      });
      t3.start(); t2.start(); t1.start();
      
    2. 使用CountDownLatch
      CountDownLatch latch1 = new CountDownLatch(1), latch2 = new CountDownLatch(1);
      Thread t1 = new Thread(() -> {
          System.out.println("T1");
          latch1.countDown();
      });
      Thread t2 = new Thread(() -> {
          try { latch1.await(); } catch (InterruptedException e) {}
          System.out.println("T2");
          latch2.countDown();
      });
      Thread t3 = new Thread(() -> {
          try { latch2.await(); } catch (InterruptedException e) {}
          System.out.println("T3");
      });
      t1.start(); t2.start(); t3.start();
      

Redis与数据库一致性

  • 常见策略
    1. 双写策略:先更新数据库,再更新缓存
    2. 失效策略:更新数据库后删除缓存
    3. 延迟双删:更新数据库后删除缓存,再延迟一段时间再次删除
    4. Canal客户端
      • 原理:监听MySQL binlog,捕获数据变更事件
      • 实现步骤:
        1. 配置MySQL开启binlog
        2. 启动Canal服务,解析binlog生成JSON数据
        3. 客户端订阅Canal数据,更新Redis和数据库

AOP切面应用场景

  • 典型场景
    • 日志记录(请求参数、执行时间)
    • 权限校验(接口访问控制)
    • 事务管理(方法级事务回滚)
    • 性能监控(方法耗时统计)
    • 缓存管理(读取/更新缓存)

策略模式 vs 工厂模式

  • 策略模式
    • 用途:动态替换算法(如支付策略、排序策略)
    • 结构:定义策略接口 + 多个实现类 + 上下文类
  • 工厂模式
    • 用途:解耦对象创建(如数据库连接池)
    • 结构:定义工厂接口 + 具体工厂类 + 产品接口/实现

Seata AT模式

  • 核心流程
    1. 一阶段(本地事务):
      • 执行业务SQL,生成分支事务日志(undo log)
    2. 二阶段(全局提交/回滚):
      • 提交:直接提交本地事务
      • 回滚:根据undo log逆向执行SQL

异常与错误区别

  • 异常(Exception)
    • 可捕获处理(如IOException, NullPointerException
    • 分类:
      • Checked异常(编译时检查,如IOException
      • Unchecked异常(运行时异常,如ArrayIndexOutOfBoundsException
  • 错误(Error)
    • 不可恢复(如OutOfMemoryError, StackOverflowError

MongoDB vs Redis

  • MongoDB
    • 用途:文档型数据库,适合存储复杂结构数据(如JSON)
    • 优势:灵活的Schema、水平扩展、支持聚合查询
  • Redis
    • 用途:内存缓存,适合高频读写场景(如计数器、Session存储)

LRU缓存淘汰策略

  • 实现原理
    • 维护一个双向链表(记录访问顺序) + 哈希表(快速查找)
    • 操作
      • get:访问元素时移动到链表头部
      • put:插入新元素时,若超出容量则删除链表尾部元素
  • 阈值设置
    • 根据业务需求动态调整(如设置缓存最大容量为内存的50%)

分布式锁实现

  • 常用方案
    1. Redis
      • 使用SETNX命令 + 过期时间
      • 示例:SET key value NX PX 3000
    2. Zookeeper
      • 创建临时顺序节点,最小节点获取锁
    3. 数据库
      • 通过唯一索引实现锁表

适合存入Redis的数据

  • 高频读写:Session、Token、计数器
  • 低一致性要求:缓存数据(如商品详情)
  • 结构化数据:Hash、List(如消息队列)
  • 临时数据:验证码、限时活动

G1垃圾回收算法

  • 特点
    • 并行与并发收集
    • 区域划分(Region)
    • 优先回收垃圾最多的区域
  • 参数设置
    • -XX:+UseG1GC启用G1
    • -XX:MaxGCPauseMillis=200设置最大停顿时间

CPU飙升排查

  • 常见原因
    1. 死循环或递归
    2. 高并发竞争锁
    3. 频繁GC
    4. 正则表达式失控
  • 排查工具
    • top/htop定位进程
    • jstack查看线程堆栈
    • perf分析CPU占用

OOM排查

  • 步骤
    1. 使用jstat -gc查看堆内存状态
    2. 生成堆转储文件:jmap -dump:file=heap.bin <pid>
    3. 使用MAT工具分析堆内存泄漏

事务传播行为

  • 常见配置
    • @Transactional(propagation = Propagation.REQUIRED):默认,加入现有事务
    • @Transactional(propagation = Propagation.REQUIRES_NEW):新建事务
    • @Transactional(propagation = Propagation.NEVER):禁止事务

事务失效场景

  • 原因
    1. 方法未被Spring代理(如私有方法)
    2. 数据库引擎不支持事务(如MyISAM)
    3. 抛出非运行时异常(需手动回滚)
    4. 多线程中调用事务方法

获取类注解

  • Java代码
    AnnotatedElement element = ...; // 类/方法/字段对象
    MyAnnotation annotation = element.getAnnotation(MyAnnotation.class);
    if (annotation != null) {
        // 处理注解
    }
    

Linux后台进程命令

  • 获取后台进程
    ps aux | grep <process_name>
    jps -l # 查看Java进程
    

查找并删除文件

  • 命令
    find /path/to/dir -name "*.log" -exec rm -f {} \;
    

运行Java程序并设置内存

  • 命令
    java -Xms512m -Xmx2g -XX:NewSize=256m -XX:MaxNewSize=512m -jar app.jar
    

1. 不使用同步锁共享变量

  • 无锁编程:通过原子操作(如CAS)或双buffer设计实现线程安全。
    • 原子操作:使用std::atomic(C++)或AtomicInteger(Java)避免锁。
    • CAS(Compare-And-Swap):通过硬件指令实现无锁队列等数据结构。
    • 双buffer设计(适用于一写多读场景):
      • 使用两个指针(ptrbak_ptr)指向主数据和备份数据。
      • 写线程更新备份数据后,交换指针完成更新,避免读写冲突。

2. Spring Cloud 常用组件

  • 核心组件
    1. Spring Cloud Config:集中式配置管理。
    2. Spring Cloud Discovery(如 Eureka、Consul):服务发现与注册。
    3. Spring Cloud Gateway:API网关,路由与负载均衡。
    4. Spring Cloud Load Balancer:客户端负载均衡。
    5. Spring Cloud Circuit Breaker(如 Hystrix):断路器,防止雪崩。
    6. Spring Cloud Sleuth:分布式链路追踪。
    7. Spring Cloud Stream:消息驱动微服务(支持 Kafka、RabbitMQ)。
    8. Spring Cloud Task:短暂任务的调度与监控。

3. @Transactional 注解及事务使用

  • 事务注解属性
    • propagation:事务传播行为(如 REQUIRED, REQUIRES_NEW)。
    • isolation:事务隔离级别(如 READ_COMMITTED, REPEATABLE_READ)。
    • timeout:超时时间(秒)。
    • rollbackFor:指定回滚的异常类型。
  • 事务传播行为
    • REQUIRED(默认):如果存在事务则加入,否则新建。
    • REQUIRES_NEW:总是新建事务,挂起当前事务(若有)。
    • SUPPORTS:有事务则加入,无事务则非事务执行。
    • NEVER:禁止事务执行,若存在事务则抛异常。

4. Redis 实现签到功能

  • 数据类型:使用 BitMap(基于 Redis 的 String 类型实现)。
  • 实现步骤
    1. 按月存储:以 userId:yyyyMM 为 Key。
    2. 签到操作
      • SETBIT key dayOfMonth-1 1:标记某天签到。
      • GETBIT key dayOfMonth-1:查询某天是否签到。
    3. 统计签到天数
      • BITCOUNT key:统计当月签到次数。

5. Spring 线程池参数

  • 核心参数
    1. corePoolSize:核心线程数(长期存活线程)。
      • 设置依据:CPU密集型任务设为 CPU 核心数;I/O 密集型任务设为 CPU 核心数 × 2。
    2. maxPoolSize:最大线程数。
      • 设置依据:通常为核心线程数的 2~3 倍,避免资源耗尽。
    3. queueCapacity:任务队列容量。
      • 设置依据:根据系统负载调整,有界队列可防止内存溢出。
    4. keepAliveSeconds:非核心线程空闲存活时间(建议 60~120 秒)。
  • 队列触发条件
    • 当线程池中线程数 < corePoolSize,新任务直接分配线程。
    • 当线程数 >= corePoolSize 且队列未满,任务入队。
    • 当队列满且线程数 < maxPoolSize,创建新线程。
    • 当队列满且线程数 >= maxPoolSize,触发拒绝策略。

6. CompletableFuture 与线程池的区别

  • CompletableFuture
    • 基于 Future 的扩展,支持链式调用和异步编排。
    • 更适合处理 异步任务依赖(如多个异步任务的结果组合)。
  • 线程池
    • 用于 资源管理,控制线程的创建和复用。
    • 更适合 批量任务调度(如固定任务分发)。

7. 为什么要使用 CompletableFuture

  • 优势
    1. 异步编排:通过 thenApplythenCompose 等方法实现任务链式处理。
    2. 异常处理:支持统一的异常捕获和处理。
    3. 多任务聚合:通过 allOfanyOf 处理多个异步结果。
    4. 减少阻塞:避免线程阻塞等待任务完成。

8. RabbitMQ 的几种模式

  1. 简单队列模式:生产者 → 队列 → 消费者(一对一)。
  2. 工作队列模式:多个消费者竞争消费队列消息。
  3. 发布/订阅模式:生产者 → 交换机(广播)→ 多个队列 → 消费者。
  4. 路由模式:通过路由键(Routing Key)绑定队列。
  5. 主题模式:基于通配符匹配路由键(如 *.error)。

9. 布隆过滤器初始容量设置

  • 初始容量:建议设置为 数据量的 1.5~2 倍,避免误判率过高。
  • 误判率:通常设置为 0.1%~1%,具体值取决于哈希函数数量和位数组长度。

10. 分布式事务实现方式

  • 常见方案
    1. 两阶段提交(2PC):协调者 + 参与者,保证原子性。
    2. TCC(Try-Confirm-Cancel):业务层面补偿事务。
    3. Saga 模式:通过本地事务和补偿操作实现最终一致性。
    4. Seata:开源分布式事务框架,支持 AT、TCC、SAGA 模式。

11. 未知类型对象互相转换

  • 解决方案
    1. 反射机制:通过 Class 对象动态获取属性并赋值。
    2. Spring BeanCopier
      BeanCopier copier = BeanCopier.create(Source.class, Target.class, false);
      Target target = new Target();
      copier.copy(source, target, null);
      
    3. Jackson/Gson:通过 JSON 序列化反序列化实现转换。

12. HashMap 扩容机制

  • 扩容触发条件
    • size > threshold(容量 × 负载因子,默认 0.75)时触发扩容。
  • 扩容过程
    1. 创建新的数组(容量为原容量的 2 倍)。
    2. 重新计算每个键值对的哈希桶位置。
    3. 将旧数组的元素迁移至新数组。

13. 多线程中子线程无法获取主线程 ID

  • 解决方案
    1. InheritableThreadLocal:主线程设置值,子线程继承。
      ThreadLocal<String> threadLocal = new InheritableThreadLocal<>();
      threadLocal.set("mainThreadId");
      
    2. 显式传递参数:在启动子线程时,将主线程 ID 作为参数传入。

14. 内存泄漏定位与解决

  • 定位方法
    1. 工具分析:使用 MAT(Memory Analyzer)、JProfiler 等工具分析堆内存。
    2. 日志跟踪:通过 GC 日志定位内存增长点。
  • 常见原因
    • 长生命周期对象持有短生命周期对象引用。
    • 未关闭的资源(如数据库连接、缓存未清理)。
  • 解决方法
    • 显式释放资源。
    • 使用弱引用(WeakReference)或软引用(SoftReference)。

15. MinIO 的优点与分布式特性

  • 优点
    • 高性能:基于 HTTP/2 的对象存储服务。
    • 兼容 S3 API:支持 AWS S3 协议。
    • 轻量部署:单节点部署或分布式集群。
  • 是否分布式,支持多节点分布式部署,提供高可用性。

16. 相同表结构复制数据到新表

  • SQL 语句
    INSERT INTO new_table (column1, column2, ...)
    SELECT column1, column2, ...
    FROM old_table;
    
  • 说明
    • new_tableold_table 结构需一致。
    • 若表结构复杂,可先使用 CREATE TABLE new_table AS SELECT * FROM old_table 创建新表并复制数据。

Linux 常用命令

1. 解压缩

  • tar 解压
    tar -xvf filename.tar -C /目标路径
    
  • gzip 解压
    gunzip filename.gz
    
  • zip 解压
    unzip filename.zip -d /目标路径
    

2. 创建文件

  • 创建空文件
    touch filename
    
  • 创建并写入内容
    echo "内容" > filename
    

3. 查看进程

  • 查看所有进程
    ps -ef
    
  • 按名称过滤进程
    ps -ef | grep 进程名
    

4. 增加执行权限

  • 给文件添加执行权限
    chmod +x filename
    

5. 查询指定文件下所有 .java 文件

  • 使用 find 命令
    find /目录路径 -name "*.java"
    

6. vi 指令

  • 打开文件
    vi filename
    
  • 进入编辑模式:按 i
  • 保存并退出:按 Esc,输入 :wq
  • 强制退出:按 Esc,输入 :q!

聚簇索引 vs 非聚簇索引

聚簇索引(Clustered Index)

  • 特点
    • 数据与索引存储在一起(InnoDB 的主键索引)。
    • 叶子节点直接存储完整数据。
  • 适用场景:主键查询效率高。
  • 限制:每个表只能有一个聚簇索引。

非聚簇索引(Secondary Index)

  • 特点
    • 叶子节点存储主键值(需回表查询数据)。
    • 支持多个非聚簇索引。
  • 适用场景:辅助字段查询(如 WHERE name = 'xxx')。

MySQL 存储引擎

常用引擎

  1. InnoDB
    • 支持事务、行级锁、外键。
    • 默认使用聚簇索引。
  2. MyISAM
    • 不支持事务,但性能高。
    • 使用非聚簇索引。
  3. Memory
    • 数据存储在内存中,适合临时表。

MySQL 调优

优化方向

  1. 索引优化
    • 为频繁查询的列创建索引。
    • 避免全表扫描(如 SELECT *)。
  2. 配置调优
    • 调整 innodb_buffer_pool_size(建议物理内存的 70%-80%)。
    • 优化日志文件大小(innodb_log_file_size)。
  3. 硬件优化
    • 使用 RAID 5/6 提高 I/O 性能。
    • 增加内存以减少磁盘 I/O。

索引失效场景

  1. 使用函数:如 WHERE YEAR(create_time) = 2025
  2. 类型转换:如 WHERE id = '123'id 是整数)。
  3. 模糊查询前导通配符:如 LIKE '%abc'
  4. OR 条件:若其中一个条件未使用索引,全表扫描。
  5. NOT IN!=:索引失效。
  6. 联合索引未使用最左匹配:如联合索引 (a, b),查询 WHERE b = 1 无效。

事务隔离级别

隔离级别脏读不可重复读虚读说明
读未提交最低隔离,性能高但数据一致性差。
读已提交防止脏读,但允许不可重复读。
可重复读MySQL 默认级别,通过间隙锁防止幻读。
串行化最高隔离,性能最低,完全串行化事务。

JVM 新生代 & 老年代

新生代(Young Generation)

  • 结构
    • Eden 区:新对象分配。
    • Survivor 区(S0/S1):存活对象复制。
  • 回收算法:复制算法(Minor GC)。

老年代(Old Generation)

  • 存放对象:长期存活的对象(经过多次 Minor GC)。
  • 回收算法:标记-整理(Mark-Compact)或标记-清除(Mark-Sweep)。

对象头存储位置

  • 对象头(Object Header)
    • Mark Word:存储对象的哈希码、GC 标志、锁状态等。
    • 类型指针:指向类元数据(Class Metadata)。
    • 数组长度(仅数组对象):记录数组长度。
  • 存储位置:对象在堆内存的起始部分。

Redis 数据类型

  1. String
    • 存储键值对(如用户信息)。
    • 底层:SDS(Simple Dynamic String)。
  2. Hash
    • 存储对象字段(如购物车)。
    • 底层:小数据量用 ziplist,大数据量用 hashtable
  3. List
    • 有序集合(如消息队列)。
    • 底层:小数据量用 ziplist,大数据量用 linkedlist
  4. Set
    • 无序不重复集合(如抽奖活动)。
    • 底层:小集合用 intset,大集合用 hashtable
  5. Sorted Set
    • 带分数的有序集合(如排行榜)。
    • 底层:skiplist + dict

Redisson

基本用法

  1. 引入依赖(Maven):
    <dependency>
        <groupId>org.redisson</groupId>
        <artifactId>redisson</artifactId>
        <version>3.16.4</version>
    </dependency>
    
  2. 创建客户端
    Config config = new Config();
    config.useSingleServer().setAddress("redis://127.0.0.1:6379");
    RedissonClient redisson = Redisson.create(config);
    
  3. 分布式对象
    • 分布式锁、队列、Map 等。

线程池 + 异步编排

线程池核心参数

  1. corePoolSize:核心线程数。
  2. maximumPoolSize:最大线程数。
  3. keepAliveTime:非核心线程空闲存活时间。
  4. workQueue:任务队列。
  5. threadFactory:线程工厂。
  6. handler:拒绝策略。

异步编排(CompletableFuture)

CompletableFuture.supplyAsync(() -> {
    // 异步任务1
}).thenApply(result -> {
    // 处理结果
}).exceptionally(ex -> {
    // 异常处理
});

synchronized vs ReentrantLock

特性synchronizedReentrantLock
可中断
超时等待
公平锁
条件变量
性能低(JDK 1.6 优化后提升)
代码简洁

volatile

  • 作用
    1. 保证可见性:修改后立即写入主存。
    2. 禁止指令重排序:通过内存屏障实现。
  • 不保证原子性:如 volatile int count; count++ 非原子操作。

HashMap put 的底层原理

  1. 哈希计算key.hashCode()(h ^ (h >>> 16)) & (n - 1)
  2. 哈希冲突解决:链表 + 红黑树(链表长度 ≥ 8 时转换)。
  3. 扩容机制:当 size > threshold 时,容量翻倍。
  4. 红黑树插入:树化后插入节点。

MQ 的使用场景

  1. 异步处理:如订单下单后发短信。
  2. 解耦:模块间通过消息队列通信。
  3. 削峰填谷:应对流量高峰(如秒杀)。
  4. 广播:一对多通知(如价格更新)。

Spring DI & IOC

  • IOC(控制反转):由 Spring 容器管理对象生命周期和依赖关系。
  • DI(依赖注入):通过 @Autowired 或 XML 配置注入依赖。

BeanFactory vs FactoryBean

  • BeanFactory:Spring 容器接口,负责创建和管理 Bean。
  • FactoryBean:自定义 Bean 工厂接口,实现 getObject() 返回实例。

循环依赖

  • Spring 解决方式
    1. 三级缓存
      • singletonObjects:一级缓存(完整 Bean)。
      • earlySingletonObjects:二级缓存(提前暴露的 Bean)。
      • singletonFactories:三级缓存(ObjectFactory)。
    2. AOP 代理对象:通过三级缓存提前暴露代理对象。

Spring 事务传播

传播行为说明
REQUIRED有事务则加入,无事务则新建(默认)。
REQUIRES_NEW总是新建事务,挂起当前事务(若有)。
SUPPORTS有事务则加入,无事务则非事务执行。
NOT_SUPPORTED强制非事务执行,挂起当前事务(若有)。
MANDATORY必须有事务,否则抛异常。
NEVER必须无事务,否则抛异常。
NESTED在当前事务中嵌套子事务。

OpenFeign 负载均衡

  • 实现方式
    • 集成 Ribbon 实现客户端负载均衡。
    • 通过 @LoadBalanced 注解启用负载均衡策略(如轮询、随机)。

count(1) vs count(列名) vs count(*)

  • count(*):统计所有行(包括 NULL 值)。
  • count(1):统计所有行(等效于 count(*))。
  • count(列名):仅统计该列非 NULL 的行。

JVM 调优

  1. 内存配置
    • 设置 -Xms-Xmx 为相同值避免动态扩容。
    • 调整 NewRatio 控制新生代比例。
  2. GC 选择
    • 低延迟场景:G1(Garbage-First)。
    • 高吞吐场景:Parallel Scavenge。
  3. 监控工具
    • jstat:查看 GC 状态。
    • jmap:分析堆内存。
    • jstack:分析线程状态。

AOP 注解

  • 常用注解
    • @Aspect:定义切面类。
    • @Before:前置通知。
    • @After:后置通知。
    • @Around:环绕通知。
    • @Pointcut:定义切点。

Redis 持久化

  1. RDB(快照)
    • 定期将内存数据保存为 dump.rdb 文件。
    • 优点:恢复速度快,文件紧凑。
    • 缺点:可能丢失最后一次快照后的数据。
  2. AOF(追加日志)
    • 记录所有写操作命令。
    • 优点:数据安全性高(可配置同步策略)。
    • 缺点:文件体积大,恢复速度慢。

xxl-job

  • 核心组件
    1. 调度中心:管理任务和触发。
    2. 执行器:执行具体任务。
  • 优点
    • 支持分布式任务调度。
    • 提供可视化界面和日志追踪。

@Async 异步

  • 配置步骤
    1. 启用异步支持:@EnableAsync
    2. 配置线程池:
      @Configuration
      public class AsyncConfig {
          @Bean(name = "taskExecutor")
          public Executor taskExecutor() {
              ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
              executor.setCorePoolSize(10);
              executor.setMaxPoolSize(20);
              executor.setQueueCapacity(100);
              executor.setThreadNamePrefix("Async-");
              executor.initialize();
              return executor;
          }
      }
      
    3. 使用注解:
      @Async("taskExecutor")
      public void asyncMethod() {
          // 异步逻辑
      }
      

Sentinel 熔断

  • 核心功能
    1. 流量控制:限制 QPS 或并发线程数。
    2. 熔断降级:失败率超过阈值时熔断。
    3. 系统负载保护:根据 CPU 使用率等指标自动降级。
  • 使用场景
    • 微服务调用链中的异常保护。
    • 高并发下的服务稳定性保障。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

~Yogi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值