咱们在开发的过程当中,会遇到像这样的状况:php
好比,咱们须要开发一个给注册用户发送邮件的功能。其实制做起来并非很难,无非就是两步,mysql
一、获取须要发送邮件的邮箱,并填写发送内容。程序员
二、发送。redis
这功能实现起来很简单,也很写,对吧!sql
那么,如今问题来了。并发
我如今有好百万的并发,几百万个用户同时都在注册(固然这里是假设)。这么高并发的状况下,咱们仍是用同步的方式去执行上面的1和2这两个步骤。高并发
我能够很负责的告诉你们,必定会出现发送失败的案例,并且会不少。post
那怎么解决这样的问题呢?spa
消息队列!!!线程
这里咱们就引入了消息队列的概念。在理解这个概念以前,咱们先来看一个生活中的小例子:
咱们都到餐厅去吃过饭对吧,服务员点单和厨师作菜,必定是服务员点单远远快于厨师作菜。那么问题再一次来了,若是服务员点单和厨师作菜是单线程的同步执行的。
那么咱们做为顾客,必定会有很大的怨言。由于咱们要等到上一座点单的是的菜上齐事后才能点餐。
可是在现实生活中,没有一家餐厅是这样的。一般餐厅中服务员点单和厨师作菜没有直接联系,服务员只管点单,点单成功后记录在一个介质上(这里假设为记录在纸上),而后传递给后厨,后厨再按照单子的先后顺序依次制做。
其实,咱们上面天天都经历的这个情形就是一个典型的消息队列:消息发布者(服务员),将消息存入消息队列(纸质点单记录),消息执行者(厨师)从消息队列取得消息并执行。
看了上面的例子,我相信绝大部分人对消息队列都应该有了必定的认识了。
下面为消息队列的一个抽象图。(生产者:服务员、消费者:厨师)
下面,咱们来说一下如何使用消息队列实现百万并发的邮件发送(保证每一封邮件都能发送成功,除非客户填写了一个错误的邮件地址,这里咱们不考虑这种状况)
须要注意的是,存储消息的介质有不少,咱们能够根据需求随意选择,不用拘泥于redis的list。这里咱们暂且选择mysql做为消息的存储介质。
咱们新建一个表,用于存储消息。代表为MQ,含有三个字段id、u_email(用户邮箱)、post_content(发送内容)。
一、当用户申请注册的时候,将用户的邮箱和发送内容(发送内容能够视状况而定,这里的逻辑就具体问题具体分析了哈)存入MQ表,存入成功后立刻就能够给用户反馈。好比(请到您的邮箱查看邮件是否已发送到您的邮箱......)
二、用php实现一个定时器,定时从MQ表中取出数据,进行邮件发送。若是成功则从数据表MQ中删除该条记录(固然,通常咱们用逻辑删除),若是没有成功,则不删除。
优势:
一、后台运行,前台无需等待,立刻能够给客户以反应,友好度较高。
二、成功率高,失败的记录会自动重发,直到成功。
在工做中会遇到不少刚接触消息队列的程序员,误觉得redis的list就是消息队列。其实list只是redis的一种数据类型,它可以实现消息队列功能而已。
作一个消息队列的总结:
消息(Message)是指在应用之间传送的数据,消息能够很是简单,好比只包含文本字符串,也能够更复杂,可能包含嵌入对象。
消息队列(Message Queue)是一种应用间的通讯方式,消息发送后能够当即返回,有消息系统来确保信息的可靠专递,消息发布者只管把消息发布到MQ中而无论谁来取,
消息使用者只管从MQ中取消息而无论谁发布的,这样发布者和使用者都不用知道对方的存在。
推荐一个消息队列的中间件,你们有时间能够去了解:RabbitMQ
但愿可以帮到有须要的人。