ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
## 队列 ![](http://cdn.aipin100.cn/17-10-15/51482813.jpg) 为了更好的学习,分享知识,我在segmentfault上建立了一个技术圈子:[php队列](https://segmentfault.com/g/1570000010691466) * * * * * ### php-resque分析 [PHP的轻量消息队列php-resque使用说明](https://avnpc.com/pages/run-background-task-by-php-resque) 1. 允许处理多个队列工作,用逗号分隔,*标示处理所有队列 2. 允许定义工作进程是否使用阻塞的模式(默认为false,表示阻塞),和阻塞时间间隔(默认为5秒,不能为0) 3. 允许开启多个工作进程(子进程的形式)来工作,默认是启动一个工作进程 4. 每个工作进程通过死循环来实现“常驻进程”,“守护进程”的效果 5. 工作进程是怎么获取队列和执行工作的呢,实际上工作进程也会开辟子进程(死循环开辟),“执行队列工作”在其子进程中完成,获取队列在自身进程中完成,在分析这里面之前先来了解下这个: > 工作进程通过lpop和blpop两种方式来弹出左边的一条工作队列(队列任务),之所以会以两种方式来从队列中弹出一条工作信息是有意义的,下面来分析: 先来看获取队列时使用到的两个方法: 1. [blpop](http://doc.redisfans.com/list/blpop.html)的第二个参数会使用到阻塞的时间间隔,也就是以阻塞的方式获取队列 2. [lpop](http://doc.redisfans.com/list/lpop.html)虽然没有使用到,但是在工作进程中使用usleep阻塞了 > 总结:不管blocking为true还是为false,不阻塞还是阻塞,其实都会阻塞的,这是在没有新队列时,在有队列时都不会阻塞(唯一的阻塞大概就是lpop时redis的并发处理阻塞吧,猜测,还在了解redis)这是为了最大化队列工作的效率 上面总结是事实,那具体代码中是怎么做到的呢,下面揭秘: 1. 获取工作时,如果发现blocking为true即非阻塞时,则采用blpop查询,blpop的特点是如果没有数据,则阻塞,有数据则与lpop无异。否则blocking为false即阻塞时,则采用lpop查询,没有阻塞。 2. 接下来如果有队列则往下执行,如果,没有队列,并且blocking为false即阻塞时那就使用usleep阻塞。 关键的部分我们大概分析完了,现在有几个问题? 1. 获取队列是在工作进程中进行的,而“执行队列工作”是在工作进程的子进程完成的,也就是说做到了没有让队列工作执行阻塞工作进程,一般也我们也假设队列工作的执行是最耗时的部分,比如发短信,和发邮件,而获取队列,虽然可能是redis的并发阻塞,但是redis是内存是数据库,所以还是很快的,那么是不是有可能造成工作进程开辟很多子进程呢,并且队列工作的执行很耗时,那么造成大量的子进程在运行,会不会将服务器拖垮呢?因为这个子进程的数量没有得到控制。 2. 为什么我们获取队列工作时每次只获取一条呢,为什么不获取多条呢,下面分析获取多条与单条的优缺点比较: ## 获取多条: * 好处: 1. 减少数据库的查询次数,下面再循环执行工作就可以 2. 减少开销,用最少的进程完成工作,减少进程的开辟数量,提升性能 * 坏处: 1. 获取多条数据的时间相对慢 2. 怎么加锁呢,不管是悲观还是乐观锁,增加维护的成本 3. 一个工作进程中循环执行多次队列任务(有可能多个不同的工作队列),内存得不到及时的释放,这样会消耗更多的性能和时间(队列工作的执行时相互阻塞的),即使将每个队列工作都放在子进程中,那也更得不偿失,嵌套开辟子进程过多,性能更没保证。 ## 获取单条: * 好处: 1. 获取单条快,加锁容易 2. 每次执行一个队列工作,管理容易,维护方便 3. 每次执行一个队列工作,符合队列的快进快出原则,尽早执行完,尽早释放,有更好的性能 * 坏处: 1. 消费执行相同数量的队列工作需要操作数据库的次数增多,影响性能 2. 消费执行相同数量的队列工作需要开辟维护的进程的数增多,影响性能 3. 每个工作进程通过死循环来实现“常驻进程”,“守护进程”的,这样长时间工作有没有性能问题呢,比如内存释放等,如果再MVC框架中还会有更大的性能开销呢,如果不用在MVC框架中,但是我们的工作业务逻辑很重,很依赖框架啊,这个么办法解决呢? 4. redis会不会导致数据丢失呢?每次好像没有考虑队列工作的执行结果啊,弹出后如果执行没有成功,这个问题怎么解决? #### 先来看第一个问题 > 如果第一个问题php-resque没有好的办法解决,或者它没有想到这个问题,没有考虑过这个问题,那我们只能盼望队列工作的执行相对于取队列来说消耗很短的时间了,我们把取队列需要消耗t时间,消费执行队列工作需要消耗t2时间,我们只能盼望t2相对于t慢不了太多,也就是说我们t2要很快才行,t2-1越大意味着我们越担心会出问题,如果越小则说明系统越稳定,越健康。(可是我们怎么能够赌上这一把呢,怎么能够期待它呢,这很不靠谱好吧!) ### 解决问题1: [pcntl_wait](http://php.net/manual/zh/function.pcntl-wait.php) wait函数挂起当前进程的执行直到一个子进程退出或接收到一个信号要求中断当前进程或调用一个信号处理函数。 如果一个子进程在调用此函数时已经退出(俗称僵尸进程),此函数立刻返回。子进程使用的所有系统资源将 被释放。关于wait在您系统上工作的详细规范请查看您系统的wait(2)手册。 这样的话就不用担心这个问题了,在子进程为完成前,会把父进程阻塞住,也就不会出问题了。这跟用不用子进程其实是一样的,但是这样的好处是更灵活。 #### 用生活中的例子来说明队列的使用场景,并做分析与对比。 队列要效率就要多进程,就像生活中的例子,公交站很多人,每个人要想快点回家,只有来更多的公交车才行,但这里要注意一点,马路要宽,要同时容纳或者同时能走两辆车才行,如果马路只能同时有一辆车走那就没意义了。 这也就是多进程不会阻塞的意义。 但是还有一个问题,即使执行队列是多进程不阻塞,但是获取队列缺失阻塞的,总不能并发给用户发多次通知短信吧,所以阻塞还是有的,只不过这里的阻塞时间很短很短,这就没问题。而执行队列如果阻塞,那不敢想象,就像马路一次只能走一辆车(假设马路的承重有限),来再多车都没有意义。 看一个典型容易出错的问题:队列工作阻塞和这个例子类似吗? 如果我们用循环,不用子进程就相当于生活中,多辆公交车来站台载人,其实这就说错了不严谨,因为多辆公交车可以“并行”啊,就算马路只能很窄只能容纳一辆车通行,第二辆车也可以跟在后面啊,所以这并不叫阻塞好吧!其实这就很尴尬了,既不能并行,后面的车只能跟在前面的车的屁股后面,也不算是程序里面的串行的意义,这种情况真是尴尬,它没有体现并行的效率,但也不是串行的低效率,既不是真正意义上的并行,也不是真正意义上的串行,反正程序里面是不会有这样的情况的。程序里面只有绝对的并行和绝对的串行,现实生活中简直是被玩坏了。 所以在此严谨的定义下: * 串行:马路很窄只能有一辆公交车,且马路的承重是一辆车的重量,两辆车会会把马路压塌的所以每辆车上路时都会检查马路上有没有车,必须保证任何时候马路上最多只能有一辆车。 * 并行:马路很宽,承重不止一辆车,能同时在上面跑很多车(跟在屁股后面那种形式已经被我们干掉了,不用考虑了,不允许这样的情况),或者有很多条马路,每个人从站台开始,决定上哪一辆,走哪条路。 说了这么多其实是要先指出“把队列工作,并行,串行,多进程,对应到现实生活中的例子时”容易犯的一个尴尬错误。 指出这个问题后,以后我们说的每种情况都不会在去纠结这个问题了,永远不会再包含种情况了,并行就是同时发多辆车可以绝对并行与程序代码并行意义一致,串行就是发一辆车与程序串行意义一致,意味着我们默认声明了不包含这种情况了!请知晓,别说没警告你哦。 现在我们问题就会明朗很多了,多进程就是同时发多辆车,单进程就是发一辆车,可以看出我们还有一个问题没有解决,那就是别人怎么上车啊,上车有阻塞吗? 用lpop的话其实是有阻塞的,这个阻塞是必要的,这就相当于是,公交站有一个叉装的通道,只有一个入口,叉装通道通道每个车里面去,这个唯一的入口每次只能通行一个人,两个人是挤不过去的。 其实还有一个比如更恰当,假设这些公交车会来抢人的,并且乘车的人都是按先来后到顺序排队的,这些公交车就按照这个顺序抢排在前面先来的人,但是这么多人抢,总不能把一个人扯死五马分尸吧,所以lpop内部应该是阻塞的。 也就是说上车是阻塞的,有没有办法实现上车不阻塞呢? 还真有!**取模。** 在thinkPHP社区看到的使用定时任务system方式“多进程”,这其实不算多进程,这还是串行阻塞的方式的,每个队列工作只能前一个执行完毕,后面一个才能执行,这是串行阻塞。 但是他那里面有一个思想还可以,就是巧妙的用了乐观锁(id%count=i),保证每个进程(他说的进程,其实不是多进程),不会相互取到对方的队列信息,并且是每次取多条队列,这个思想还是可以的。 [队列应用场景,自己实现队列【附视频和代码】 - ThinkPHP框架](http://www.thinkphp.cn/topic/14728.html) ~~~ 本次公开课讲的队列,不是一种数据结构,而是一个业务逻辑的处理方法。 作为一个WEB开发人员,想象一下这样的场景:你的网站平均一个用户有一百多个好友,他们要给友好群发消息。假设每发送一条消息的相关操作,需要耗时0.1秒,发送一百多条,就需要十几秒。肯定不能让用户点了“发送”按钮之后在那等着发消息吧。这些耗时的操作,我们都是在后台运行,甚至是在专门的队列程序服务器上运行,而不能让这些耗时的操作影响用户体验。 同样的场景还有很多,比如邮件队列,任务队列,Feed队列等等。 怎么处理这些队列呢,本次课讲讲解一个低成本,易操作,易部署的方法:数据库+轮询程序,还会涉及到一些小技巧,比如,如何用多进程快速执行队列,如何监测队列等等 ~~~ 虽然他这个是假多进程,但是我们可以利用这个思想,用真多进程实现出来。 不过这个是MySQL的,如果是redis可能不太好实现吧,并且这样有一个问题,那就是不好维护,如果突然需要增加进程或者减少进程,不可贸然的改变进程数量,否则会乱,会出问题的,这涉及到队列重新分配的问题,所以必须要关闭所有进程,等所有进程执行完毕后才能操作,管理,这就很麻烦了,也就是说管理很不方便,维护麻烦。 这个问题留着慢慢讨论,其实redis的lpop的阻塞效率应该很高了,我们将阻塞最厉害的部分,队列工作的执行部分并行掉了,这个地方阻塞其实没多大问题的哈。 还是想将这个问题分析完,上面那个“队列分流”问题管理麻烦到底是哪里麻烦呢,id%count=i这里count是确定了的,也以为着所有的id都被分配好了,不论未知的id是否有被加进来,它都已经被早早的安排好的。只能唯一的被管理count的这个进程管理,如果这个管理"count"的是一个脚本,i是它开辟的子进程,那么则这个脚本只能有一个启动一次,否则会出问题,出什么问题呢,并发的问题,将导致你可能会受到多条提示短信,这是我们不愿看到的。 如果突然要增加进程或者减少呢,需要重新分配“队列分流”就可能造成问题,那怎么解决这个问题呢,两个办法,一是控制源头,暂停所有队列的写入,让队列全部执行完,此时关闭守护进程,调整参数,重新启动,一般不采取这钟方案,这会导致这段时间内的队列无法使用,丢失,不能使用队列。第二种方式可平滑变动,无需停掉队列服务,即软关闭守护进程(直接杀死进程可能会出问题),这就需要在代码中增加钩子提前做好控制了,工作进程都关闭后再关闭守护进程,调整参数,重新启动,这样就能平滑的过渡了。基本没有什么影响,只是会在关闭工作进程到重新启动这个期间队列服务有一点的演示而已。 乐观锁虽然好,但确实在有些时候确实会给管理维护带来麻烦。 [什么是一致性Hash算法?](https://www.toutiao.com/a6533182504579367431/?tt_from=weixin&utm_campaign=client_share&timestamp=1521306221&app=news_article_lite&utm_source=weixin&iid=25315997380&utm_medium=toutiao_android&wxshare_count=1) > 主要体现在服务器数量变动的时候,所有缓存的位置都要发生改变!(求模,机器数量发生变化了就得重排,之前全部失效,效率太低了。) * * * * * ### 分析完php-resque后再来分析think-queue **这个还没看完,但大概分析了一下,感觉结构还是比php-resque弱很多,但是自定义功能加强了(可能仅适于MySQL吧),下面总结几点:** 1. 不支持多进程,没有要求支持ext-pcntl扩展 2. 守护进程也是靠死循环做的,支持阻塞延时 3. 单进程本来就是阻塞的,每次循环都会sleep阻塞 4. 每次获取一条队列信息,采取开启事务,加悲观锁,取一条,立即改变状态,然后提交事务,释放锁的方式 5. 支持添加延迟任务到队列 6. 队列任务有超时时间,机制是每次一个队列执行完毕后就sleep,没有php-resque的智能机制 7. 支持任务执行失败的捕获 8. 支持重新发布(超时/失败)任务 **队列中两个重要的东西:** **多进程:** php-resque依靠PHP的ext-pcntl扩展做的 **常驻/守护进程:** php-resque和think-queue都是用死循环(thinkPHP论坛那个帖子用的是crontab定时器) (启动脚本时,SSH->bash 关闭窗口后就关闭进程了,这个用nohup常驻就行了) 最后记录:2016-8-16 12:13:07 * * * * * ### 扩展 **什么放队列,什么不放队列,有什么原则?** 本来立即要做,但是当前做太耗时,不适应网页这种快速处理,快速响应的场景,并且可以允许适当的延后执行(那些当前必须做的事就在本次就做了,做的过程中客户端处于等待的状态,做完后再响应),即使队列执行失败也不会影响到程序逻辑,对程序整体不会产生错误,这样的事可以放到队列。比如下单发短信。 只要满足这个原则的都可以当队列,反之就不适合当队列,要考虑其它方法了。 有一类事情,需要定时去检查,去做的不适合放队列。这个适合定时任务。 比如关闭超时订单,这个需要扫订单表,将超时订单找出来处理。 记住这些情况可以结合队列使用,两者可以一起使用,已经说了只要满足队列的使用原则就可以使用它。 实际上队列也是一个定时程序。 还有一种算是任务类的,比如给全站所有用户推送消息。 队列程序,一般最好一个队列程序监控某一类或者某几类任务,比如一个程序专门监控短信任务,只负责发短信。 那么上面的说的给所有用户发信息的任务算是一个比较耗时长时间执行的任务了,这个可以让一个队列程序专门监控这类任务的任务队列。 一个队列程序又可以多进程并行处理队列任务,这样就能加快处理速度。 update:2016-12-6 14:19:46 * * * * * **有两种观点:** 1. 队列处理程序为了性能有时候没必要完全引入整个MVC 2. 如果不引入MVC的话,那就相对独立了,系统配置什么的,环境,自动加载,数据模型等,这就很不方便了。 当然如果框架系统考虑到了队列,CLI那么提供一种CLI模式运行环境,那也是极好的。 另外需要注意的一个问题就是,假设a程序是处理程序,那么现在每个几秒钟去运行一次a还是运行a,在里面死循环比较好。**(这个和php的运行模式和生命周期有关,例子是Laravel和Swoole,下面有探讨。)** 如果每隔几秒去运行a,那就相当于另外的程序去主动调用a了(命令行/自动任务等),那么就要注意不能重复调用a,不能多个其他程序都去调用了a,这可以做一个文件锁来保证a同一时间内只能被调用一次,也就是不允许并发执行。死循环的话,一个脚本太长时间执行,担心影响性能,出现内存泄露,并且死循环不能是“死的”,需要提供可以控制的能力,可以停止执行,这可以用文件锁/配置/信号处理之类的来做到。不能强行的对处理程序做“热插拔”,否则如果再处理重要任务时异常中断就可能会出现意外。 还要有监控的能力,知道程序是否执行了,最后的执行时间,执行日志等。 所以两种方法各有优点和缺点,如果取其中间,调用&程序内循环,增加调用间隔,循环增加限制(可以是执行时间,也可以是循环次数),超过自动退出。 记住任何时候,最好的就是最合适的。 [队列的思考 · php笔记 · 看云](https://www.kancloud.cn/xiak/php-node/504497) > 可以在控制器方法中启动队列监听,这样整个生命周期就只有一次框架环境实例了,但是配置文件的更改,任务的修改可能得不到更新,因为已经引入内存中了,所以当配置或任务文件更改后需重新重启监听。 * * * * * ### 扩展 - [原创 | 消息中间件的工作原理和RabbitMQ入门](https://mp.weixin.qq.com/s/r8k1TN46Pk61qTjZ8ljsEQ) - [think-queue队列这个怎么用呢](http://www.thinkphp.cn/topic/42388.html) - [thinkphp-queue 笔记](https://github.com/coolseven/notes/blob/master/thinkphp-queue/README.md) - [php调用外部exe程序-CSDN论坛](http://bbs.csdn.net/topics/390270857) - [PHP调用外部程序的方法](http://blog.csdn.net/whatday/article/details/54880851) - [PHP在linux上执行外部命令](http://www.cnblogs.com/wumingcong/p/5899046.html) - [消息队列 云消息 订阅管理监控 分布式应用-阿里云](https://www.aliyun.com/product/ons) - [1分钟实现“延迟消息”功能 - 架构师之路 | 十条](http://www.10tiao.com/html/249/201703/2651959961/1.html) > 这里把我想到的几个问题全部说出来了,“后知后觉”的问题,和重复执行的问题,还是做架构的人牛逼,哈哈。 - [深入理解php底层:php生命周期](http://blog.csdn.net/hguisu/article/details/7377520) - [Python3之多进程](http://www.toutiao.com/a6439858194382962945/?tt_from=weixin&utm_campaign=client_share&app=news_article&utm_source=weixin&iid=11683717705&utm_medium=toutiao_android&wxshare_count=1) - [进程与线程的一个简单解释 - 阮一峰的网络日志](http://www.ruanyifeng.com/blog/2013/04/processes_and_threads.html) - [Linux 守护进程的启动方法 - 阮一峰的网络日志](http://www.ruanyifeng.com/blog/2016/02/linux-daemon.html) - [极客漫画:不要使用 SIGKILL 的原因(看哭了)](http://www.toutiao.com/a6454826726273843726/?tt_from=weixin&app=news_article&iid=12619555732&wxshare_count=1) - [关于PHP连接处理中set_time_limit()、connection_status()和ignore_user_abort()深入解析 - 很多时候,你缺少的不是知识而是热情 - CSDN博客](http://blog.csdn.net/jiao_fuyou/article/details/17138057) ~~~ php种也是一样,默认`ignore_user_abort(false)`也没有给代码处理后续工作的机会,但是`register_shutdown_function()`可以做一些收尾工作(比如日志保存之类的,不过也不能优雅的控制代码中进程回收问题)。 ~~~ - [【rabbitMQ 用法】 - Hongyang - CSDN博客](http://blog.csdn.net/lmj623565791/article/category/2386657) - [「服务器」RabbitMQ入门教程——简介及工作原理](https://www.toutiao.com/a6512994463378309645/?tt_from=weixin&utm_campaign=client_share&timestamp=1516444347&app=news_article&utm_source=weixin&iid=22069500288&utm_medium=toutiao_android&wxshare_count=1) - [计算机底层知识拾遗(四)理解文件系统 - zdy0_2004的专栏 - CSDN博客](http://blog.csdn.net/zdy0_2004/article/details/44259313) [Q新闻丨Go 语言排行飙升至前十;GitHub 已切换到 Kubernetes;陆奇最新内部演讲:如何成为一个优秀的工程师?](http://mp.weixin.qq.com/s/pboTbWevEWoN2FJEQgtcKA) ~~~ 默默维护 30 年,glibc 创始人兼维护者辞职 GNU C library (glibc) 项目原作者兼维护者 Roland McGrath 宣布辞职和退出该项目,原因与家庭或其它问题无关,而是因为 30 年了该放手了。1980 年代,Roland 当时还是一名十多岁的青少年,他在为自由软件基金会工作期间开发了最早的 C 函数库。 他在邮件列表上表示,他过去几个月故意保持沉默,不回应任何邮件,看看这个项目还需不需要他这位维护者,结果证明 glibc 项目没有他仍然能继续前进,因此他决定辞职和不再直接参与 glibc。今年夏天将迎来 glibc 诞生三十周年的纪念。Roland 对所有帮助和参与 glibc 项目的人表示感谢,称有许多人对项目做出的贡献比他更大。 ~~~ [在WordPress中使用wp-cron插件来设置定时任务](http://www.jb51.net/article/76183.htm) [PHP实现执行定时任务的几种思路详解 - Web烤猫 - SegmentFault](https://segmentfault.com/a/1190000002955509) [基于Laravel Task-Scheduler定时发送邮件小程序 - 来生做个漫画家 - SegmentFault](https://segmentfault.com/a/1190000005057786) [Laravel 5.2 文档 服务 —— 任务调度 – Laravel学院](http://laravelacademy.org/post/3267.html) [详解PHP实现定时任务的五种方法_php技巧_脚本之家](http://www.thinkphp.cn/topic/42571.html) > 定时运行任务对于一个网站来说,是一个比较重要的任务,比如定时发布文档,定时清理垃圾信息等,现在的网站大多数都是采用PHP动态语言开发的,而对于PHP的实现决定了它没有Java和.Net这种AppServer的概念,而http协议是一个无状态的协议,PHP只能被用户触发,被调用,调用后会自动退出内存,没有常驻内存。 [PHP 实现定时任务的几种方法 - ThinkPHP框架](http://www.thinkphp.cn/topic/42571.html) [PHP实现定时任务的几种方式-PHPChina开发者社区-权威的PHP中文社区](http://www.phpchina.com/portal.php?mod=view&aid=41051) [php 定时任务_百度搜索](https://www.baidu.com/s?wd=php+%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1&ie=utf-8&rsv_cq=php+%E5%8D%95%E4%BE%8B&rsv_dl=0_right_recommends_20807&euri=5c209d60170a7167991896a99f87be1f) * * * * * ### 思考、求证、求问 进程通信,事件回调,事件通知,计算机内部难道就是个“死循环”实现的吗,只不过是优化的“死循环”而已,本质还是“死循环”,如果这样,那么真正意义上的【实时】其实根本就不存在了啊,看来这些东西需要了解计算机的原理,系统底层,内核才能真正理解,窥见程序的魅力啊。(注意这里的引号,真正的死循环是不可控的,也就是BUG) 参考:[究竟能不能用死循环?或者其实我们就活在一个死循环的世界中?](https://segmentfault.com/q/1010000009586182) > 死循环不如说元循环和其他循环一样有始有终,只不过其他循环是元循环的一段,走过就没了,死循环走过了回到了原点。 ***** #### 什么是实时? 实时是指两个对象,发送者,响应者,发送者发出消息后,响应者立即/同时得到信息,这就是实时。可以说事件发生时间与消息接收时间是同一时刻(两个事件同时发生)。 那么计算机的实时是怎么样的呢? 我们知道时间刻度是可以无限细分的,也就是不存在绝对的,只有相对的。 而理论上电路的通断,处理是需要时间的,只不过很短。(可以想象你按下灯泡开关,到亮灯的例子,你认为灯泡通电和你按下开关是不是同时的) 所以真正的实时,从技术上来说,计算机应该无法做到。 软件无法实现实时,软件的实时反馈其实本质也是来自于硬件的,比如硬盘磁头已经准备好了,网卡收发数据完毕了等等。 **任何事物都不能脱离它所存在的环境而存在。** 但是大多时候,我们可以认为它是实时的,至少对我们感觉上来说是实时的。 因为我们的大脑是需要反应时间的,即使简单的膝跳反应,神经反应也是需要时间的,比如如果人的反应在100ms左右,那么只要在100ms左右的反应,我们人都可以认为是实时的,因为再快的话,人的大脑也捕捉不到,就没有意义了。所以是否真正的实时,对我们来说并不需要纠结,继续钻牛角尖纠结没有意义。 所以很多东西都是相对的,要结合人去看待其它事物,以人为本。 ![](http://cdn.aipin100.cn/18-1-7/90810005.jpg) > 生活中也有同步/同时的例子,比如电机内部齿轮上的那个皮带(套在两个齿轮上),叫做同步带,显然,一个齿轮转动时通过同步带来带动另一个齿轮转动,两个齿轮是同时,同步转动的。 >[danger] **同步带 是现在我唯一能找到的,可以证明两个事件是同时发生(并行)的案列。** (你还知道哪些其它生动的例子,期待你的留言!) [用世界上最强的电子显微镜看原子 简直大开眼界](https://www.365yg.com/a6554838150886195726) [0.999…=1吗?无穷小量的数学史_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili](https://www.bilibili.com/video/av43969456) * * * * * [你手机CPU到底如何工作的!科普手机内部CPU工作原理! - 今日头条](http://www.365yg.com/item/6456519526136676878/) [你知道CPU是如何工作的? - 今日头条](http://www.365yg.com/item/6414455349574631937/) CPU就是一个死循环,里面有一个时钟,按照一个固定频率通断电路(每隔一段时间做某件事),这个频率就是CPU的主频,单位为赫兹。所以本质其实就是一个死循环。 * * * * * [你必须理解的计算机核心概念](https://mp.weixin.qq.com/s/XmHhlZzpYbJWW_m5NMPqEw) [一文告诉你什么是实时操作系统?就连Windows也不是实时操作系统](http://www.toutiao.com/a6434715971818651906/) [深入实时 Linux](http://www.toutiao.com/a6445229605447975182/) [怎么去证明两个是事件是在同一时刻发生的?](https://segmentfault.com/q/1010000009908203) [普朗克时间_百度百科](https://baike.baidu.com/item/普朗克时间/2429708?fr=aladdin) [普朗克长度和普朗克时间的存在是否意味这个宇宙可能是虚拟的? - 知乎](https://www.zhihu.com/question/29294919) [同时性_互动百科](http://www.baike.com/wiki/同时性) 任何东西都是相对的,世界上的任何事情都是相对的,没有绝对的,你觉得一秒钟过得有多快,树懒的一秒钟又有多慢,哈哈哈哈。 [Facebook“发明”了新的时间单位:1秒=705600000 Flicks](https://www.toutiao.com/a6514077852609020423/?tt_from=weixin&utm_campaign=client_share&timestamp=1516906187&app=news_article&utm_source=weixin&iid=22069500288&utm_medium=toutiao_android&wxshare_count=1) ~~~ Q:怎么证明两个事件是同时发生的,或者说,时间的最小刻度是多少? A:普朗克时间,是指时间量子间的最小间隔,即普朗克时间,为 1E-43秒(即10^-43s)。没有比这更短的时间存在。普朗克时间=普朗克长度/光速。(注:1普朗克时=0.0000000000000000000000000000000000000000001秒) (理论上存在,实际上却无法证明,那就只有出一个标准了,这个标准若要所有人信服,就必须是当前人类认知的极限 —— 量子) ----------- Q:关灯后,灯光到哪里去了? A:光是电子/原子跃迁时释放能量时产生的光子,关灯以后,光子被屋子里的环境所吸收了,如果你小时候玩过会发夜光的玩具你就明白了,小时候我们把夜光玩具放在灯光下照,然后关灯后就可以在躲在被窝里面乐呵了。 ---------- Q:光速是不是宇宙中最快的? A:是,也不是。在人类已知的宇宙中,光速是最快的,不过量子学打破了这一理论,还有超光速和快子的存在,其速度远大于光速,不过由于无法实验证明它,所以无法确定,毕竟这超出了宇宙的因果关系,而宇宙也是我们认知的一撇而已。 ~~~ http://www.ruanyifeng.com/blog/2020/10/weekly-issue-130.html > 德国科学家发现迄今为止最短的时间:光穿过一个氢分子耗时为10-21秒。 * * * * * **php的运行模式和生命周期** [Laravel的核心概念 - SegmentFault](https://segmentfault.com/p/1210000007162144) [为什么Swoole可以加速php - daryl的技术天地 - SegmentFault](https://segmentfault.com/a/1190000009486485) * * * * * [关于PHP协程与阻塞的思考](http://mp.weixin.qq.com/s/WxcP_ghWyY3kWoPi_8dC8w) * * * * * [linux kill php进程,对PHP的生命周期产生怎样的影响?](https://segmentfault.com/q/1010000005030126) 题主如果是想控制php的死循环,不想用命令行,也不想用信号,那么通过“配置”也是可以做到的,配置可以是文件,可以数据库存储的值,相当于开关: 开始时间 = 当前时间 生命周期时间 = 300 ~~~php while(ture) { if task.lock 不存在 退出 else 执行业务逻辑 } ~~~ 题外话:其实这种循环是可控的,不是真正的死循环,就算是真正的死循环可能也是有作用的(如事件循环),如果无法控制的死循环,意外造成的死循环,那才是真正的BUG,所以以前学校老师说:“不要写出死循环代码,那是最严重的BUG,会消耗完机器内存”,那句话其实不严谨! * * * * * [为什么Socket被翻译为“套接字”? - 简书](http://www.jianshu.com/p/2515266051ea) > 服务器就像一个大插排,包含很多插座,客户端就是像一个插头,每一个线程代表一条电线,客户端将电线的插头插到服务器插排上对应的插座上,就可以开始通信了。 [Http Server : 一个差生的逆袭](http://mp.weixin.qq.com/s/WO2GuaUCtvUFWIupgpWcbg) [互联网为什么要提供套接字?-痞子高的回答-悟空问答](https://www.wukong.com/answer/6486678019279683854/?iid=12619555732&app=news_article&share_ansid=6486678019279683854&wxshare_count=1&tt_from=weixin&utm_source=weixin&utm_medium=toutiao_android&utm_campaign=client_share) * * * * * **图灵是完备的,函数是一等公民。** [什么是图灵完备? - 知乎](https://www.zhihu.com/question/20115374) [2017 年你应该学习一下下函数式编程 - 知乎专栏](https://zhuanlan.zhihu.com/p/26608727) * * * * * **记录** 队列说到底关键的就是要消费任务,而任务一定是存在某个地方被消费者取出来消费执行的,如果想要提高处理大量任务的速度,就必须增加消费的工人数量。 那么问题就来了: 1. 任务储存在哪里效率高? 2. 如何解决多工人进程取任务时出现重复取出了,造成任务被重复执行了,也就是并发问题? ~~~ 1. 取出一条任务 2. 执行任务 3. 标记该任务被处理 如何避免消费工人的并发问题 ~~~ 其实问题就出在取任务的地方,拿MySQL来说,如果用锁的话,那么就变成串行了,多个工人就完全没有意义了。 如果不用锁的话,可以 id / n 取整的方式处理任务(n为工人数量),这样可以解决并发问题,但是需要保证任务id的连续性和唯一性,并且当工人数量变动时,需要关闭系统,再重启队列系统,否则中途改变工人数量会导致任务分配混乱 **(因为在任何时候,一个正在运行的系统是动态的,有任务当前正在执行,而系统无法知道是哪些任务,所以在贸然一个正在运行的动态的系统中做任何操作都是危险的)。** 如果用redis来做是不是能完美解决这个问题呢,也就是取任务的问题呢,redis是怎么取的呢? 待分析…… 2017-8-18 00:31:55 * * * * * ### 队列总结 **队列主要的难点问题:** 1. 消息存要高效 2. 怎么监听到有新的消息来了?(事实上并不能监听到新消息来了,没有那么智能,只能用蠢办法,死循环,好吧我不说“死循环了”,就说循环,或者是无限循环,可控的循环吧) 3. 怎么安全高效的取消息(安全:多工人,也就是多进程取消息时不会出现重复取消息,不然如果是转账的消息,如果出现重复执行的话,多次转账,那就完蛋了,还有执行完毕后,消息应该标记为已处理,并且任务处理失败的话,要记录日志和状态等详细信息,以便于加到重试队列或者有其它作用;高效:取消息效率必须要高,不能出现select那种扫表,如果循环扫表的话那就很悲催) 4. 怎么管理,常驻工人进程(怎么启动维护后台常驻程序,怎么有效的管理多工人进程,比如工人数量的增减同时还要保证服务正确,不会错乱) 5. 怎么高效的让工人根据消息内容找到任务执行者,并让它执行。(一般任务执行者和工人是部署在同一个服务器的,任务执行者因为可能需要DB操作,或者其它操作,所以最好是保证和我们框架是一样的环境,怎么让它在框架的cli环境下执行,并且要高效,因为如果和web访问模式一样每次访问都要走一遍框架的初始化流程,那效率就太低了,所以要改变这种模式,让框架环境只初始化一次,让任务执行者在里面执行就可以了。) **通过对队列的分析,我们看到要做好队列服务,至少5个有以上的难点需要思考和解决的。** [聊架构:使用Redis队列解决商品数据大批量上传问题](http://www.toutiao.com/a6399982285475938561/?tt_from=weixin&utm_campaign=client_share&app=news_article&utm_source=weixin&iid=12619555732&utm_medium=toutiao_android&wxshare_count=1) [Apache Kafka:下一代分布式消息系统](http://www.infoq.com/cn/articles/apache-kafka) * * * * * [Raft 为什么是更易理解的分布式一致性算法 - mindwind - 博客园](http://www.cnblogs.com/mindwind/p/5231986.html) [raft算法与paxos算法相比有什么优势,使用场景有什么差异? - 知乎](https://www.zhihu.com/question/36648084) [春晚抢微信红包如何实现 - 腾讯云分布式消息队列CMQ架构](http://www.toutiao.com/a6333075051169399041/?tt_from=weixin&utm_campaign=client_share&app=news_article&utm_source=weixin&iid=12619555732&utm_medium=toutiao_android&wxshare_count=1) * * * * * last update:2017-9-11 15:12:49 * * * * * **Redis为队列存取而生** Redis实现队列重要的一点解决了存和取的问题,存很快,取弹出队列(`blpop: 客户端阻塞直到队列有值输出`),注意是**阻塞弹出队列的,即阻塞取消息的**,这意味着多工人进程也没事,多工人时不会出现重复取消息,不会出现并发问题,是安全的,这就方便多了,要是用mysql存消息,为了防止并发问题,保证不会出现重复取消息,那处理起来就麻烦多了,需要开启事务用锁,每次limit 1,扫表,多进程间的锁等待,真是不敢想象的恐怖,超级超级的低效率。所以Redis真爽,一下子就解决了队列中最头痛的问题,简直是为队列消息存取而生的。 [Redis 实现队列 · php笔记 · 看云](https://www.kancloud.cn/xiak/php-node/399425) last update:2017-9-9 18:43:02 * * * * * [从Timer类源码分析,猜想今日头条的取消推荐文章的技术实现](https://www.toutiao.com/i6488636316970910222/?tt_from=weixin&utm_campaign=client_share&app=news_article&utm_source=weixin&iid=12619555732&utm_medium=toutiao_android&wxshare_count=1) > 你那个死循环合不合适啊 * * * * * **没错就是“死循环”(无限循环)** [张大胖的socket - 码农翻身](http://mp.weixin.qq.com/s/XmWVy2ARauSBoehygs4Zvw) ![](https://box.kancloud.cn/0ec9e1e0038299c3ae58b099c5fca4fe_359x565.png) * * * * * [到底什么时候该使用MQ?](http://mp.weixin.qq.com/s/LqViglTO_h8UJqi3aD6P6w) [MQ,互联网架构解耦神器](http://mp.weixin.qq.com/s/2PFd4xQ9F9S_9g23WtyFGw) * * * * * [redis 队列应用实例](https://segmentfault.com/q/1010000011410596) ~~~ 1 : 你说的有点忽悠人,其实就是死循环,或者说是无限循环,可控的循环吧。有消息就一直循环不等待,无消息就控制一下循环的频率,睡眠5秒钟继续循环。 阻塞是redis客户端取消息的原子操作,这个是redis保证的,这样就不会出现多进程重复消费消息的问题了。不过你要理解最终在redis中是原子操作的,也就是串行的。 至于消费失败的情况,可以做一个记录,记录失败的消息,再根据情况,比如重试机制。 php有一个来源的队列库。以上就是从那里分析来的。 当然还有更好的商用队列产品,这个就不细说了。 ~~~ [消息队列应用场景 - 13070113 - 博客园](http://www.cnblogs.com/stopfalling/p/5375492.html) > 按照以上约定,用户的响应时间相当于是注册信息写入数据库的时间,也就是50毫秒。**注册邮件,发送短信写入消息队列后,直接返回,<span style="color:red;">因为写入消息队列的速度很快,基本可以忽略</span>**,因此用户的响应时间可能是50毫秒。因此架构改变后,系统的吞吐量提高到每秒20 QPS。比串行提高了3倍,比并行提高了两倍。 [消息队列使用的四种场景 - CSDN博客](https://blog.csdn.net/ntotl/article/details/72765713)(原文) * * * * * [重磅资料!Github上的PHP资源汇总大全 - 资讯/编程 - 极思维](http://www.topthink.com/topic/8309.html) **队列** ——处理事件和任务队列的库 [Pheanstalk](https://github.com/pda/pheanstalk): 一个Beanstalkd客户端库 [PHP AMQP](https://github.com/videlalvaro/php-amqplib): 一个纯PHP AMQP库 [Thumper](https://github.com/videlalvaro/Thumper): 一个RabbitMQ模式库 [Bernard](https://github.com/bernardphp/bernard): 一个多后端的抽象库 [php-amqplib/php-amqplib: The most widely used PHP client for RabbitMQ](https://github.com/php-amqplib/php-amqplib) [php-amqplib/Thumper: PHP Library that implements several messaging patterns for RabbitMQ](https://github.com/php-amqplib/Thumper) [pda/pheanstalk: PHP client for beanstalkd queue](https://github.com/pda/pheanstalk) [beanstalkd首页、文档和下载 - 轻量级消息队列 - 开源中国社区](http://www.oschina.net/p/beanstalkd) [kr/beanstalkd: Beanstalk is a simple, fast work queue.](https://github.com/kr/beanstalkd) * * * * * [为什么使用mq?-淮安二傻子的回答-悟空问答](https://www.wukong.com/answer/6481088357995643150/?iid=12619555732&app=news_article&share_ansid=6480998431820087566&wxshare_count=1&tt_from=weixin&utm_source=weixin&utm_medium=toutiao_android&utm_campaign=client_share) * * * * * >[danger] MQ其实也是一种异步编程模型的实现方式,它解耦了相互独立的业务模型。 * * * * * [2.7 消息队列 - 51CTO.COM](http://book.51cto.com/art/201412/462303.htm) 消息队列对电商平台特别是大型电商平台来说是不可或缺的部分,电商平台中的众多操作,如邮件发送、短信发送、商品属性更改后需要通知各类促销模块,以及执行时间较长的insert/update/delete等,这些操作如果在小型站点中使用同步方式处理姑且可以容忍,但在大型平台中,由于用户量、访问量特别大,使用同步处理会造成站点的堵塞,用户可能需要等待很长时间,有的甚至会直接超时。但如果只是简单将操作都改成js异步触发,同样不是很好的解决办法,用户需要发出js请求并等待返回,大量异步js请求同样会造成系统的压力猛增,直至堵塞,所以将这些费时但又不需要立刻完成的请求放入一个队列中,然后由队列来执行这些任务,在将任务放入队列后,用户不需要等待任务的执行,而是继续进行下面的操作,这样极大提高了用户体验。 * * * * * 分布式、锁、一致性、调度、队列、延时、Broker、task、worker、…… ***** [消息队列 - 如何实现php的异步任务队列 - SegmentFault 思否](https://segmentfault.com/q/1010000000186204) [请教PHP+Redis实现任务队列的思路 - SegmentFault 思否](https://segmentfault.com/q/1010000007207389) ```php // 堵塞等待队列中第一个和$uuid匹配的(到我了) while($uuid != $redis->lGet($tsk_name, 0)){ if((time()-$time_start)> $time_out) { break; // 超时跳出(某些原因队列异常了, 可能永远取不到) } usleep(10); // sleep 10ms, 再次尝试 } ``` >[tip] 阻塞获取就没问题(没有数据会阻塞着不返回,当有数据了就马上返回),如果没有这点的话,那和传统那样一直循环查询有什么区别,那样性能太低了,就没什么意义了。 ***** ### 开源项目 [resque/php-resque: An implementation of Resque in PHP.](https://github.com/resque/php-resque) >[tip] Package chrisboulton/php-resque is abandoned, you should avoid using it. Use resque/php-resque instead. [一个简单的定时任务 · Thinkphp5.1学习笔记 · 看云](https://www.kancloud.cn/hideblue/thinkphpnotebook/853526) > 逻辑代码中,请不要使用exit、die、sleep语句 [定时任务调度系统 opencron](https://www.toutiao.com/a6622156995799548419/) [Quartz使用总结 - 路边飞 - 博客园](https://www.cnblogs.com/drift-ice/p/3817269.html) > Quartz就是来干这样的事,你给它一个触发条件的定义,它负责到了时间点,触发相应的Job起来干活。 [pheanstalk/pheanstalk: PHP client for beanstalkd queue](https://github.com/pheanstalk/pheanstalk) [beanstalkd/beanstalkd: Beanstalk is a simple, fast work queue.](https://github.com/beanstalkd/beanstalkd) [有赞延迟队列设计](https://tech.youzan.com/queuing_delay/) [mysql - PHP定时通知、按时发布怎么做? - SegmentFault 思否](https://segmentfault.com/q/1010000009508176?_ea=4975839) [chenlinzhong/php-delayqueue: 基于redis实现高可用,易拓展,接入方便的延迟队列](https://github.com/chenlinzhong/php-delayqueue) [Kafka中的时间轮算法](https://mp.weixin.qq.com/s/DDfPQgxDQz814BYB-LfzdA) > 我觉得可以写多个轮子,一个放一分钟内要执行的任务,每秒检查一次,一个放一个小时内要执行的任务,每个分钟检查一次,以此类推,一百年的任务也只要 60+24+365+100,内存完全没问题。不过我好奇的是怎么写这个定时检测的代码…… 1 作者 > 起一个定时器去扫就行了 [PHP: Queue - Manual](http://php.net/manual/zh/class.ds-queue.php) [resque/resque: Resque is a Redis-backed Ruby library for creating background jobs, placing them on multiple queues, and processing them later.](https://github.com/resque/resque) [chrisboulton/php-resque: PHP port of resque (Workers and Queueing)](https://github.com/chrisboulton/php-resque) [tangshuang/php-cron: 实现PHP Cron,也就是PHP定时任务,通过本地文件记录schedules,然后通过fsockopen实现非阻塞式的后台访问对应的url来实现定时任务,通过sleep实现定时,如果错过任务,则通过用户访问来执行该任务(还未完善)](https://github.com/tangshuang/php-cron) [lisijie/webcron: 定时任务管理器](https://github.com/lisijie/webcron) [kcloze/queueSwoole: 基于swoole的微型框架,适合于高并发场景下的抢购/秒杀业务场景](https://github.com/kcloze/queueSwoole) [yunwuxin/think-cron: 计划任务 for thinkphp5](https://github.com/yunwuxin/think-cron) [notes/README.md at master · coolseven/notes](https://github.com/coolseven/notes/blob/master/thinkphp-queue/README.md) [huyanping/php_crontab: A crontab written in PHP based on pcntl and react/event-loop](https://github.com/huyanping/php_crontab) [mawenpei/swoole-crontab: 基于swool实现的crontab,兼容linux的crontab格式,并且支持秒级](https://github.com/mawenpei/swoole-crontab) [xuxueli/xxl-job: A lightweight distributed task scheduling framework.(分布式任务调度平台XXL-JOB)](https://github.com/xuxueli/xxl-job) [kohkimakimoto/workerphp: A PHP micro job scheduler framework like cron.](https://github.com/kohkimakimoto/workerphp) [jobbyphp/jobby: Manage all your cron jobs without modifying crontab. Handles locking, logging, error emails, and more.](https://github.com/jobbyphp/jobby) [george518/PPGo_Job: 定时任务管理-支持多台服务器](https://github.com/george518/PPGo_Job) [Automattic/kue: Kue is a priority job queue backed by redis, built for node.js.](https://github.com/Automattic/kue) [symfony/process: The Process component executes commands in sub-processes.](https://github.com/symfony/process) [php + Laravel 实现部署自动化](http://mp.weixin.qq.com/s/qZGVdNtCJOycR_sye9az6w) [qq8044023/taskPHP: taskPHP基于原生态php开发的定时计划任务框架,利用多进程实现任务的分配和运行,利用原生态php内存共享实现进程间通信,支持linux和windows。有较好的伸缩性、扩展性、健壮稳定性而被多家公司使用,同时也希望开源爱好者一起贡献。](https://github.com/qq8044023/taskPHP) [top-think/think-worker: ThinkPHP5 Workerman extend](https://github.com/top-think/think-worker) [justlive1/earth-frost: 分布式任务调度框架](https://gitee.com/justlive1/earth-frost?from=20180429) [SegmentFault/SimpleFork: 一个最精简的php多进程控制库](https://github.com/SegmentFault/SimpleFork) [从0到1优雅的实现PHP多进程管理 - 掘金](https://juejin.im/post/5a1ff1396fb9a0451704fb42) [\[Node\]\[Agenda\]Node Agenda 中文文档 定时任务调度系统\[基础篇\] - CSDN博客](https://blog.csdn.net/github_36749622/article/details/76595489) [Redis 还能做实时订阅推送功能?原谅我无知...--文末送书](https://mp.weixin.qq.com/s/ECvC9-sMv94ce4Hw3HSZhA) [实战:消息中间件,解耦、异步、削峰,到底该如何使用](https://mp.weixin.qq.com/s/jswWojRQkXgHraEZeIntlg) [分布式调度框架Quartz衍生出的三种任务类型,你用过几个?](https://mp.weixin.qq.com/s/j7iA0nPCK94HFUpgekRTJg) [究竟什么时候该使用MQ?](https://mp.weixin.qq.com/s/_kXoRBAotb4GXoDTqTObYQ) [Sprint Boot如何基于Redis发布订阅实现异步消息系统的同步调用?](https://mp.weixin.qq.com/s/7C1noGWEUFNArhrGzVUFDA) [为了kafka概念扫盲,写了万字长文(我看完吐了)](https://mp.weixin.qq.com/s/M8V77F4Fc4bhOm_LP5YjCQ) [一般电商应用的订单队列架构思想](https://mp.weixin.qq.com/s/ZTrBQwKjdoK_OMackUX1Qw) [「ThinkPHP开发者周刊」第39期——消息队列](https://www.kancloud.cn/thinkphp/weekly/1173591) [浅谈redission以及Redis分布式锁探索入门](https://mp.weixin.qq.com/s/noIpTGWeRFBqK1pPltDtVA) [网易云音乐的消息队列改造之路](https://mp.weixin.qq.com/s/Q48LvBZaoBRP5Y5NIG7upA) [同样是消息队列,为什么Kafka这么快?](https://mp.weixin.qq.com/s/5pPjUOfAH6IN7cXMgMvoKw) [从这个角度,我终于理解为什么需要Kafka这样的东西了!](https://mp.weixin.qq.com/s/ghFDVMCacgYuTcG5klxTiw) [Python 源码分析:queue 队列模块](https://mp.weixin.qq.com/s/_TxlIF037dlTphYae2GcWw) [经典得不能再经典的分布式服务和消息队列面试题](https://mp.weixin.qq.com/s/OUt077Y4INNn_Q-3cjWxOA) [Java并发编程之阻塞队列](https://mp.weixin.qq.com/s/6XXpPykDtFfnAgnEXrZLKA) > 消息被消费的顺序性不能依赖于队列系统,最好在业务里面解决掉 > 队列的brck和任务调度器对业务系统来说都属于第三方,不能依赖于它 [关于消息队列的思考](https://mp.weixin.qq.com/s/g5Qq_gasJbDFVfOYkZaPcg) > Message Broker 可能不可靠,但是任务消费的状态记录必须可靠,这才是实现最终一致性的保证。 [五分钟入门消息中间件](https://mp.weixin.qq.com/s/AQDmjICPmwbR_t9ayOsdkw) [1分钟实现“延迟消息”功能](https://mp.weixin.qq.com/s/eDMV25YqCPYjxQG-dvqSqQ) [世上最全的RabbitMQ-总结](https://mp.weixin.qq.com/s/0cX6o3QVygxhOTK4uxWFPw) [如何快速实现“延时消息”?](https://mp.weixin.qq.com/s/9qt3JEvjv1wka57GBTng9g) [定时和延时问题在业务场景中的常见处理](https://mp.weixin.qq.com/s/2hvuI4z1HXZ6EFqKTkTGiA) [我所知道的数据结构之队列](https://mp.weixin.qq.com/s/0p4oovNTtUsqV9SvUQHuyA) [非常强悍的 RabbitMQ 总结,写得真好!](https://mp.weixin.qq.com/s/Xx2A9-EGHgQtLg8MyCiB-Q) [RabbitMQ 七战 Kafka,五胜二负,差异立现!](https://mp.weixin.qq.com/s/c_o5HIsQKVQmC6aiCtU8bg) * * * * * ### 相关课程 [PHP消息队列实现及应用-慕课网](https://www.imooc.com/learn/852) [Beanstalkd-带你玩转消息队列-慕课网](https://www.imooc.com/learn/912) [php+mysql 模拟队列发送邮件-慕课网](https://www.imooc.com/learn/721) [Redis课程简介,Redis的Lua脚本编程教程-慕课网](https://www.imooc.com/learn/1039) [redis计数器与数量控制](http://www.imooc.com/learn/1067) [开源消息队列QMQ的设计与实现理念](https://mp.weixin.qq.com/s/Jz8OXPHnC3Cs22vPubZ9pQ) [MQ消息队列应用场景比较介绍](https://mp.weixin.qq.com/s/pq9wCA-IL2SWixoJikeSxw) [Kafka基本原理](https://mp.weixin.qq.com/s/t_NGK7WY6FygCdWoayUHZQ) [【消息队列 MQ 专栏】消息队列之 RabbitMQ —— 集群原理与搭建篇](https://mp.weixin.qq.com/s/lvXwN-KejP2KrRLEOh-Q8w) [【消息队列 MQ 专栏】RabbitMQ](https://mp.weixin.qq.com/s/F2XTL9QFO0P4zNDExMx6Cg) [【系统架构】聊聊开源消息中间件的架构和原理](https://mp.weixin.qq.com/s/NwjYJde9_TC4PXMPpYw1Gw) [网站架构之消息队列(MQ)简述](http://toutiao.com/group/6552863131087929864/?iid=31395168747&app=news_article_lite&timestamp=1525748634&wxshare_count=1&tt_from=weixin&utm_source=weixin&utm_medium=toutiao_android&utm_campaign=client_share) > 请求 治标不治本 [消息队列背后的设计思想](https://mp.weixin.qq.com/s/k8sA6XPrp80JiNbuwKaVfg) [面试官:给我一个避免消息重复消费的解决方案?](https://mp.weixin.qq.com/s/xW8vjzmrGZ-yNYdPsiACsQ) ***** [阿里云免费套餐-企业版](https://free.aliyun.com/?open_id=928e888d-52df-40e3-ac87-a1360365866d-37062509&open_cid=910)(试用队列) * * * * * last update:2018-2-6 15:08:27