共計 2156 個字符,預計需要花費 6 分鐘才能閱讀完成。
自動寫代碼機器人,免費開通
這篇文章將為大家詳細講解有關 redis 如何實現定時任務,丸趣 TV 小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
技術棧
redis / nodeJs / koa
技術重難點
開啟 redis 的鍵空間通知功能 (2.8.0 及以上的版本才有此功能)
盡量使用單獨的 redis db 來實現
使用基于 redis 的分布式鎖來實現相關事件不會被重復消費
需要二次使用的信息需要體現在 redis 緩存的 key 中
redis cache key 使用業務前綴,避免重名覆蓋
防止業務服務重啟導致 nodejs 層面的監聽失效
talk is cheap, show me the code ?
核心代碼
核心代碼
const { saveClient, subClient } = require(./db/redis) // 存儲實例和訂閱實例需要為兩個不同的實例
const processor = require(./service/task)
const config = require(./config/index)
const innerDistributedLockKey = __ // 內部使用的分布式鎖的 key 的特征值
const innerDistributedLockKeyReg = new RegExp(`^${innerDistributedLockKey}`)
saveClient.on(ready , async () = { saveClient.config( SET , notify-keyspace-events , Ex) // 存儲實例設置為推送鍵過期事件
console.log(redis init success)
subClient.on(ready , () = { // 服務重啟后依舊可以初始化所有 processor
subClient.subscribe(`__keyevent@${config.redis.sub.db}__:expired`) // 訂閱實例負責訂閱消息
subClient.on(message , async (cahnnel, expiredKey) = {
// 分布式鎖的 key 不做監聽處理
if (expiredKey.match(innerDistributedLockKeyReg)) return
// 簡易分布式鎖,拿到鎖的實例消費 event
const cackeKey = `${innerDistributedLockKey}-${expiredKey}`
const lock = await saveClient.set(cackeKey, 2, ex , 5, nx) // 這里的用法可以實現簡易的分布式鎖
if (lock === OK) { await saveClient.del(cackeKey)
for (let key in processor) { processor[key](expiredKey) // processor 對應的是接收到相關鍵過期通知后執行的業務邏輯,比如推送短信,然后在相關 processor 中再次 set 一個定時過期的 key
}
}
})
console.log(subClient init success)
})
servide/task (processor)
exports.sendMessage = async function sendMessage(expiredKey, subClient) {
// 只處理相關業務的過期事件
if (expiredKey.match(/^send_message/)) { const [prefix, userId, type] = expiredKey.split(-)
let user = getUser(userId)
if (user.phone) { push(message) // 偽代碼
resetRedisKey(expiredKey, ttl) // 重新把 key 設置為一段時間后過期,過期后會再次觸發本邏輯
}
}
}
總結
此功能利用了 redis 的鍵空間通知功能實現了簡單了基于用戶或者基于不同業務場景的定時任務功能。由于鍵空間事件通知功能是一個較消耗 CPU 的操作,所以建議使用單獨的 DB 來處理。
這里展示出來的是基本用法,未考慮定時任務的持久化功能,如果使用過程中 redis 故障重啟,則會導致所有定時任務丟失。如果在 redis 發布鍵失效通知時,訂閱服務出故障未在線,或者網絡問題沒有被消費方收到,也會導致此次事件丟失。
redis 的 expired 事件并不是在 key 過期的時候觸發,而是在 key 被刪除的時候觸發。redis 會定期清理過期的 key,或者當訪問 key 的時候檢查是否過期,只有這時過期的 key 才會觸發刪除操作,因此會有一些小的時間差距(個人的實際使用中并沒有影響用戶體驗)。
因此需要權衡使用 redis 的過期機制實現的定時任務的使用場景。
關于“redis 如何實現定時任務”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
向 AI 問一下細節