点击上方“程序员蜗牛g”,选择“设为星标”
跟蜗牛哥一起,每天进步一点点
程序员蜗牛g
大厂程序员一枚 跟蜗牛一起 每天进步一点点
31篇原创内容
公众号
为了提高订单状态更新的效率和系统的响应能力,我们决定采用分布式任务调度实现高效的订单状态批量更新。
应用场景
数据批处理
-
批量数据导入/导出:将大量数据从一个系统迁移到另一个系统时,可以将数据分成多个批次进行处理。
-
日志处理:分析和处理大量的日志文件,每个分片处理一部分日志。
实时监控与报警
-
监控指标收集:实时收集和处理监控指标,每个分片负责收集一部分系统的监控数据。
-
报警规则评估:评估报警规则,每个分片处理一部分报警条件。
任务分片的目的
如何进行任务分片?
代码实操
<!-- Spring Boot Starter -->
<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 Connector -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- ElasticJob Lite Core -->
<dependency>
<groupId>com.dangdang</groupId>
<artifactId>elastic-job-lite-core</artifactId>
<version>2.1.5</version>
</dependency>
<!-- ElasticJob Lite Spring Boot Starter -->
<dependency>
<groupId>com.dangdang</groupId>
<artifactId>elastic-job-lite-spring-boot-starter</artifactId>
<version>2.1.5</version>
</dependency>
<!-- Zookeeper Client -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.2.0</version>
</dependency>
application.yml
server:
port:8080
spring:
datasource:
url:jdbc:mysql://localhost:3306/order_db?useSSL=false&serverTimezone=UTC
username:root
password:123456
driver-class-name:com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto:update
show-sql:true
properties:
hibernate:
dialect:org.hibernate.dialect.MySQL5InnoDBDialect
elasticjob:
regCenter:
serverLists:localhost:2181# ZooKeeper服务器地址
namespace:elastic-job-demo # 命名空间
jobs:
orderStatusUpdateJob:
cron: 0 0 * * * ? # Cron表达式,每小时执行一次
shardingTotalCount:5 # 分片总数
jobClass:com.example.job.OrderStatusUpdateJob# 任务类全限定名
description:"更新订单状态"# 任务描述
Application.java
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling // 启用定时任务调度
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
订单状态更新任务
package com.example.job;
import com.dangdang.ddframe.job.api.ShardingContext;
import com.dangdang.ddframe.job.simple.api.SimpleJob;
import com.example.service.OrderService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* 订单状态更新任务类
* 实现SimpleJob接口,用于定期更新订单状态
*/
@Component
publicclass OrderStatusUpdateJob implements SimpleJob {
privatestaticfinal Logger log = LoggerFactory.getLogger(OrderStatusUpdateJob.class);
@Autowired
private OrderService orderService; // 注入OrderService服务
/**
* 执行任务的方法
* @param context 分片上下文
*/
@Override
public void execute(ShardingContext context) {
int shardingItem = context.getShardingItem(); // 获取当前分片项
int shardingTotalCount = context.getShardingTotalCount(); // 获取总分片数
long maxOrderId = orderService.getMaxOrderId(); // 获取最大订单ID
// 计算当前分片需要处理的订单范围
long startId = (long) shardingItem * (maxOrderId / shardingTotalCount);
long endId = Math.min(startId + (maxOrderId / shardingTotalCount), maxOrderId);
log.info("Processing orders from {} to {}", startId, endId); // 记录处理的订单范围
int updatedCount = orderService.updateStatusInRange(startId, endId, "Processed"); // 更新订单状态
log.info("Updated {} orders in range {} to {}", updatedCount, startId, endId); // 记录更新结果
}
}
订单实体类
package com.example.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
/**
* 订单实体类
* 映射到数据库中的order表
*/
@Entity
publicclass Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; // 订单ID
private String status; // 订单状态
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}
订单Repository
package com.example.repository;
import com.example.model.Order;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* 订单Repository接口
* 提供基本的CRUD操作和自定义查询
*/
publicinterface OrderRepository extends JpaRepository<Order, Long> {
/**
* 根据ID范围查找订单
* @param startId 开始ID
* @param endId 结束ID
* @return 订单列表
*/
List<Order> findByIdBetween(Long startId, Long endId);
/**
* 根据ID范围更新订单状态
* @param startId 开始ID
* @param endId 结束ID
* @param newStatus 新状态
* @return 更新的订单数量
*/
@Modifying
@Transactional
@Query("UPDATE Order o SET o.status = :newStatus WHERE o.id BETWEEN :startId AND :endId")
int updateStatusInRange(@Param("startId") Long startId, @Param("endId") Long endId, @Param("newStatus") String newStatus);
}
订单服务类
package com.example.service;
import com.example.model.Order;
import com.example.repository.OrderRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 订单服务类
* 处理订单相关的业务逻辑
*/
@Service
publicclass OrderService {
@Autowired
private OrderRepository orderRepository; // 注入OrderRepository
/**
* 根据ID范围获取订单
* @param startId 开始ID
* @param endId 结束ID
* @return 订单列表
*/
public List<Order> getOrdersByRange(Long startId, Long endId) {
return orderRepository.findByIdBetween(startId, endId);
}
/**
* 根据ID范围更新订单状态
* @param startId 开始ID
* @param endId 结束ID
* @param newStatus 新状态
* @return 更新的订单数量
*/
public int updateStatusInRange(Long startId, Long endId, String newStatus) {
return orderRepository.updateStatusInRange(startId, endId, newStatus);
}
/**
* 获取最大订单ID
* @return 最大订单ID
*/
public long getMaxOrderId() {
return orderRepository.findAll().stream()
.mapToLong(Order::getId)
.max()
.orElse(0L);
}
}
如果这篇文章对您有所帮助,或者有所启发的话,求一键三连:点赞、转发、在看。