开源一个超好用的数据核对/对账框架

项目地址:github.com/starslink/d...

🚀 高性能、多策略的数据对账框架,支持内存、流式、并行、Redis、数据库等多种处理方式

✨ 特性

  • 🎯 多种对账策略 - 内存、流式、并行、Redis、数据库、增量处理
  • 🔧 灵活配置 - 支持注解和适配器两种数据定义方式
  • 📊 性能优化 - 根据数据量自动选择最优处理策略
  • 🌐 分布式支持 - Redis分布式缓存,支持集群部署
  • 💾 内存友好 - 流式处理避免大数据量内存溢出
  • 高并发 - 多线程并行处理,充分利用CPU资源

🚀 快速开始

1. 添加依赖

xml 复制代码
<dependency>
  <groupId>com.starslink</groupId>
  <artifactId>data-check</artifactId>
  <version>1.0-SNAPSHOT</version>
</dependency>

2. 基础使用

java 复制代码
// 创建对账配置
CheckConfig config = CheckConfig.builder()
        .id("order-check")
        .name("订单对账")
        .srcLoader(date -> loadSourceData(date))      // 源数据加载器
        .targetLoader(date -> loadTargetData(date))   // 目标数据加载器
        .allowableErrorRange(BigDecimal.valueOf(0.01)) // 允许误差
        .checkAfter(context -> {
          // 处理对账结果
          System.out.println("发现差异: " + context.getCheckResult().getDiffDetails().size());
        })
        .build();

// 执行对账
CheckExecutor executor = CheckExecutor.buildExecutor(config);
CheckContext result = executor.process("2023-12-01");

3. 数据实体定义

方式一:使用注解

java 复制代码
public class Order {

  @CheckIdentity
  private String orderId;

  @CheckField(order = 1)
  private BigDecimal amount;

  @CheckField(order = 2)
  private String status;
}

方式二:实现适配器

java 复制代码
public class OrderAdapter implements CheckAdapter {

  @Override
  public String getKey() {
    return orderId;
  }

  @Override
  public Map<String, Object> getCheckData() {
    return MapUtil.of("amount", amount, "status", status);
  }
}

📊 处理器选择

处理器类型 适用数据量 主要特点 使用场景
Memory < 10万 全内存,速度最快 小数据量,实时对账
Stream 10万-100万 分批处理,内存友好 大数据量,防止OOM
Parallel 任意 多线程并行 CPU密集型,追求速度
Redis 任意 分布式缓存 集群环境,数据共享
Database > 100万 SQL优化 超大数据量
Incremental 任意 增量处理 定期对账,减少计算

🔧 高级配置

流式处理(推荐大数据量)

java 复制代码
CheckConfig config = CheckConfig.builder()
    .id("stream-check")
    .batchSize(5000)  // 批次大小
    .checkProcessor(new StreamCheckProcessor())
    .build();

并行处理(推荐多核CPU)

java 复制代码
CheckConfig config = CheckConfig.builder()
    .id("parallel-check")
    .isAsync(true)
    .checkProcessor(new ParallelCheckProcessor())
    .build();

Redis分布式处理

java 复制代码
CheckConfig config = CheckConfig.builder()
    .id("redis-check")
    .checkCacheEnum(CheckCacheEnum.REDIS)
    .redisConfig(redisConfig)
    .build();

数据库处理(超大数据量)

java 复制代码
CheckConfig config = CheckConfig.builder()
    .id("database-check")
    .checkProcessor(new DatabaseCheckProcessor(dataSource))
    .build();

增量处理

java 复制代码
IncrementalDataProvider provider = new MyIncrementalDataProvider();
CheckConfig config = CheckConfig.builder()
    .id("incremental-check")
    .checkProcessor(new IncrementalCheckProcessor(provider))
    .build();

🎯 智能选择策略

java 复制代码
public CheckProcessor selectOptimalProcessor(int dataSize) {
  if (dataSize < 10_000) {
    return new MemoryCheckProcessor();           // 小数据量
  } else if (dataSize < 100_000) {
    return new ParallelCheckProcessor();         // 中等数据量
  } else if (dataSize < 1_000_000) {
    return new StreamCheckProcessor();           // 大数据量
  } else {
    return new DatabaseCheckProcessor(dataSource); // 超大数据量
  }
}

📈 性能对比

makefile 复制代码
数据量: 100万条记录测试结果

Memory处理器:    ❌ OutOfMemoryError
Stream处理器:    ✅ 45秒, 内存占用: 200MB
Parallel处理器:  ✅ 28秒, 内存占用: 800MB  
Database处理器:  ✅ 35秒, 内存占用: 50MB

🛠️ 完整示例

java 复制代码
@Test
public void testOrderReconciliation() {
  // 模拟数据
  List<Order> sourceOrders = loadOrdersFromSystem1("2023-12-01");
  List<Order> targetOrders = loadOrdersFromSystem2("2023-12-01");

  // 配置对账
  CheckConfig config = CheckConfig.builder()
      .id("daily-order-check")
      .name("每日订单对账")
      .srcLoader(date -> CheckEntry.wrap(sourceOrders))
      .targetLoader(date -> CheckEntry.wrap(targetOrders))
      .allowableErrorRange(BigDecimal.valueOf(0.01))
      .checkProcessor(selectOptimalProcessor(sourceOrders.size()))
      .checkPre(context -> validateData(context))
      .checkAfter(context -> {
        CheckResult result = context.getCheckResult();
        generateReport(result);
        sendNotification(result);
      })
      .build();

  // 执行对账
  CheckExecutor executor = CheckExecutor.buildExecutor(config);
  CheckContext result = executor.process("2023-12-01");

  // 输出结果
  System.out.println("对账完成:");
  System.out.println("- 源数据: " + result.getSource().size());
  System.out.println("- 目标数据: " + result.getTarget().size());
  System.out.println("- 差异记录: " + result.getCheckResult().getDiffDetails().size());
}
相关推荐
uzong17 小时前
Mermaid: AI 时代画图的魔法工具
后端·架构
q***697718 小时前
Spring Boot与MyBatis
spring boot·后端·mybatis
IUGEI19 小时前
synchronized的工作机制是怎样的?深入解析synchronized底层原理
java·开发语言·后端·c#
间彧19 小时前
GraalVM Native Image:跨平台能力与编译模式深度解析
后端
间彧19 小时前
GraalVM Native Image 与传统 JVM 内存管理:云原生时代的技术选型指南
后端
r***123819 小时前
SpringBoot最佳实践之 - 使用AOP记录操作日志
java·spring boot·后端
b***748819 小时前
前端GraphQL案例
前端·后端·graphql
LSL666_20 小时前
SpringBoot自动配置类
java·spring boot·后端·自动配置类
q***783720 小时前
Spring Boot 3.X:Unable to connect to Redis错误记录
spring boot·redis·后端
t***265921 小时前
SpringBoot + vue 管理系统
vue.js·spring boot·后端