社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  DATABASE

Spring Boot + Apache Doris,抛弃MySQL开启实时分析新时代

Java知音 • 8 月前 • 311 次点击  

前言

在大数据爆发的今天,实时数据分析已成为企业决策的核心支撑 —— 电商需要实时监控爆款库存,运维需要秒级定位系统异常,营销需要实时调整投放策略。而作为传统关系型数据库的代表,MySQL 在中小规模数据存储和简单查询场景中表现稳定,但面对千万级以上数据量的复杂聚合分析(如多维度统计、漏斗转化计算)时,往往陷入查询超时、性能暴跌的困境,难以满足实时性需求。

此时,Apache Doris 这款高性能 MPP 分析型数据库应运而生,它专为实时数据分析场景设计,完美弥补了 MySQL 的短板。

本文将带大家实战 Spring Boot 与 Apache Doris 的集成方案,看看如何用它替代 MySQL,轻松搞定高并发、大数据量的实时分析需求!

救星登场:Apache Doris 闪亮来袭

什么是 Apache Doris?

Apache Doris 是一款基于 MPP(Massively Parallel Processing,大规模并行处理)架构的开源分析型数据库,起源于百度,2018 年开源并捐赠给 Apache 基金会。

它专为 OLAP(在线分析处理)场景设计,核心定位是 “实时、高效、易用”,支持 PB 级数据的低延迟查询,无需复杂的分库分表或数据预处理,就能直接应对多维度、高并发的分析需求。

核心特性,碾压 MySQL 的关键

1、极致查询性能: MPP 架构让数据在多个节点并行计算,单查询响应时间可低至毫秒级,比 MySQL 在大数据量下的查询速度快 10-100 倍;

2、实时数据接入: 支持从 Kafka、Flink 等流处理框架实时导入数据,也可同步 MySQL、Hive 等数据源,数据延迟低至秒级;

3、兼容 MySQL 协议: 无需修改业务代码中的 SQL 语法,支持 JDBC/ODBC 连接,集成成本极低;

4、高并发支持: 可轻松支撑每秒数千次的查询请求,适合面向用户的分析型应用(如数据看板、自助分析平台);

5、极简运维: 支持单节点部署,也可横向扩展至数百节点,自动分片、负载均衡,无需复杂的集群管理。

Doris vs MySQL:适用场景对比

一句话总结:MySQL 适合 “写多查少” 的业务交易场景(如订单创建、用户注册),Apache Doris 适合 “读多写少” 的实时分析场景(如数据统计、报表生成)。

Spring Boot 集成 Apache Doris 实战

前期准备

  • 环境要求:  JDK 1.8+、Spring Boot 2.3+、Maven 3.6+;
  • Apache Doris 部署: 推荐使用 Docker 快速部署(适合测试),或参考官方文档部署集群;
  • 核心依赖: Doris JDBC 驱动(兼容 MySQL 协议,可直接使用 MySQL JDBC 驱动)。

第一步:创建 Spring Boot 项目

1.访问 Spring Initializr,选择:

  • Spring Boot 版本: 2.7.x(稳定版);
  • 依赖: Spring Web(提供接口)、Spring Data JPA(简化数据操作)、MySQL Driver(兼容 Doris);

2.下载项目后,解压并导入 IDEA,项目基本结构如下:

src/
├── main/
│   ├── java/com/example/dorisdemo/
│   │   ├── controller/  // 接口层
│   │   ├── entity/      // 实体类
│   │   ├── repository/  // 数据访问层
│   │   ├── service/     // 业务层
│   │   └── DorisDemoApplication.java  // 启动类
│   └── resources/
│       └── application.yml  // 配置文件
└── pom.xml  // 依赖配置

第二步:核心配置(关键步骤)

1、 配置 pom.xml 依赖

无需额外引入 Doris 专属依赖,直接使用 MySQL JDBC 驱动即可(Doris 兼容 MySQL 协议),在 pom.xml 中添加:


<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-webartifactId>
dependency>

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-data-jpaartifactId>
dependency>

<dependency>
    <groupId>mysqlgroupId>
    <artifactId>mysql-connector-javaartifactId>
    <scope>runtimescope>
dependency>

<dependency>
    <groupId>org.projectlombokgroupId>
    <artifactId>lombokartifactId>
    <optional>trueoptional>
dependency>
2、 配置 application.yml

在  resources 目录下创建 application.yml,配置 Doris 连接信息(重点注意 url 格式):

spring:
  # 数据库配置(Doris兼容MySQL协议)
datasource:
    url:jdbc:mysql://127.0.0.1:9030/demo_db?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
    username:root# Doris默认用户名
    password:123456# 部署时设置的密码
    driver-class-name:com.mysql.cj.jdbc.Driver
# JPA配置(简化CRUD操作)
jpa:
    hibernate:
      ddl-auto:none# 关闭自动建表(Doris表手动创建)
    properties:
      hibernate:
        dialect:org.hibernate.dialect.MySQL8Dialect
        format_sql:true# 格式化SQL日志
    show-sql:true# 打印SQL语句

# 日志配置(可选)
logging:
level:
    org.springframework.data.jpa:debug
    com.example.dorisdemo:info

说明:Doris 的 JDBC 连接端口默认是 9030(FE 查询端口),demo_db是提前在 Doris 中创建的数据库。

第三步:创建 Doris 数据表

在 Doris 中手动创建测试表(以电商用户行为表为例),执行 SQL:

-- 创建数据库
CREATE DATABASEIFNOTEXISTS demo_db;
USE demo_db;

-- 创建用户行为表(分区表,按日期分区)
CREATETABLEIFNOTEXISTS user_behavior (
    user_id BIGINTCOMMENT'用户ID',
    product_id BIGINTCOMMENT'商品ID',
    category_id INTCOMMENT'商品分类ID',
    behavior_type VARCHAR(20COMMENT'行为类型(click/purchase/collect)',
    create_time DATETIME COMMENT'行为时间'
ENGINE=OLAP
DUPLICATEKEY(user_id, product_id)
PARTITIONBYRANGE(create_time) (
    PARTITION p202401 VALUESLESSTHAN ('2024-02-01'),
    PARTITION p202402 VALUESLESSTHAN ('2024-03-01')
)
DISTRIBUTEDBYHASH(user_id) BUCKETS 10
PROPERTIES (
    "storage_medium" = "HDD",
    "storage_ttl" = "30 DAY"
);

说明:Doris 支持分区表、分桶表,通过PARTITION BYDISTRIBUTED BY优化查询性能,适合大数据量存储。

第四步:编写代码实现业务逻辑

1、 实体类(Entity)

映射 Doris 的user_behavior表:

package com.example.dorisdemo.entity;

import lombok.Data;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;

import javax.persistence.*;
import java.time.LocalDateTime;

@Data
@Entity
@Table(name = "user_behavior")  // 对应Doris表名
@DynamicInsert// 动态插入(只插入非空字段)
@DynamicUpdate// 动态更新(只更新修改字段)
publicclass UserBehavior {

    @Id// 主键(Doris无自增主键,需手动指定)
    @Column(name = "user_id")
    private Long userId;

    @Column(name = "product_id")
    private Long productId;

    @Column(name = "category_id")
    private Integer categoryId;

    @Column(name = "behavior_type")
    private String behaviorType;  // click/purchase/collect

    @Column(name = "create_time")
    private LocalDateTime createTime;
}
2、 数据访问层(Repository)

继承 JpaRepository,简化 CRUD 操作:




    
package com.example.dorisdemo.repository;

import com.example.dorisdemo.entity.UserBehavior;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.time.LocalDateTime;
import java.util.List;

@Repository
publicinterface UserBehaviorRepository extends JpaRepository<UserBehaviorLong{

    // 自定义查询:查询指定日期范围内的用户行为
    List findByCreateTimeBetween(LocalDateTime start, LocalDateTime end);

    // 复杂查询:统计指定分类的商品点击量(Doris优化的聚合查询)
    @Query(value = "SELECT COUNT(*) FROM user_behavior WHERE category_id = :categoryId AND behavior_type = 'click' AND create_time BETWEEN :start AND :end", nativeQuery = true)
    Long countClickByCategoryId(@Param("categoryId") Integer categoryId, 
                                @Param("start") LocalDateTime start, 
                                @Param("end") LocalDateTime end)
;
}
3、 业务层(Service)

实现核心业务逻辑:

package com.example.dorisdemo.service;

import com.example.dorisdemo.entity.UserBehavior;
import com.example.dorisdemo.repository.UserBehaviorRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;

@Service
@RequiredArgsConstructor// 构造器注入依赖
publicclass UserBehaviorService {

    privatefinal UserBehaviorRepository behaviorRepository;

    // 保存用户行为数据
    public UserBehavior save (UserBehavior behavior) {
        return behaviorRepository.save(behavior);
    }

    // 批量保存(适合批量导入数据)
    public List batchSave(List behaviors) {
        return behaviorRepository.saveAll(behaviors);
    }

    // 查询指定日期范围的行为数据
    public List getBehaviorByDateRange(LocalDateTime start, LocalDateTime end) {
        return behaviorRepository.findByCreateTimeBetween(start, end);
    }

    // 统计分类商品点击量(实时分析核心接口)
    public Long getCategoryClickCount(Integer categoryId, LocalDateTime start, LocalDateTime end) {
        return behaviorRepository.countClickByCategoryId(categoryId, start, end);
    }
}
4、接口层(Controller)

提供 HTTP 接口供前端调用:

package com.example.dorisdemo.controller;

import com.example.dorisdemo.entity.UserBehavior;
import com.example.dorisdemo.service.UserBehaviorService;
import lombok.RequiredArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.List;

@RestController
@RequestMapping("/user-behavior")
@RequiredArgsConstructor
publicclass UserBehaviorController {

    privatefinal UserBehaviorService behaviorService;

    // 保存单个行为数据
    @PostMapping
    public UserBehavior save(@RequestBody UserBehavior behavior) {
        return behaviorService.save(behavior);
    }

    // 批量保存行为数据
    @PostMapping("/batch")
    public List batchSave(@RequestBody List behaviors) {
        return behaviorService.batchSave(behaviors);
    }

    // 按日期范围查询
    @GetMapping("/range")
    public List getByRange(
            @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
 LocalDateTime start,
            @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime end) 
{
        return behaviorService.getBehaviorByDateRange(start, end);
    }

    // 统计分类点击量(实时分析接口)
    @GetMapping("/click-count")
    public Long getClickCount(
            @RequestParam Integer categoryId,
            @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
 LocalDateTime start,
            @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime end) 
{
        return behaviorService.getCategoryClickCount(categoryId, start, end);
    }
}

第五步:测试与验证

1、 启动项目

运行DorisDemoApplication.java,确保项目启动成功,无报错。

2、 接口测试(用 Postman 或 curl)

批量插入测试数据:

POST /user-behavior/batch
Content-Type: application/json
[
    {"userId":1001,"productId":2001,"categoryId":301,"behaviorType":"click","createTime":"2024-01-15 10:30:00"},
    {"userId":1002,"productId":2002,"categoryId":301,"behaviorType":"click", "createTime":"2024-01-15 11:20:00"},
    {"userId":1003,"productId":2003,"categoryId":302,"behaviorType":"purchase","createTime":"2024-01-15 14:10:00"}
]

统计 301 分类的点击量:

GET /user-behavior/click-count?categoryId=301&start=2024-01-01 00:00:00&end=2024-01-31 23:59:59
3、性能对比测试

用 100 万条用户行为数据进行测试,对比 MySQL 和 Doris 的查询性能:

可以看到,Doris 在分析场景下的性能远超 MySQL,且数据量越大,优势越明显。

小结

Spring Boot 与 Apache Doris 的集成极其简单(兼容 MySQL 协议和 JDBC 驱动),但带来的性能提升却是革命性的 —— 它让开发者无需关注复杂的分布式架构,就能快速实现 PB 级数据的实时分析能力,完美替代 MySQL 在 OLAP 场景中的不足。

未来,随着实时数据需求的进一步增长,Apache Doris 这类专注于分析场景的数据库将成为技术栈的标配。无论是电商、金融、物流还是政务领域,只要涉及大数据量的实时统计、报表生成、多维度分析,“Spring Boot + Apache Doris” 都是值得优先选择的方案。

如果你还在为 MySQL 的分析性能瓶颈烦恼,不妨试试这个组合,相信会给你带来惊喜!欢迎在评论区分享你的使用体验或疑问~

构建高质量的技术交流社群,欢迎从事编程开发、技术招聘HR进群,也欢迎大家分享自己公司的内推信息,相互帮助,一起进步!

文明发言,以交流技术职位内推行业探讨为主

广告人士勿入,切勿轻信私聊,防止被骗

图片
加我好友,拉你进群

点下方的“❤ 支持我们,非常感谢!

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/190118