代码补偿
@Component
@Slf4j
public class MyKafkaTask {
private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Resource
private KafkaTemplate<String, String> kafkaTemplate;
@Autowired
private ProductService productService;
@Autowired
private OrderService orderService;
@Autowired
private RedisClient redisClient;
@Autowired
KafkaProducers kafkaProducers;
//@Scheduled(cron = "0/30 * * * * ?")
@XxlJob("youTaskNameJobHandler")
//@Scheduled(initialDelay=2000, fixedRate=60000)
public void excuteTask() throws JsonProcessingException {
List<String> keySet = redisClient.getHash("messageObject_");//模仿数据来源
if (keySet != null && keySet.size() > 0) {
ObjectMapper objectMapper = new ObjectMapper();
for (String jonsonObjStr : keySet) {
MessageObject messageObject = objectMapper.readValue(jonsonObjStr , MessageObject.class);
String status = messageObject.getStatus();
if (!"1".equals(status) && !StringUtils.isEmpty(status)){
continue;
}
String id = messageObject.getId();
Long userId = messageObject.getUserId();
Long productId = messageObject.getProductId();
String productName = messageObject.getProductName();
String orderName = messageObject.getOrderName();
Order order = new Order();
order.setProductId(productId);
order.setUserId(userId);
order.setId(id);
order.setOrderName(orderName);
order.setProductName(productName);
List<Order> orderList = orderService.selectOne(id);
if (!CollectionUtils.isEmpty(orderList)){ // 防止消息重复消费,保证幂等性(存个key到Redis指定过期时间也可以,但要保证是同一条消息)
log.info("[该订单已存在] date={}" , sdf.format(new Date()));
continue;
}
Integer i = orderService.saveOrder(order);
Product product = new Product();
String name = messageObject.getName();
Integer stock = messageObject.getStock();
Date creatTime = messageObject.getCreatTime();
Date startTime = messageObject.getStartTime();
Date endTime = messageObject.getEndTime();
product.setId(productId);
product.setStock(stock);
product.setName(name);
product.setStartTime(startTime);
product.setEndTime(endTime);
product.setCreatTime(creatTime);
int p = productService.updateProduct(productId);
if (p > 0 && i > 0){ //更新到Redis(表)
messageObject.setStatus("0");
String message = objectMapper.writeValueAsString(messageObject);
redisClient.putHash("messageObject_" , productId + "_" + userId , message);//把状态更新回缓存
kafkaTemplate.send("seckill_order", JSONUtil.objToString(order));//重新发送到队列
}
}
}
}
}
一、XXL-Job简介
官网地址:
“https://www.xuxueli.com/xxl-job/
XXL-Job是一个开源的分布式任务调度平台,主要用于解决大规模分布式系统中的任务调度和管理问题。
XXL-Job简介:
XXL-Job是一个基于Java开发的分布式任务调度平台,旨在帮助开发者和运维人员管理和调度任务,特别适用于大规模分布式应用。它提供了直观的Web界面,易于配置和监控各种类型的任务。
XXL-Job的关键特点包括:
-
分布式任务调度: XXL-Job支持分布式任务调度,可以轻松处理任务分布在不同节点的情况。这对于大型微服务架构和集群环境非常有用。
-
弹性扩展: XXL-Job支持弹性扩展,你可以随时增加或减少执行器节点,以适应不同负载和任务需求。这确保了高可用性和性能。
-
任务调度中心: XXL-Job提供了一个任务调度中心,可以集中管理和监控任务。你可以在Web界面上创建、编辑、删除任务,查看任务日志和统计信息。
-
多种任务类型: 支持多种任务类型,包括简单的定时任务、Bean调用、Shell脚本、HTTP任务、GLUE任务(动态语言任务),满足各种任务需求。
-
任务依赖和失败重试: XXL-Job允许你配置任务之间的依赖关系,确保任务按照指定的顺序执行。同时,它支持失败重试机制,确保任务在失败时能够重新执行。
-
报警和日志: 提供了报警机制,可以通过邮件、短信等方式通知任务执行结果。任务执行日志也可以在Web界面中查看,便于故障排查和监控。
-
开源和社区支持: XXL-Job是开源项目,拥有活跃的社区支持和持续的更新。你可以根据自己的需求进行定制和扩展。
XXL-Job的分布式任务调度特点使其成为处理大规模、复杂任务调度需求的强大工具。它可以帮助开发团队更好地管理任务,提高系统的可靠性和可维护性,同时降低了任务调度的复杂性。
对比别的任务调度
XXL-Job在分布式任务调度领域有其独特之处,下面是它与其他一些任务调度解决方案的比较,以突出其优势和特点:
Quartz:
-
Quartz是一个强大的Java任务调度框架,但通常需要额外的配置和管理来支持分布式环境。XXL-Job提供了更易于配置和管理的分布式任务调度方案。
-
XXL-Job的Web界面和报警机制更加现代化,便于任务管理和监控。
Spring的@Scheduled:
-
Spring的@Scheduled注解适用于单节点应用程序,而XXL-Job专门设计用于分布式任务调度,支持在多个节点上执行任务。
-
XXL-Job提供了任务依赖和失败重试的机制,以处理复杂任务流程。
Elastic Job:
-
Elastic Job是另一个分布式任务调度框架,但XXL-Job更注重任务的可视化管理,提供了直观的Web界面。
-
XXL-Job的报警机制更加丰富,能够及时通知任务执行结果。
Akka Scheduler:
-
Akka是一个并发编程库,它提供了定时任务功能,但相对更加复杂。XXL-Job更适合那些希望通过Web界面轻松管理任务的团队。
-
XXL-Job的弹性扩展特性使其适用于大规模分布式系统。
Cron4J:
-
Cron4J是一个轻量级的Java定时任务库,适用于简单任务。XXL-Job提供了更多高级功能,如任务依赖、失败重试和任务监控。
总体而言,XXL-Job在分布式任务调度方面的优势在于其易用性、可视化管理、分布式支持、任务依赖和报警机制。它是一个强大的工具,特别适合需要大规模任务调度和监控的应用程序。
然而,具体选择取决于项目需求,一些轻量级的解决方案可能在小型应用中更加合适。
使用xxl-job需要引入依赖,如:
@XxlJob("youTaskNameJobHandler")
@XxlJob("youTaskNameJobHandler")
public void myTask(){
System.out.println(123);
}
<!-- https://mvnrepository.com/artifact/com.xuxueli/xxl-job-core -->
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.58.Final</version>
</dependency>
分布式XXL-JOB任务调度中心的操作(定时任务),每30秒执行一次