• 企业400电话
  • 网络优化推广
  • AI电话机器人
  • 呼叫中心
  • 全 部 栏 目

    网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    基于redis实现定时任务的方法详解
    POST TIME:2021-10-18 23:40

    前言

    业务中碰到的需求(抽象描述一下):针对不同的用户能够实现不同时间的间隔循环任务。比如在用户注册成功24小时后给用户推送相关短信等类似需求。

    使用crontab?太重,且基本不现实,不可能给每一个用户在服务器上生成一个定时任务。
    定时轮询?IO频繁且效率太低

    想到经常的使用的redis可以设置缓存时间,应该会有过期的事件通知吧,查了一下文档,果然有相关配置,叫做“键空间事件通知”。具体说明可参考官方文档。

    技术栈

    redis / nodeJs / koa

    技术重难点

    "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的过期机制实现的定时任务的使用场景。

    好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。

    您可能感兴趣的文章:
    • java操作Redis缓存设置过期时间的方法
    • 使用redis的increment()方法实现计数器功能案例
    • Redis有效时间设置以及时间过期处理操作
    上一篇:Redis全量复制与部分复制示例详解
    下一篇:详解redis desktop manager安装及连接方式
  • 相关文章
  • 

    关于我们 | 付款方式 | 荣誉资质 | 业务提交 | 代理合作


    © 2016-2020 巨人网络通讯

    时间:9:00-21:00 (节假日不休)

    地址:江苏信息产业基地11号楼四层

    《增值电信业务经营许可证》 苏B2-20120278

    X

    截屏,微信识别二维码

    微信号:veteran88

    (点击微信号复制,添加好友)

     打开微信