背景
离线开发支持间隔时长按分钟更新,比如设置间隔时长(分)7,希望每隔7分钟执行一次,但是发现 15:56 运行之后,14:00又运行了一次,中间只间隔了4分钟。
原因
这是因为bi的定时更新,是生成corn表达式,Cron 表达式是用于指定任务在特定时间执行的字符串,其格式通常由 5 或 6 个字段组成,不同的字段分别代表不同的时间单位,以下是各字段的含义及顺序:
接下来分析0 */7 * * * *
这个 Cron 表达式:
- 秒(第 1 个字段):该字段值为
0
,这表明任务会在每分钟的第 0 秒开始执行。 - 分(第 2 个字段):字段值为
*/7
,其中*
代表该时间单位的所有取值范围,也就是从 0 到 59 分钟;/
是间隔符,*/7
意味着从 0 分开始,每隔 7 分钟执行一次,也就是 0 分、7 分、14 分、21 分……56 分都会执行任务。 - 小时(第 3 个字段):字段值为
*
,表示在一天 24 小时中的任意时刻都有可能执行任务。 - 日(第 4 个字段):字段值为
*
,意味着在一个月内的任意一天都可能执行任务。 - 月(第 5 个字段):字段值为
*
,表示在一年 12 个月中的任意月份都可能执行任务。 - 周(第 6 个字段):字段值为
*
,说明在一周 7 天的任意一天都可能执行任务。
所以,0 */7 * * * *
这个 Cron 表达式会让任务在每分钟的第 0 秒开始执行,并且每隔 7 分钟执行一次,每个整点都会触发,不会跨小时循环。
案例
如果想避开整点运行,比如有些整点定时任务很多,或者其他业务需求要求整点不触发,该如何实现呢?
实现
以mysql为例,可以使用数据库sleep函数让调度暂停执行指定的秒数。放在工作流最前面,每次运行时都会等待几分钟,数据库类型无所谓,这个数据集只做暂时工具使用。比如 select sleep(180)
这样定时更新从原来的 0 分、7 分、14 分、21 分……56 分 变成 3分、10分、17分、24分......59分,整点就不会触发更新了。
当执行 SELECT SLEEP(180)
语句时,MySQL 服务器会暂停当前线程的执行,时长为 180 秒(也就是 3 分钟)。在这 180 秒内,该线程会处于阻塞状态,不会去处理其他任务。等到 180 秒过去,SLEEP()
函数才会返回 0,并且该 SQL 语句执行完毕。