小易说IT 小易说IT

SpringBoot+HikariCP+Redis + 线程池 性能最优配置

前置说明

适配:SpringBoot3.x + Java17 + HikariCP + Redis (Lettuce) + 自定义线程池

原则:不是无脑调大参数,偏向生产高性能、防雪崩、适合 IO 密集型后端(数据库 + Redis 混合 IO); 区分:业务线程池(不混用 Tomcat 线程)、Hikari 连接池、Lettuce Redis 池 依赖:spring-boot-starter-data-redis、spring-boot-starter-jdbc /mybatis-spring-boot-starter

1. application.yml(直接复制)

# ===================== 服务基础 & Tomcat优化 =====================
server:
  port: 8080
  tomcat:
    threads:
      max: 200          # Tomcat最大工作线程,IO密集建议 150~250,CPU密集调低
      min-spare: 20     # 核心空闲线程
    accept-count: 100   # 排队队列长度,溢出直接拒绝
    connection-timeout: 10000
    max-connections: 800

spring:
  # ===================== HikariCP 数据库连接池【重点最优配置】=====================
  datasource:
    type: com.zaxxer.hikari.HikariDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/demo?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true&useSSL=false
    username: root
    password: 123456
    hikari:
      pool-name: HikariCP-DB-POOL
      maximum-pool-size: 12          # 黄金经验值:CPU核数*2 + 磁盘数;不要盲目开大!数据库连接很贵
      minimum-idle: 6                # 最小空闲,不建议等于max,避免抖动
      idle-timeout: 300000           # 空闲连接5分钟释放
      max-lifetime: 1800000          # 连接最大存活30min,比数据库wait_timeout小
      connection-timeout: 3000       # 获取连接超时3s,快速失败,不要设很大
      validation-timeout: 2000
      leak-detection-threshold: 5000  # 连接泄露检测,超过5s拿连接不归还打印告警

  # ===================== Redis Lettuce 连接池(SpringBoot3默认Lettuce,不用Jedis)=====================
  redis:
    host: 127.0.0.1
    port: 6379
    password: ""
    database: 0
    timeout: 2000ms
    lettuce:
      pool:
        max-active: 16    # 最大连接
        max-idle: 8
        min-idle: 4
        max-wait: 1000ms
      shutdown-timeout: 100ms

# ===================== 自定义业务线程池配置项(后面Java配置类读取)=====================
custom-thread-pool:
  core-pool-size: 8
  maximum-pool-size: 32
  queue-capacity: 200
  keep-alive-seconds: 60
  thread-name-prefix: biz-pool-
  allow-core-thread-timeout: false

2. 自定义线程池配置类【直接复制】

重要:禁止直接用 Executors,使用 ThreadPoolExecutor,拒绝策略用 AbortPolicy / 自定义告警策略 用途:异步业务、批量处理、非主链路任务;DB 操作必须从 Hikari 拿连接,不要在线程池里无限开连接

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.*;

@Configuration
@ConfigurationProperties(prefix = "custom-thread-pool")
public class BizThreadPoolConfig {

    private Integer corePoolSize;
    private Integer maximumPoolSize;
    private Integer queueCapacity;
    private Integer keepAliveSeconds;
    private String threadNamePrefix;
    private Boolean allowCoreThreadTimeout;

    /**
     * 业务IO线程池,用于异步任务、批量查询、消息消费等
     * 【不用于Tomcat主请求,和web线程隔离】
     */
    @Bean("bizTaskExecutor")
    public Executor bizTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(corePoolSize);
        executor.setMaxPoolSize(maximumPoolSize);
        executor.setQueueCapacity(queueCapacity);
        executor.setKeepAliveSeconds(keepAliveSeconds);
        executor.setThreadNamePrefix(threadNamePrefix);
        executor.setAllowCoreThreadTimeOut(allowCoreThreadTimeout);
        // 拒绝策略:队列满+线程满,直接抛异常,防止堆积拖垮服务;生产可替换为自定义告警策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
        executor.initialize();
        return executor;
    }

    // ========== getter & setter ==========
    public Integer getCorePoolSize() {
        return corePoolSize;
    }

    public void setCorePoolSize(Integer corePoolSize) {
        this.corePoolSize = corePoolSize;
    }

    public Integer getMaximumPoolSize() {
        return maximumPoolSize;
    }

    public void setMaximumPoolSize(Integer maximumPoolSize) {
        this.maximumPoolSize = maximumPoolSize;
    }

    public Integer getQueueCapacity() {
        return queueCapacity;
    }

    public void setQueueCapacity(Integer queueCapacity) {
        this.queueCapacity = queueCapacity;
    }

    public Integer getKeepAliveSeconds() {
        return keepAliveSeconds;
    }

    public void setKeepAliveSeconds(Integer keepAliveSeconds) {
        this.keepAliveSeconds = keepAliveSeconds;
    }

    public String getThreadNamePrefix() {
        return threadNamePrefix;
    }

    public void setThreadNamePrefix(String threadNamePrefix) {
        this.threadNamePrefix = threadNamePrefix;
    }

    public Boolean getAllowCoreThreadTimeout() {
        return allowCoreThreadTimeout;
    }

    public void setAllowCoreThreadTimeout(Boolean allowCoreThreadTimeout) {
        this.allowCoreThreadTimeout = allowCoreThreadTimeout;
    }
}

3. 使用示例(注入线程池)

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.concurrent.Executor;

@Service
public class BizService {

    private final Executor bizTaskExecutor;

    public BizService(@Qualifier("bizTaskExecutor") Executor bizTaskExecutor) {
        this.bizTaskExecutor = bizTaskExecutor;
    }

    public void submitTask(){
        bizTaskExecutor.execute(() -> {
            // 异步业务逻辑
        });
    }

    // @Async 注解方式,指定线程池
    @Async("bizTaskExecutor")
    public void asyncMethod(){

    }
}

4. 配套 POM 关键依赖(SpringBoot3 + Java17)

<dependencies>
    <!-- Spring Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- JDBC + HikariCP(boot自带hikari,无需额外引入) -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
    <!-- Redis Lettuce -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    <!-- mysql驱动 -->
    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
        <scope>runtime</scope>
    </dependency>
    <!-- 配置属性绑定 @ConfigurationProperties -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

✅ 调参核心准则(非常关键)

  1. Hikari maximum-pool-size 不要超过数据库的 max_connections,MySQL 默认一般 151;大多数业务 10~20 足够,不是越大越快!连接多了会造成数据库锁竞争、上下文切换飙升。

  2. Lettuce 是异步非阻塞,Redis 连接池不需要开很大,Lettuce 底层多路复用,很多人踩坑把 redis 连接池开几百完全没必要。

  3. Tomcat 线程池、业务线程池、Hikari、Redis 池是四套独立池,不要混淆:

    • Tomcat:接收 HTTP 请求

    • Hikari:数据库连接

    • Lettuce pool:Redis 连接

    • bizTaskExecutor:自定义异步业务

  4. 拒绝策略:高并发场景不要用CallerRunsPolicy(会把任务打回 Tomcat 线程,阻塞 web 请求);优先 AbortPolicy + 监控告警。

📌 监控配套建议(生产必加)

  • 接入 Micrometer + Prometheus 监控:hikari、lettuce、线程池队列、活跃线程数

  • 重点告警:Hikari 连接等待超时、连接泄露、线程池队列堆积、拒绝任务次数


本文原创作者:易君召,详见:https://www.yijunzhao.cc/about,转载请注明出处。

原文链接 https://www.yijunzhao.cc/archives/springboot-hikaricp-redis-thread-pool-optimal-performance-configuration

欢迎访问 https://www.yijunzhao.cc/

https://www.yijunzhao.cc/