zoukankan      html  css  js  c++  java
  • Redis——任务队列

            很多博客网站中都会有发送邮件这个功能,发送邮件是一个双向数据的交互过程,如果使用单线程实现,很难避免会等待很长时间的情况出现,但碍于某些框架或语言不容易实现多线程,这时可以通过进程来实现。设想一个进程能够完成发邮件的功能,那么只要通知这个进程向指定的地址发送邮件就可以了。

            通知的过程可以借助任务队列来实现。与任务队列交互的类有两种:一类是生产者,另一类是消费者。生产者会将需要的任务放入任务队列中,而消费者则不断从任务队列中读取任务信息并执行。

    任务队列的优点:

    1、松耦合

            生产者和消费者不需知道彼此的实现细节,只要根据事先制定的协议,就可以有条不紊执行。

    2、易扩展

            Redis的任务队列实现是基于列表类型的基础上。完成发邮件的任务,生产者需要将邮件信息组成对象并序列化成字符串,然后将其加入到任务队列中,而消费者则需要循环遍历,从队列中拉取任务,伪代码如下:

    while(1){
        $task = RPOP queue
        if($task != null){
            execute($task);
        }else{
            wait some second;//以免频繁访问
        }
    }

            正如上面所示,如果使用RPOP命令,每次循环,至少都要等待一定时间,为了能够简化,并且一检测到有新任务,就可以马上被拉取,可以使用BRPOP命令,改进后的伪代码为:

    while(1){
        $task = BRPOP queue 0
     
        execute($task);
    }

    BRPOP命令接收两个参数,第一个是键名,第二个是超时时间,单位是秒。伪代码那里设置为0,表示如果没有新元素加入列表,就一直处于等待状态。

    下面是cmd窗口使用,需要开启两个以上的cmd窗口:


    输入命令后,客户端一直处于等待状态,


    在另一个客户端放入信息,原先客户端马上读取任务信息,并退出等待状态。

            现在又假设,博客网站还有订阅功能,这一功能也可以用任务列表实现,因为要执行的任务跟发送确认邮件一样,所以可以共用一个消费者。但是,这就出现问题了,如果现在有1000个人订阅了一位大神的博客,某一时刻这位大神发布了一篇文章,那么将会有1000封邮件加入到任务队列里面,如果每一封邮件耗时3秒,那么1000封就需要将近一个小时。在这一个小时期间,刚好有新用户想要订阅大神博客,当他提交自己的邮箱,等待查收确认邮件时,他就不得不等待一个小时的时间,因为他的任务被安排在这1000封邮件之后。

            为了解决上述这种情况,可以使用BLPOP(BRPOP)命令实现优先级队列。BLPOP可以同时监测多个键,只要其中一个键有任务,就会弹出元素,如果多个键同时都具有任务,那么优先弹出最左边的键的元素。

    例子1:

    先启动检测,

    再在另一个客户端放入任务,


    右边已检测到queue2有任务,马上弹出,第一个信息表示键,第二个信息表示键的元素。

    例子2:

    先在键里面放入元素,


    再启动检测,


    每次执行检测,只会弹出一个元素(这就是伪代码使用循环的原因),而且还是从左到右按顺序取值。连续执行了三遍检测命令,到了第三次就进入等待状态,因为前两次已经将放进去的元素都弹出来了。

            按照这样的思路,可以分别使用键名queue:confirmation:email和queue:notification:email来存储确认邮件和通知邮件的信息,一旦都有任务加入,优先弹出queue:confirmation:email的元素。

  • 相关阅读:
    PAT (Advanced Level) Practice 1055 The World's Richest (25 分) (结构体排序)
    PAT (Advanced Level) Practice 1036 Boys vs Girls (25 分)
    PAT (Advanced Level) Practice 1028 List Sorting (25 分) (自定义排序)
    PAT (Advanced Level) Practice 1035 Password (20 分)
    PAT (Advanced Level) Practice 1019 General Palindromic Number (20 分) (进制转换,回文数)
    PAT (Advanced Level) Practice 1120 Friend Numbers (20 分) (set)
    从零开始吧
    Python GUI编程(TKinter)(简易计算器)
    PAT 基础编程题目集 6-7 统计某类完全平方数 (20 分)
    PAT (Advanced Level) Practice 1152 Google Recruitment (20 分)
  • 原文地址:https://www.cnblogs.com/SysoCjs/p/10332778.html
Copyright © 2011-2022 走看看