成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

幾種簡單實用的分布式定時任務(wù)!

開發(fā) 架構(gòu)
相較于之前兩種方式,這種基于 Redis 的實現(xiàn)可以通過多點來增加定時任務(wù),多點消費。但是要做好防范重復(fù)消費的準(zhǔn)備。

單點定時任務(wù)

JDK 原生

自從 JDK1.5 之后,提供了 ScheduledExecutorService 代替 TimerTask 來執(zhí)行定時任務(wù),提供了不錯的可靠性。

public class SomeScheduledExecutorService {
public static void main(String[] args) {
// 創(chuàng)建任務(wù)隊列,共 10 個線程
ScheduledExecutorService scheduledExecutorService =
Executors.newScheduledThreadPool(10);
// 執(zhí)行任務(wù): 1秒 后開始執(zhí)行,每 30秒 執(zhí)行一次
scheduledExecutorService.scheduleAtFixedRate(() -> {
System.out.println("執(zhí)行任務(wù):" + new Date());
}, 10, 30, TimeUnit.SECONDS);
}
}

Spring Task

Spring Framework 自帶定時任務(wù),提供了 cron 表達(dá)式來實現(xiàn)豐富定時任務(wù)配置。新手推薦使用 https://cron.qqe2.com/ 這個網(wǎng)站來匹配你的 cron 表達(dá)式。

@Configuration
@EnableScheduling
public class SomeJob {
private static final Logger LOGGER = LoggerFactory.getLogger(SomeJob.class);

/**
* 每分鐘執(zhí)行一次(例:18:01:00,18:02:00)
* 秒 分鐘 小時 日 月 星期 年
*/
@Scheduled(cron = "0 0/1 * * * ? *")
public void someTask() {
//...
}
}

單點的定時服務(wù)在目前微服務(wù)的大環(huán)境下,應(yīng)用場景越來越局限,所以嘗鮮一下分布式定時任務(wù)吧。

基于 Redis 實現(xiàn)

相較于之前兩種方式,這種基于 Redis 的實現(xiàn)可以通過多點來增加定時任務(wù),多點消費。但是要做好防范重復(fù)消費的準(zhǔn)備。

通過 ZSet 的方式:將定時任務(wù)存放到 ZSet 集合中,并且將過期時間存儲到 ZSet 的 Score 字段中,然后通過一個循環(huán)來判斷當(dāng)前時間內(nèi)是否有需要執(zhí)行的定時任務(wù),如果有則進(jìn)行執(zhí)行。

具體實現(xiàn)代碼如下:

/**
* Description: 基于Redis的ZSet的定時任務(wù) .<br>
*
* @author mxy
* @Date 2020/8/25 11:54
*/
@Configuration
@EnableScheduling
public class RedisJob {
public static final String JOB_KEY = "redis.job.task";
private static final Logger LOGGER = LoggerFactory.getLogger(RedisJob.class);
@Autowired private StringRedisTemplate stringRedisTemplate;

/**
* 添加任務(wù).
*
* @param task
*/
public void addTask(String task, Instant instant) {
stringRedisTemplate.opsForZSet().add(JOB_KEY, task, instant.getEpochSecond());
}

/**
* 定時任務(wù)隊列消費
* 每分鐘消費一次(可以縮短間隔到1s)
*/
@Scheduled(cron = "0 0/1 * * * ? *")
public void doDelayQueue() {
long nowSecond = Instant.now().getEpochSecond();
// 查詢當(dāng)前時間的所有任務(wù)
Set<String> strings = stringRedisTemplate.opsForZSet().range(JOB_KEY, 0, nowSecond);
for (String task : strings) {
// 開始消費 task
LOGGER.info("執(zhí)行任務(wù):{}", task);
}
// 刪除已經(jīng)執(zhí)行的任務(wù)
stringRedisTemplate.opsForZSet().remove(JOB_KEY, 0, nowSecond);
}
}

適用場景如下:

  • 訂單下單之后 15 分鐘后,用戶如果沒有付錢,系統(tǒng)需要自動取消訂單
  • 紅包 24 小時未被查收,需要延遲執(zhí)退還業(yè)務(wù)
  • 某個活動指定在某個時間內(nèi)生效&失效

優(yōu)勢是:

  • 省去了 MySQL 的查詢操作,而使用性能更高的 Redis 做為代替
  • 不會因為停機等原因,遺漏要執(zhí)行的任務(wù)

鍵空間通知的方式:我們可以通過 Redis 的鍵空間通知來實現(xiàn)定時任務(wù),它的實現(xiàn)思路是給所有的定時任務(wù)設(shè)置一個過期時間,等到了過期之后,我們通過訂閱過期消息就能感知到定時任務(wù)需要被執(zhí)行了,此時我們執(zhí)行定時任務(wù)即可。

默認(rèn)情況下 Redis 是不開啟鍵空間通知的,需要我們通過 config set notify-keyspace-events Ex 的命令手動開啟。

開啟之后定時任務(wù)的代碼如下:

自定義監(jiān)聽器:

 /**
* 自定義監(jiān)聽器.
*/
public class KeyExpiredListener extends KeyExpirationEventMessageListener {
public KeyExpiredListener(RedisMessageListenerContainer listenerContainer) {
super(listenerContainer);
}

@Override
public void onMessage(Message message, byte[] pattern) {
// channel
String channel = new String(message.getChannel(), StandardCharsets.UTF_8);
// 過期的key
String key = new String(message.getBody(), StandardCharsets.UTF_8);
// todo 你的處理
}
}

設(shè)置該監(jiān)聽器:

/** * Description: 通過訂閱Redis的過期通知來實現(xiàn)定時任務(wù) .

/**
* Description: 通過訂閱Redis的過期通知來實現(xiàn)定時任務(wù) .<br>
*
* @author mxy
* @Date 2020/8/25 12:07
*/
@Configuration
public class RedisExJob {
@Autowired private RedisConnectionFactory redisConnectionFactory;
@Bean
public RedisMessageListenerContainer redisMessageListenerContainer() {
RedisMessageListenerContainer redisMessageListenerContainer = new RedisMessageListenerContainer();
redisMessageListenerContainer.setConnectionFactory(redisConnectionFactory);
return redisMessageListenerContainer;
}

@Bean
public KeyExpiredListener keyExpiredListener() {
return new KeyExpiredListener(this.redisMessageListenerContainer());
}
}

Spring 會監(jiān)聽符合以下格式的 Redis 消息:

private static final Topic TOPIC_ALL_KEYEVENTS = new PatternTopic("__keyevent@*");

基于 Redis 的定時任務(wù)能夠適用的場景也比較有限,但實現(xiàn)上相對簡單,但對于功能冪等有很大要求。從使用場景上來說,更應(yīng)該叫做延時任務(wù)。

場景舉例:

訂單下單之后 15 分鐘后,用戶如果沒有付錢,系統(tǒng)需要自動取消訂單

紅包 24 小時未被查收,需要延遲執(zhí)退還業(yè)務(wù)

優(yōu)劣勢是:

  • 被動觸發(fā),對于服務(wù)的資源消耗更小
  • Redis 的 Pub/Sub 不可靠,沒有 ACK 機制等,但是一般情況可以容忍
  • 鍵空間通知功能會耗費一些 CPU

分布式定時任務(wù)

引入分布式定時任務(wù)組件 or 中間件:將定時任務(wù)作為單獨的服務(wù),遏制了重復(fù)消費,獨立的服務(wù)也有利于擴(kuò)展和維護(hù)。

quartz

依賴于 MySQL,使用相對簡單,可多節(jié)點部署,通過競爭數(shù)據(jù)庫鎖來保證只有一個節(jié)點執(zhí)行任務(wù)。沒有圖形化管理頁面,使用相對麻煩。

elastic-job-lite

依賴于 Zookeeper,通過 Zookeeper 的注冊與發(fā)現(xiàn),可以動態(tài)的添加服務(wù)器。

  • 多種作業(yè)模式
  • 失效轉(zhuǎn)移
  • 運行狀態(tài)收集
  • 多線程處理數(shù)據(jù)
  • 冪等性
  • 容錯處理
  • 支持spring命名空間
  • 有圖形化管理頁面

LTS

依賴于 Zookeeper,集群部署,可以動態(tài)的添加服務(wù)器。可以手動增加定時任務(wù),啟動和暫停任務(wù)。

  • 業(yè)務(wù)日志記錄器
  • SPI 擴(kuò)展支持
  • 故障轉(zhuǎn)移
  • 節(jié)點監(jiān)控
  • 多樣化任務(wù)執(zhí)行結(jié)果支持
  • FailStore 容錯
  • 動態(tài)擴(kuò)容
  • 對 spring 相對友好
  • 有監(jiān)控和管理圖形化界面

xxl-job

國產(chǎn),依賴于 MySQL,基于競爭數(shù)據(jù)庫鎖保證只有一個節(jié)點執(zhí)行任務(wù),支持水平擴(kuò)容。可以手動增加定時任務(wù),啟動和暫停任務(wù)。

  • 彈性擴(kuò)容
  • 分片廣播
  • 故障轉(zhuǎn)移
  • Rolling實時日志
  • GLUE(支持在線編輯代碼,免發(fā)布)
  • 任務(wù)進(jìn)度監(jiān)控
  • 任務(wù)依賴
  • 數(shù)據(jù)加密
  • 郵件報警
  • 運行報表
  • 優(yōu)雅停機
  • 國際化(中文友好)

總結(jié)

微服務(wù)下,推薦使用 xxl-job 這一類組件服務(wù)將定時任務(wù)合理有效的管理起來。而單點的定時任務(wù)有其局限性,適用于規(guī)模較小、對未來擴(kuò)展要求不高的服務(wù)。

相對而言,基于 Spring Task 的定時任務(wù)最簡單快捷,而 xxl-job 的難度主要體現(xiàn)在集成和調(diào)試上。

無論是什么樣的定時任務(wù),你都需要確保:

任務(wù)不會因為集群部署而被多次執(zhí)行

任務(wù)發(fā)生異常得到有效的處理

任務(wù)的處理過慢導(dǎo)致大量積壓

任務(wù)應(yīng)該在預(yù)期的時間點執(zhí)行

中間件可以將服務(wù)解耦,但增加了復(fù)雜度。

責(zé)任編輯:武曉燕 來源: 石杉的架構(gòu)筆記
相關(guān)推薦

2022-03-07 11:20:01

分布式代碼微服務(wù)

2024-02-19 00:00:00

分布式定時任務(wù)框架

2022-08-09 08:40:37

框架分布式定時任務(wù)

2023-01-04 09:23:58

2022-03-17 09:55:05

架構(gòu)分布式選型

2022-03-23 11:45:39

Quartz數(shù)據(jù)庫節(jié)點

2019-11-12 09:32:39

分布式elastic-job分片

2019-11-15 10:16:27

分布式任務(wù)框架

2022-06-16 07:31:15

MySQL服務(wù)器服務(wù)

2020-06-02 14:45:48

PostgreSQL架構(gòu)分布式

2025-04-27 08:01:25

2021-10-30 19:30:23

分布式Celery隊列

2023-03-01 08:07:51

2010-03-10 15:47:58

crontab定時任務(wù)

2020-09-29 19:20:05

鴻蒙

2023-06-26 00:14:28

Openjob分布式任務(wù)

2023-09-22 08:00:00

分布式鎖Redis

2009-10-09 16:13:16

VB開發(fā)分布式

2021-08-05 07:28:25

Java實現(xiàn)方式

2019-06-19 15:40:06

分布式鎖RedisJava
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: h视频免费观看 | 欧美精品一区在线 | 国产一区二区不卡 | 亚洲综合国产精品 | 中文字幕福利视频 | 欧美日韩18| 亚洲精品国产成人 | 久久性色 | 欧美午夜精品理论片a级按摩 | 欧美性生活免费 | 亚洲日日夜夜 | 日韩精品无码一区二区三区 | 国产精品日韩欧美一区二区三区 | 二区av | 亚洲性人人天天夜夜摸 | 精品自拍视频在线观看 | 亚洲黄色成人网 | 亚洲视频一区二区三区 | 欧美日韩综合一区 | 成人av色 | 国产99久久| 观看av | 九九热在线免费视频 | 日韩91 | 午夜精品一区二区三区在线观看 | 99精品视频在线观看 | 电影91久久久 | 7777久久| 欧美国产一区二区三区 | 亚洲高清免费视频 | 一级a爱片久久毛片 | 最新中文字幕在线 | 精品免费视频 | 人成在线 | 成人午夜在线观看 | 精品一区二区三区在线观看 | 一区二区三区四区在线 | 日韩久久久久久 | 欧美在线一区二区三区 | 韩三级在线观看 | 欧美国产激情二区三区 |