日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢(xún)
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
幾種簡(jiǎn)單實(shí)用的分布式定時(shí)任務(wù)!

單點(diǎn)定時(shí)任務(wù)

JDK 原生

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

Spring Task

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

創(chuàng)新互聯(lián)服務(wù)項(xiàng)目包括施秉網(wǎng)站建設(shè)、施秉網(wǎng)站制作、施秉網(wǎng)頁(yè)制作以及施秉網(wǎng)絡(luò)營(yíng)銷(xiāo)策劃等。多年來(lái),我們專(zhuān)注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢(shì)、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,施秉網(wǎng)站推廣取得了明顯的社會(huì)效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶(hù)以成都為中心已經(jīng)輻射到施秉省份的部分城市,未來(lái)相信會(huì)繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶(hù)的支持與信任!

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

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

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

基于 Redis 實(shí)現(xiàn)

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

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

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

/**
* Description: 基于Redis的ZSet的定時(shí)任務(wù) .

*
* @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());
}

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

適用場(chǎng)景如下:

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

優(yōu)勢(shì)是:

  • 省去了 MySQL 的查詢(xún)操作,而使用性能更高的 Redis 做為代替
  • 不會(huì)因?yàn)橥C(jī)等原因,遺漏要執(zhí)行的任務(wù)

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

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

開(kāi)啟之后定時(shí)任務(wù)的代碼如下:

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

 /**
* 自定義監(jiān)聽(tīng)器.
*/
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);
// 過(guò)期的key
String key = new String(message.getBody(), StandardCharsets.UTF_8);
// todo 你的處理
}
}

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

/** * Description: 通過(guò)訂閱Redis的過(guò)期通知來(lái)實(shí)現(xiàn)定時(shí)任務(wù) .

/**
* Description: 通過(guò)訂閱Redis的過(guò)期通知來(lái)實(shí)現(xiàn)定時(shí)任務(wù) .

*
* @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 會(huì)監(jiān)聽(tīng)符合以下格式的 Redis 消息:

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

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

場(chǎng)景舉例:

訂單下單之后 15 分鐘后,用戶(hù)如果沒(méi)有付錢(qián),系統(tǒng)需要自動(dòng)取消訂單

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

優(yōu)劣勢(shì)是:

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

分布式定時(shí)任務(wù)

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

quartz

依賴(lài)于 MySQL,使用相對(duì)簡(jiǎn)單,可多節(jié)點(diǎn)部署,通過(guò)競(jìng)爭(zhēng)數(shù)據(jù)庫(kù)鎖來(lái)保證只有一個(gè)節(jié)點(diǎn)執(zhí)行任務(wù)。沒(méi)有圖形化管理頁(yè)面,使用相對(duì)麻煩。

elastic-job-lite

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

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

LTS

依賴(lài)于 Zookeeper,集群部署,可以動(dòng)態(tài)的添加服務(wù)器??梢允謩?dòng)增加定時(shí)任務(wù),啟動(dòng)和暫停任務(wù)。

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

xxl-job

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

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

總結(jié)

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

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

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

任務(wù)不會(huì)因?yàn)榧翰渴鸲欢啻螆?zhí)行

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

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

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

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


本文題目:幾種簡(jiǎn)單實(shí)用的分布式定時(shí)任務(wù)!
分享網(wǎng)址:http://www.5511xx.com/article/cdhcogp.html