生产者消费者之间的桥梁

前言

在这个多元的信息化时代,一个颇具规模的互联网公司,运营的系统可能每天需要处理海量的数据。当系统的处理速度达不到数据产生的速度的时候,就需要考虑一下异步通信的手段了。因为有可能就是一段同步调用的代码,在数据量上涨的时候,导致系统的崩溃。所以需要采用异步调用的方式,将海量的数据先暂时放到消息队列中,等待关联的程序逐步消费调用。所以本文将介绍一下异步调用的常用技术之消息队列

注:本文的消息队列针对于python语言自带的Queue模块

<code>知识拓展:
在一线互联网的公司面试中,经常会问到消息队列的使用场景。场景其实有很多,但是常用的一般总结为:
解耦,异步,削峰/<code>


生产者消费者之间的桥梁

图1

接下来从以下三个方面介绍一下python的Queue模块

  • Queue模块的基本使用
  • Queue模块的源码分析
  • 对于Queue模块的总结和思考

Queue模块的基本使用

Queue是一个队列,所以是先进先出的结构,一般可用于进程之间的通信。举一个经典的例子,消费者生产者模式的例子


生产者消费者之间的桥梁

图2

上图两个函数分别对应生产者和消费者功能,producer生产10个数字放到队列中,消费者从队列中依次将数字取出来

生产者消费者之间的桥梁

图3

对于Queue类,内置的类方法有put()方法,功能是将生产的元素放到队列中。get()方法是将队列中的数据取出来。还有两个类方法起到函数功能的辅助作用,empty()用来检测队列是否为空,队列中是否还有元素,full()方法用来告诉程序队列是否已经放满,无法再继续填充元素,一般用于设置了队列大小的情况下,默认队列是无限大的。qsize()返回目前队列中元素的数量


生产者消费者之间的桥梁

图4

Queue模块的源码分析

接下来我们一块看下Queue类的源码

生产者消费者之间的桥梁

图5

首先init方法初始化了线程的条件变量,需要notify才可以唤醒线程继续执行,从这里也可以解释为什么python的Queue是线程安全的,因为每个线程相当于加锁了,所以是线程安全的

生产者消费者之间的桥梁

图6

上图就是队列的put()方法,我们如果不指定队列的大小那么就会调用self._put()方法将数据放到队列中,同时还有一个标识self.unfinished_tasks,用来表明还有多少元素放到队列后没有被消费。并且调用self.not_empty.notify()唤醒get()方法去队列中获取元素消费。如果设置了队列的大小和超时时间的话,那么当元素数量等于队列的容量的时候,就会raise Full这个错误,同理超时也是一样的

生产者消费者之间的桥梁

图7

put()方法向队列输入数据之后,会唤醒get()方法来消费,首先get方法会先调用self._qsize()来判断当前队列中是否还有数据可以消费,如果没有,那么就wait(),直到put方法又生产了新的数据

生产者消费者之间的桥梁

图8

从图8我们可以了解到,Queue消息队列本质上用的deque这个数据结构,因为队列需要先进先出,而deque通过append之后,可以popleft将最早的元素弹出来,符合队列的规则。而empty()方法和full()方法本质上就是获取deque的长度

对于Queue模块的总结和思考

我们这篇文章主要分析了Queue这个类的使用场景和源码实现,一般对于python编程而言,通过Queue这个队列将两个进程或者线程之间联系了起来,并且是线程安全的,使用非常的方便。大家还能想起来队列的主要使用场景有哪些吗,没有印象的话可以到文章开头再看一下,对于生产者消费者模式其实本质上就是异步通信的使用场景。那么解耦和削峰的使用场景大家可以思考一下,削峰的目的其实是负载均衡,使流量的产生比较均匀,具体怎么使用,还有哪些其他的使用场景,欢迎大家留言讨论


以上就是作者的一些分析和看法,欢迎大家关注桓艺恒,多多留言讨论哈


分享到:


相關文章: