PHP消息队列学习
在我们平常网站设计时,会遇到“给用户群发短信”,“商城订单系统大批量订单处理”,“商城秒杀活动”等需求,这些功能,都有一个共同的特点:就是在面对高迸发的同时,必须要保证系统处理数据的有效性。那么如何处理这些数据,“消息队列”就是很好的选择。
接下来我们主要了解以下知识:
1.队列是什么东西?它能做哪些事情?
2.队列的应用场景有哪些?
3.如何使用队列对业务进行解耦?
4.如何使用redis队列来缓解系统压力?
一、认识消息队列
1.1 消息队列概念
从本质上来说消息队列就是一个队列结构的中间件,就是说消息放入(即入队)这个中间件之后可以不马上处理,而等待另外一个程序进行处理读取(出队)这些消息数据,并且按照顺序逐次处理。也就是说你的遇到一个并发特别大而且耗时特别长,还不需要马上进程处理返回结果的功能时,可以使用消息队列解决此类问题。
1.2 核心结构
由一个业务系统进行入队,把消息逐次插入到消息队列中,插入成功之后直接返回成功结果,然后另一个消息处理系统,这个系统会把消息系统中的记录逐次读取出来并进行处理,完成出队流程。

1.3 应用场景
数据冗余:比如商城的订单系统,后续需要严格可靠的进行数据转换和记录,消息队列可以把这些订单数据持久化存储在队列中,如果队列中有订单数据,则后续处理程序进行获取,后续处理完之后将队列中与该条订单对应的元素删除,这样就能保证每条订单都能被有效处理,以下是一些消息队列常见的使用场景。
系统解耦:软件开发尽量做到“高内聚,低耦合”,使用消息队列之后,可以做到入队系统和出队系统相互分开,互不影响,假如入队系统出现故障崩溃,出队系统不受影响,依然能够正常运作。
流量削峰:例如商城秒杀和抢购,可以配合缓存来使用消息队列,能够有效顶住瞬间的高访问量,防止服务器因承受不住压力崩溃。
异步通信:消息发送之后,如果消息入队成功之后可以直接返回发送成功。
扩展性:商城订单队列,不仅可以处理订单,还可以给其他业务使用,比如下单成功之后,必然为其生成一条快递派送订单。
排序保证:有些场景需要按照产品的顺序进行处理,比如单进单出从而保证数据按照一定的顺序处理,可以使用消息队列。
1.4 常见队列的实现优缺点
队列介质:
1、数据库,比如mysql(可靠性高,容易实现,数据量大时速度慢)
2、缓存,例如redis(速度快,单个消息报包过大时效率低)
3、消息系统,例如rabbitMq(专业性强,可靠,学习成本高)
消息处理触发机制:
1、死循环方式读取:易实现,故障时无法及时恢复。(比较适合做秒杀,比较集中,运维集中维护)
2、定时任务:压力均分,有处理上限;可选择用户访问量低时段减小服务器压力;目前比较流行的处理触发机制。(唯一缺点是间隔和数据需要注意,不要等上一个任务还没有完成下一个任务又开始了)
3.守护进程:类似于php-fpm和php-cg,需要shell基础
二、解耦案例:队列处理“订单系统”和“配送系统”
对于订单流程,我们可以设计两个系统,即“订单系统”和“配送系统”。在网购中我们都知道,当我们下单之后,在我的订单中可以看到我的货物正在配送中,这时就要参与进来一个“配送系统”。如果在架构时把“订单系统”和“配送系统”设计在一起,就会出现一些问题。对于订单系统来说,因为系统压力较大,但是“配送系统”却没有必要即时做出反应;第二个,我们不希望在订单系统出现故障时,配送系统也无法运行,这个时候两个系统就会相互影响正常运转。所以我们要把两个系统的耦合度降到最低。这个可以用“对列表”来实现两者之间的沟通。
2.1 架构设计

1、首先订单系统接收到用户的订单,然后进行订单的处理。
2、然后会把这些订单信息写到对列表中,这个对列表是沟通订单系统和订单系统的关键。
3、由配送系统定时执行的一个程序来读取队列进行处理。
4、配送系统处理之后,会把已处理的记录进行标记处理
2.2 程序流程

三、流量消峰案例:Redis 的 list 类型实现秒杀/抢购活动
redis 基于内存,它的速度非常快,redis对数据库有一个非常好的补充作用,因为它是可持久化的,redis会周期性把数据写到硬盘中,因此它不需要担心断电问题,redis提供了5种不同的数据类型(字符串,双向表链,哈希,集合,有序集合)。
一般情况下,做秒杀案例,抢购,瞬间高并发,需要排队的案例中,redis是一个很好的选择。
3.1 redis数据类型中的list类型
redis 的list 是一个双向链表,可以从头部或者尾部追加数据。
* LPUSH/LPUSHX :将值插入到(/存在的)列表头部
* RPUSH/RPUSHX: 将值插入到(/存在的)列表尾部
* LPOP : 移除并获取列表的第一个元素
* RPOP: 移除并获取列表的最后一个元素
* LTRIM: 保留指定区间内的元素
* LLEN: 获取列表长度
* LSET: 通过索引设置列表元素的值
* LINDEX: 通过索引获取列表中的元素
* LRANGE: 获取列表指定范围内的元素
3.2 架构设计

1、首先记录哪一个用户参与了秒杀同时记录他的时间。
2、将用户的id存到redis列表中,让它排队。如果规定只有前10个用户可以参与活动,如果列表中个数已经够了就不会让它继续插入数据。这样redis的列表长度就为10个。
3、最后慢慢的将redis中的数据写入到数据库中,以减小数据的压力。
3.3 代码初级设计
1、当用户开始参与秒杀时,将秒杀程序的请求写入Redis(uid, time)中。
2、假如只有10个人可以秒杀成功,检查Redis已经存放数据的长度,达到上限后不再插入,说明秒杀已完成。
3、最后循环处理存入Redis中的10条数据,然后慢慢取数据存入到数据库中。
在秒杀这一块对数据库压力特别大,如果我们直接在用户发起秒杀请求时,每次都查询数据库是否已经达到秒杀人数上限的话,会造成数据库压力巨大。现在通过Redis的一个队列list,然后把秒杀请求放入到Redis里面,最后将秒杀成功的数据通过入库程序写入到数据库,这样的话会极大缓解mysql的压力。
本文参考来自:https://www.cnblogs.com/dump/p/8243868.html
PHP消息队列学习的更多相关文章
- Rabbit五种消息队列学习(一) – 总述
RabbitMQ支持五种消息传递类型,分别如下图所示: 上图中显示6中消息队列分别为: 1.简单队列 一个生产者将消息放到队列中,一个消费者监听队列 2.工作队列(Work queues) 一个生产者 ...
- RabbitMQ五种消息队列学习(三)–Work模式
由于在实际应用中,简单队列模型无法解决很多实际问题,而且生产者和消费者是一对一的关系.模型较为单一.故引入Work模式. 结构图 一个生产者.多个消费者. 一个消息只能被一个消费者获取. 测试实现: ...
- Rabbit五种消息队列学习(二) – 简单队列
队列结构图 P:消息的生产者 C:消息的消费者 红色:队列 生产者将消息发送到队列,消费者从队列中获取消息. 测试 1.连接MQ public static Connection getConnect ...
- NSQ:分布式消息队列学习记录
参考资料: NSQ:分布式的实时消息平台 初识NSQ分布式实时消息架构 深入NSQ之旅 nsq topic和channel的区别
- 消息队列——RabbitMQ学习笔记
消息队列--RabbitMQ学习笔记 1. 写在前面 昨天简单学习了一个消息队列项目--RabbitMQ,今天趁热打铁,将学到的东西记录下来. 学习的资料主要是官网给出的6个基本的消息发送/接收模型, ...
- Linux进程间通信IPC学习笔记之消息队列(SVR4)
Linux进程间通信IPC学习笔记之消息队列(SVR4)
- skynet源代码学习 - 从全局队列中弹出/压入一个消息队列过程
学习云风的skynet源代码,简单记录下. void skynet_globalmq_push(struct message_queue * queue) { struct global_queue ...
- 【框架学习与探究之消息队列--EasyNetQ(1)】
前言 本文欢迎转载,实属原创,本文原始链接地址:http://www.cnblogs.com/DjlNet/p/7603554.html 废话 既然都是废话了,所以大家就可以跳过了,这里是博主有事没事 ...
- 【框架学习与探究之消息队列--EasyNetQ(2)】
声明 本文欢迎转载,系博主原创,本文原始链接地址:http://www.cnblogs.com/DjlNet/p/7654902.html 前言 此文章,是承接上篇:[框架学习与探究之消息队列--Ea ...
随机推荐
- Vue.extend动态注册子组件
写本篇文章之前其实也关注过vue中的一个关于加载动态组件is的API,最开始研究它只是用来实现一个tab切换的功能,使用起来也蛮不错的. is 预期:string | Object (组件的选项对象) ...
- Oracle 取上周一到周末的sql
-- 这样取的是 在一周内第几天,是以周日为开始的 select to_char(to_date('20131005','yyyymmdd'),'d') from dual; --结果:7 注释:20 ...
- 内核的执行头程序head.S
功能 定义data段和text段 重新手动初始化gdt表, idt表, tss表结构 初始化页表和页目录 --> 页目录的数据放在一个页表中 在页目录中, 其实地址为0x1000, 初始化页目录 ...
- Rspec基本语法
引用链接:http://reverocean.iteye.com/blog/1489957 1. describe和context describe和context方法用来组织相关的行为example ...
- flask --db-Column属性
db.Column 中其余的参数指定属性的配置选项. 选项名 说 明 primary_key 如果设为 True,这列就是表的主键 unique 如果设为 True,这列不允许出现重复的值 index ...
- 属性(property)与成员变量(ivar)
类内使用成员变量{}, 类外使用属性@property /*********** --- Person.h */ @interface Person : NSObject { NSString *_n ...
- Java面向对象的练习。动物乐园
本次项目是:以面向对象的思想设计动物乐园系统. 动物乐园中有猫,狗,鸭子等成员,还可以增加新成员. 猫和鸭子都有自己的名字,都有自己的腿,但腿的条数不同,猫和鸭子会发出叫声,猫的叫声是:喵喵喵……,鸭 ...
- ios微信浏览器音乐自动播放
setTimeout(function(){ //一般情况下,这样就可以自动播放了,但是一些奇葩iPhone机不可以 document.getElementById('bgmedia').play() ...
- windows mysql忘记密码解决方案
因为mysql很久之前装的,今天突然想用的时候发现密码不记得,怎一个尴尬了得,所以没办法,只能修改一个新的密码. 在此过程中遇到了几个问题 1.没法进入数据库: 2.修 ...
- jQuery_3_过滤选择器
过滤选择器(过滤器)类似于CSS3里的伪类,包含 1. 基本过滤器 2. 内容过滤器 3. 可见性过滤器 4. 子元素过滤器 5. 其他方法 一. 基本过滤器 过滤器名 jQuery语法 注释 :f ...