找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

481

积分

0

好友

64

主题
发表于 4 小时前 | 查看: 4| 回复: 0

在大数据爆发的今天,实时数据分析已成为企业决策的核心支撑。电商需要实时监控爆款库存,运维需要秒级定位系统异常,营销需要实时调整投放策略。而作为传统关系型数据库的代表,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中添加:

<!-- Spring Web -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Data JPA -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- MySQL JDBC驱动(兼容Doris) -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>
<!--  lombok(简化实体类) -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</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 DATABASE IF NOT EXISTS demo_db;
USE demo_db;
-- 创建用户行为表(分区表,按日期分区)
CREATE TABLE IF NOT EXISTS user_behavior (
    user_id BIGINT COMMENT '用户ID',
    product_id BIGINT COMMENT '商品ID',
    category_id INT COMMENT '商品分类ID',
    behavior_type VARCHAR(20) COMMENT '行为类型(click/purchase/collect)',
    create_time DATETIME COMMENT '行为时间'
)
ENGINE=OLAP
DUPLICATE KEY(user_id, product_id)
PARTITION BY RANGE(create_time) (
    PARTITION p202401 VALUES LESS THAN ('2024-02-01'),
    PARTITION p202402 VALUES LESS THAN ('2024-03-01')
)
DISTRIBUTED BY HASH(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 // 动态更新(只更新修改字段)
public class 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
public interface UserBehaviorRepository extends JpaRepository<UserBehavior, Long> {
    // 自定义查询:查询指定日期范围内的用户行为
    List<UserBehavior> 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 // 构造器注入依赖
public class UserBehaviorService {
    private final UserBehaviorRepository behaviorRepository;
    // 保存用户行为数据
    public UserBehavior save(UserBehavior behavior) {
        return behaviorRepository.save(behavior);
    }
    // 批量保存(适合批量导入数据)
    public List<UserBehavior> batchSave(List<UserBehavior> behaviors) {
        return behaviorRepository.saveAll(behaviors);
    }
    // 查询指定日期范围的行为数据
    public List<UserBehavior> 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
public class UserBehaviorController {
    private final UserBehaviorService behaviorService;
    // 保存单个行为数据
    @PostMapping
    public UserBehavior save(@RequestBody UserBehavior behavior) {
        return behaviorService.save(behavior);
    }
    // 批量保存行为数据
    @PostMapping("/batch")
    public List<UserBehavior> batchSave(@RequestBody List<UserBehavior> behaviors) {
        return behaviorService.batchSave(behaviors);
    }
    // 按日期范围查询
    @GetMapping("/range")
    public List<UserBehavior> 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的集成极其简单,但带来的性能提升却是革命性的。它让开发者无需关注复杂的分布式架构,就能快速实现PB级数据的实时分析能力,完美解决MySQL在OLAP场景中的性能瓶颈。未来,随着大数据实时分析需求的增长,Apache Doris这类专注于分析场景的数据库将成为技术栈的重要组成。无论是电商、金融还是物流领域,只要涉及大数据量的实时统计与多维度分析,“Spring Boot + Apache Doris”都是一个高效且值得考虑的方案。




上一篇:Kubernetes StatefulSet稳定性详解:有状态服务架构设计与实战指南
下一篇:GESP C++六级搜索算法深度解析:DFS与BFS的核心区别与实战应用
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区(YunPan.Plus) ( 苏ICP备2022046150号-2 )

GMT+8, 2025-12-6 23:53 , Processed in 0.093095 second(s), 36 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 CloudStack.

快速回复 返回顶部 返回列表