PHP消息队列实现及应用
目前对消息队列并不了解其原理,本篇文章主要是通过慕课网学习归纳的一些笔记,为后续学习打下基础。
众所周知在对网站设计的时候,会遇到给用户“群发短信”,“订单系统有大量的日志”,“秒杀设计”等,服务器没法处理这种瞬间迸发的压力,这种情况要保证系统正常有效的使用,就需要“消息队列”的帮助。本篇主要通过消息队列的思路进行学习。
主要了解如下知识:
1、队列是个什么东西,他能干什么?
2、对列的应用场景有哪些?
3、如何使用队列对业务进行解偶?
4、如何使用Redis队列来消除高压力?
5、专业的对列系统RabbitMQ如何使用?
归纳如下主要内容
@消息队列的概念,原理和场景
@解耦案例:队列处理订单系统和配送系统
@流量削峰案例:Redis的List类型实现秒杀
@RabbitMQ:更专业的消息系统实现方案
一、认识消息队列
1.1 消息对列概念
从本质上说消息对列就是一个队列结构的中间件,也就是说消息放入这个中间件之后就可以直接返回,并不需要系统立即处理,而另外会有一个程序读取这些数据,并按顺序进行逐次处理。
也就是说当你遇到一个并发特别大并且耗时特别长同时还不需要立即返回处理结果,使用消息队列可以解决这类问题。
1.2 核心结构
由一个业务系统进行入队,把消息逐次插入到消息队列中,插入成功之后直接返回成功的结果,后续会有一个消息处理系统,这个系统会把消息系统中的记录逐次进行取出并进行处理,完成一个出队的流程。
1.3 应用场景
数据冗余:比如订单系统,后续需要严格的进行数据转换和记录,消息队列可以把这些数据持久化的存储在队列中,然后有订单,后续处理程序进行获取,后续处理完之后在把这条记录进行删除来保证每一条记录都能够处理完成。
系统解耦:使用消息系统之后,入队系统和出队系统是分开的,也就说只要一天崩溃了,不会影响另外一台系统正常运转。
流量削峰:例如秒杀和抢购,我们可以配合缓存来使用消息队列,能够有效的顶住瞬间访问量,防止服务器承受不住导致崩溃。
异步通信:消息本身使用入队之后可以直接返回。
扩展性:例如订单队列,不仅可以处理订单,还可以给其他业务使用。
排序保证:有些场景需要按照产品的顺序进行处理比如单进单出从而保证数据按照一定的顺序处理,使用消息队列是可以的。
以上都是消息队列常见的使用场景,当然消息队列只是一个中间件,可以配合其他产品进行使用。
1.4 常见队列实现优缺点
队列介质
1、数据库,例如mysql(可靠性高,易实现,速度慢)
2、缓存, 例如redis (速度快,单个消息报包过大时效率低)
3、消息系统,例如rabbitMq (专业性强,可靠,学习成本高)
消息处理触发机制
1、死循环方式读取:易实现,故障时无法及时恢复;(比较适合做秒杀,比较集中,运维集中维护)
2、定时任务:压力均分,有处理上限;目前比较流行的处理触发机制。(唯一的缺点是间隔和数据需要注意,不要等上一个任务没有完成下一个任务又开始了)
3、守护进程:类似于php-fpm 和php-cg,需要shell基础
二、解藕案例:队列处理“订单系统”和“配送系统”
简单说一下程序解耦:程序解耦就是避免出现你老婆和你妈同时掉到水里先去救谁的问题(偷笑ing)
对于订单流程,我们可以设计两个系统,一个是“订单系统” 另外一个是 “配送系统”, 在网购的时候我们应该都见过,当我提交了一个订单之后,我在后台可以看到我的货物正在配送中。这个时候就要参与进来一个“配送系统”。
如果我们在做架构的时候把 “订单系统” 和 “配送系统” 设计在一起的话就会出现一些问题,首先对于订单系统来说,因为系统的压力会比较大,但是 "配送系统" 没必要为这些压力做一些即时的反应。
第二个我们也不希望在订单系统出现故障之后导致配送系统也出现故障,这个时候就会同时影响到两个系统的正常运转。所以我们希望把这两个系统进行解耦。这两系统分开之后我们可以通过一个中间的 “队列表” 进行这两个系统的沟通。
2.1 架构设计
1、首先订单系统会接收用户的订单,然后进行订单的处理。
2、然后会把这些订单信息写到队列表中,这个队列表是沟通这两个系统的关键。
3、由配送系统定时执行的一个程序来读取队列表进行处理。
4、配送系统处理之后,会把已处理的记录进行标记。
2.2 程序流程
三、流量削峰案例:Redis 的 list 类型实现秒杀
redis 基于内存,它的速度会非常快,redis 对数据库有一个非常好的补充作用因为它是可持久化的,redis会周期性的把数据写到硬盘里,所以它不用担心断电的问题,从这方面说它比另一款缓存 memcache 更有优势些,另外 redis 提供五种数据类型(字符串,双向链表,哈希,集合,有序集合)
一般情况下,做秒杀案例,抢购,瞬间高并发,需要排队 的案例中 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_stamp)中。
2、假使规定只有10人可以秒杀成功,检查 Redis 已经存放数据的长度,超出上限直接丢弃说明秒杀完成。
3、最后在死循环处理存入Redis中的10条数据,然后在慢慢的取数据并存入到mysql数据库中。
在秒杀这一块对于数据库的压力特别的大,如果我们没有这样的设计,会造成mysql的写入瓶颈。我们通过Redis的一个对列list,然后把秒杀的请求放入到Redis里面, 最后通过入库程序,把数据慢慢的写入到数据库,这样的话就可以实现流量的均衡,对mysql不会造成太大的压力。
四、RabbitMQ
这里讲解一些RabbitMQ的使用,首先我们之前讲秒杀案例的时候提到了锁的机制,防止其他程序处理同一条记录,如果我们的系统架构非常的复杂,有多个程序实时的读取一个队列,或者我有多个发送程序,同时来操作一个或多个队列,甚至我还想这些程序分布在不同的机器上,这种情况下用redis队列就有些力不从心了。这种时候怎么办呢,我们就需要来引入一些更专业的消息队列系统,这些系统可以更好的来解决问题。
4.1 RabbitMQ的架构和原理
特点:完整的实现了AMQP,集群简化,持久化,跨平台
RabbitMQS使用
1、RabbitMQ安装 (rabbitmq-server, php-amqplib)
2、生产者向消息通道发送消息
3、消费者处理消息
工作队列
思想:由生产者发送给消息系统,消息系统把任务封装成消息队列之后,然后供多个消费者使用同一个队列
这不仅解决了生产者和消费者之间的解耦,还可以实现了消费者和任务的共享,减缓了服务器的压力。
五、总结
以上主要学习消息队列的概念,原理,场景。解耦案例以及削峰案例,以及了解RabbitMQ的简单使用方法。
六、问题
redis 和消息服务器 选择的最大区别是什么。
我的理解是Redis 是一个一个处理请求,redis属于单线程,它和消息服务器 IO 的实现方式不同,一个是同步一个是异步,而redis使用的是同步阻塞,而消息服务器使用的是异步非阻塞。
PHP消息队列实现及应用的更多相关文章
- 消息队列——RabbitMQ学习笔记
消息队列--RabbitMQ学习笔记 1. 写在前面 昨天简单学习了一个消息队列项目--RabbitMQ,今天趁热打铁,将学到的东西记录下来. 学习的资料主要是官网给出的6个基本的消息发送/接收模型, ...
- 消息队列 Kafka 的基本知识及 .NET Core 客户端
前言 最新项目中要用到消息队列来做消息的传输,之所以选着 Kafka 是因为要配合其他 java 项目中,所以就对 Kafka 了解了一下,也算是做个笔记吧. 本篇不谈论 Kafka 和其他的一些消息 ...
- .net 分布式架构之业务消息队列
开源QQ群: .net 开源基础服务 238543768 开源地址: http://git.oschina.net/chejiangyi/Dyd.BusinessMQ ## 业务消息队列 ##业务消 ...
- 【原创经验分享】WCF之消息队列
最近都在鼓捣这个WCF,因为看到说WCF比WebService功能要强大许多,另外也看了一些公司的招聘信息,貌似一些中.高级的程序员招聘,都有提及到WCF这一块,所以,自己也关心关心一下,虽然目前工作 ...
- Java消息队列--ActiveMq 实战
1.下载安装ActiveMQ ActiveMQ官网下载地址:http://activemq.apache.org/download.html ActiveMQ 提供了Windows 和Linux.Un ...
- Java消息队列--JMS概述
1.什么是JMS JMS即Java消息服务(Java Message Service)应用程序接口,是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送 ...
- 消息队列性能对比——ActiveMQ、RabbitMQ与ZeroMQ(译文)
Dissecting Message Queues 概述: 我花了一些时间解剖各种库执行分布式消息.在这个分析中,我看了几个不同的方面,包括API特性,易于部署和维护,以及性能质量..消息队列已经被分 ...
- Netty构建分布式消息队列(AvatarMQ)设计指南之架构篇
目前业界流行的分布式消息队列系统(或者可以叫做消息中间件)种类繁多,比如,基于Erlang的RabbitMQ.基于Java的ActiveMQ/Apache Kafka.基于C/C++的ZeroMQ等等 ...
- Netty构建分布式消息队列实现原理浅析
在本人的上一篇博客文章:Netty构建分布式消息队列(AvatarMQ)设计指南之架构篇 中,重点向大家介绍了AvatarMQ主要构成模块以及目前存在的优缺点.最后以一个生产者.消费者传递消息的例子, ...
- C#分布式消息队列 EQueue 2.0 发布啦
前言 最近花了我几个月的业余时间,对EQueue做了一个重大的改造,消息持久化采用本地写文件的方式.到现在为止,总算完成了,所以第一时间写文章分享给大家这段时间我所积累的一些成果. EQueue开源地 ...
随机推荐
- python format() 函数
转载 https://www.cnblogs.com/wushuaishuai/p/7687728.html 正文 Python2.6 开始,新增了一种格式化字符串的函数 format() ,它增强了 ...
- CentOS安装python3.6
下载Python安装包 cd /usr/local/src 编译时要提前装好gcc编译器和zlib zlib-devel 1.下载文件 wget https://www.python.org/ftp/ ...
- python学习日记(模块导入)
什么是模块? 常见的场景:一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀. 但其实import加载的模块分为四个通用类别: 1 使用python编写的代码(.p ...
- opencv debug版本在linux下编译,并写了一个DEMO
用如下方法编译opencv: git clone "https://github.com/opencv/opencv.git" mkdir opencv_debug cd open ...
- anacodna/python 安装 tensorflow
study from : https://www.cnblogs.com/HongjianChen/p/8385547.html 执行1-6 7 安装jupyter 每次使用tensorflow,都要 ...
- MFC:关联变量
1. 对象(控制)变量(control) a. 数据类型:control 只能创建关联一次 b). control 用来操控控件 c). 创建 control 变量:控件 -> 右击 -& ...
- 关于 redis 的 数据类型 和 内存模型
该文章 是在读了 公众号 : java 后端技术 之后 做的一个小记录 原文网址 : https://mp.weixin.qq.com/s/mI3nDtQdlVlLv2uUTxJegA 作者文章写的 ...
- Codeforces Round #554 (Div. 2) C. Neko does Maths(数学+GCD)
传送门 题意: 给出两个整数a,b: 求解使得LCM(a+k,b+k)最小的k,如果有多个k使得LCM()最小,输出最小的k: 思路: 刚开始推了好半天公式,一顿xjb乱操作: 后来,看了一下题解,看 ...
- python之路(7)装饰器
前言 装饰器:为函数添加附属功能,本质为函数 原则:不修改被修饰函数的源代码 不修改被修饰函数的调用方式 装饰器=高阶函数+函数嵌套+闭包 使用场景演示 定义下面函数 def cal(l): res ...
- UNIX域协议之描述符传递
一.mycat程序 #include <fcntl.h> #include <stdlib.h> #include <unistd.h> #define BUFFS ...