0%

MySQL InnoDB 数据存储:系统表空间与独立表空间详解

InnoDB 存储引擎提供了两种数据存储方式 ——系统表空间独立表空间,它们在文件管理、性能和维护方面有显著差异。理解这两种模式的特点,有助于优化数据库存储结构和性能。

表空间类型的查看与默认配置

通过以下命令可查看当前使用的表空间模式:

1
2
-- ON:独立表空间;OFF:系统表空间
show variables like '%innodb_file_per_table%';
  • MySQL 5.5 及之前:默认使用系统表空间
  • MySQL 5.6 及之后:默认使用独立表空间(更灵活,推荐生产环境使用)。

系统表空间(共享表空间)

系统表空间是一种共享存储模式,多个表的数据和索引共用一个或多个文件,默认文件名为 ibdata1ibdata2 等。

核心配置

1
2
3
4
5
6
7
8
-- 查看系统表空间文件路径和大小配置
show variables like 'innodb_data%';
-- 输出示例:
-- innodb_data_file_path = ibdata1:12M:autoextend(初始12M,自动扩展)
-- innodb_data_home_dir = (默认数据目录,如 /var/lib/mysql)

-- 查看自动扩展增量(默认64M)
show variables like 'innodb_autoextend_increment';
阅读全文 »

Java 对象的引用级别:从强到虚的内存管理艺术

在 Java 中,对象的引用并非只有 “存在” 或 “不存在” 两种状态,而是被细分为强引用、软引用、弱引用和虚引用四个级别。这种分级设计赋予了 JVM 更灵活的内存管理能力,允许开发者根据对象的重要性调整其生命周期,平衡内存使用与程序性能。本文将详细解析这四种引用类型的特性、使用场景及底层实现,帮助理解如何通过引用级别优化内存管理。

引用分级的核心目的

Java 引入多级别引用的核心诉求是:让对象的生命周期更灵活地响应内存状况。具体来说:

  • 对于核心对象(如用户会话、配置信息),需确保其始终驻留内存;
  • 对于次要对象(如缓存数据),可在内存紧张时主动回收,避免 OOM(内存溢出)。

通过引用分级,JVM 能在 “保留必要对象” 和 “释放冗余内存” 之间找到平衡,尤其适合内存敏感型应用(如缓存系统、大内存服务)。

强引用(Strong Reference)

强引用是最常见的引用类型,也是默认的引用方式。它直接关联对象,如同 “必需品”,JVM 绝不会主动回收强引用指向的对象。

特性与表现

  • 创建方式:通过new关键字实例化对象并赋值给变量,即形成强引用。

    1
    User user = new User(); // user 是指向 User 对象的强引用
  • 回收策略:只要强引用存在,无论内存是否紧张,JVM 都不会回收该对象。

  • 极端行为:若内存耗尽且无强引用可回收,JVM 会抛出 OutOfMemoryError,而非回收强引用对象。

  • 潜在问题:不当的强引用可能导致内存泄漏(如长期持有不再使用的对象引用)。

使用场景

强引用适用于必须始终存在的核心对象,如:

  • 程序运行的关键数据(如用户会话、全局配置);
  • 方法内的局部变量(随方法栈帧销毁自动释放)。

软引用(SoftReference)

软引用是 “可有可无” 的引用,其指向的对象在内存充足时保留,内存不足时(OOM 前)被回收,适合实现 “内存敏感的缓存”。

阅读全文 »

Spring 获取 Bean 完整流程源码解析:从 getBean 到 Bean 就绪

Spring 容器获取 Bean 的核心入口是 getBean() 方法,但其底层逻辑完全封装在 doGetBean() 中 —— 这是 Spring IOC 容器实现 “Bean 查找、创建、依赖注入、初始化” 的核心方法。从 “入口触发→Bean 名称处理→缓存查找(三级缓存)→循环依赖处理→不同作用域 Bean 创建→属性注入与初始化” 六个维度,逐行拆解获取 Bean 的全流程。

核心入口:getBean()doGetBean()

getBean() 是用户调用的入口方法,但其仅做简单转发,真正的逻辑全部在 doGetBean() 中实现。这一设计遵循 “职责单一” 原则 ——getBean() 暴露接口,doGetBean() 封装复杂逻辑。

1. 入口方法调用链

1
2
3
4
5
6
7
8
9
// 1. 用户调用:从容器获取 Bean(示例)
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
Car car = (Car) context.getBean("car"); // 入口1:调用 ApplicationContext 的 getBean()

// 2. ApplicationContext 继承 BeanFactory,最终委托给 AbstractBeanFactory 的 getBean()
// AbstractBeanFactory#getBean(String name)
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false); // 入口2:转发到 doGetBean()
}

2. doGetBean():获取 Bean 的 “总控制器”

doGetBean() 是整个流程的核心,代码虽长,但逻辑清晰,可拆解为 8 个关键步骤,每个步骤对应特定职责:

阅读全文 »

spark streaming容错机制详解:保障流处理的可靠性

在分布式系统中,节点故障、网络波动等问题难以避免。Spark Streaming 提供了完善的容错机制,通过检查点(Checkpoint) 实现状态恢复和驱动器容错,确保流处理作业在故障后可继续运行。本文将深入解析 Spark Streaming 的容错原理、检查点机制及驱动器恢复策略,帮助你构建高可靠的流处理系统。

Spark Streaming 容错的核心目标

流处理系统的容错需解决两大核心问题:

  1. 数据不丢失:确保从数据源接收的数据被正确处理,避免因故障导致数据丢失;
  2. 状态可恢复:在驱动器或工作节点故障后,能恢复流处理的中间状态和作业元数据;
  3. 作业连续性:故障恢复后,作业可从断点继续运行,无需从头重算。

检查点(Checkpoint)机制

检查点是 Spark Streaming 容错的核心,通过将关键信息持久化到可靠存储(如 HDFS),实现故障后的状态恢复。其核心作用包括:

检查点的两大目的

  • 控制重算范围:将中间状态持久化,减少故障后需重算的数据量;
  • 驱动器容错:保存 StreamingContext 的元数据,支持驱动器重启后恢复作业。

检查点的两种类型

检查点类型 存储内容 适用场景
元数据检查点 - StreamingContext 配置 - DStream 依赖关系 - 未完成的批次信息 驱动器故障恢复
数据检查点 - updateStateByKey 或窗口操作的中间状态 - 有状态转换的累计结果 状态恢复,避免重复计算

检查点存储介质

  • 推荐:分布式文件系统(如 HDFS、S3),确保集群节点可访问;
  • 不推荐:本地文件系统(仅限单机测试,集群环境下节点故障会导致数据丢失)。
阅读全文 »

JVM 垃圾回收(GC):从标记到回收的完整机制

垃圾回收(Garbage Collection,GC)是 JVM 自动管理内存的核心机制,负责识别并回收不再被使用的对象,释放内存空间。GC 主要作用于堆内存方法区,其设计直接影响程序的性能和稳定性。本文将全面解析 GC 的核心原理,包括对象存活判断、回收算法、垃圾回收器及实践配置,帮助深入理解 JVM 内存管理机制。

对象存活判断:如何识别 “垃圾”?

GC 的第一步是判断对象是否存活(即是否为 “垃圾”)。JVM 采用两种核心算法:引用计数法可达性分析

1. 引用计数法(Reference Counting)

  • 原理:为每个对象维护一个 “引用计数器”,当对象被引用时计数器 + 1,引用失效时 - 1。若计数器为 0,则认为对象是垃圾。

  • 优点:实现简单,判断效率高,回收无延迟。

  • 缺点

    • 需额外存储计数器,增加内存开销;
    • 无法解决循环引用问题(如两个对象互相引用,计数器永不为 0,导致无法回收)。

    示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    class A { B b; }
    class B { A a; }
    A a = new A();
    B b = new B();
    a.b = b;
    b.a = a;
    a = null;
    b = null;
    // 此时a和b互相引用,计数器均为1,引用计数法无法回收,导致内存泄漏

    由于循环引用问题,Java 未采用此算法。

2. 可达性分析(Reachability Analysis)

  • 原理:以 “根对象集合(GC Roots)” 为起点,通过引用链遍历对象。若对象无法通过任何引用链连接到 GC Roots,则被判定为 “不可达”(垃圾)。
  • 解决循环引用:因 GC Roots 不包含堆内对象的引用,循环引用的对象若与 GC Roots 无连接,会被正确标记为垃圾。
(1)GC Roots 的类型

GC Roots 是不在堆中的引用,常见类型包括:

  • 虚拟机栈中局部变量表的引用(如方法参数、局部变量);
  • 本地方法栈中 JNI(Native 方法)的引用;
  • 方法区中类静态属性的引用(如 static Object obj);
  • 方法区中常量的引用(如字符串常量池的引用);
  • synchronized 持有的对象引用;
  • JVM 内部引用(如基本类型的 Class 对象、系统类加载器)。
(2)对象的三种状态

通过可达性分析,对象会处于以下状态:

阅读全文 »