- 浏览: 159258 次
- 性别:
- 来自: 南京
文章分类
- 全部博客 (158)
- 每天工作日志 (64)
- php工作遇到技术难题记录 (4)
- linux成长记录 (17)
- web前端开发记录 (12)
- SQL成长记录 (16)
- joomla开发记录 (0)
- 开发工具使用记录 (1)
- vpn简单安装 (0)
- 直接查询字段结果进行以逗号分隔,不用在php代码中进行foreach循环处理 (1)
- phalcon项目搭建 (1)
- java项目实践 (5)
- share everythings (0)
- Mac工作记录 (3)
- 闲文杂谈 (6)
- 细说javascript面向对象 (0)
- 瞎几把扯 (2)
- Shell编程学习与分享 (0)
- GO语言开发 (5)
- angular2 (1)
- Go开发 (3)
- java开发 (15)
最新评论
-
弹指一世界:
感谢博主分享,但是我把项目下载下来放本地运行报了一个错误Exc ...
php phalcon项目实战 -
xialluyouyue:
...
php xmlrpc的简单实用
PHP消息队列实现及应用
- 博客分类:
- 每天工作日志
https://www.cnblogs.com/dump/p/8243868.html目前对消息队列并不了解其原理,本篇文章主要是通过慕课网学习归纳的一些笔记,为后续学习打下基础。
众所周知在对网站设计的时候,会遇到给用户“群发短信”,“订单系统有大量的日志”,“秒杀设计”等,服务器没法处理这种瞬间迸发的压力,这种情况要保证系统正常有效的使用,就需要“消息队列”的帮助。本篇主要通过消息队列的思路进行学习。
主要了解如下知识:
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使用的是同步阻塞,而消息服务器使用的是异步非阻塞。
众所周知在对网站设计的时候,会遇到给用户“群发短信”,“订单系统有大量的日志”,“秒杀设计”等,服务器没法处理这种瞬间迸发的压力,这种情况要保证系统正常有效的使用,就需要“消息队列”的帮助。本篇主要通过消息队列的思路进行学习。
主要了解如下知识:
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使用的是同步阻塞,而消息服务器使用的是异步非阻塞。
发表评论
-
shell脚本--sed的用法(转)
2019-12-06 10:50 264本文链接:https://blog.csdn.net/wdz3 ... -
Javascript 面试核心考点(转)
2019-06-26 16:53 392Javascript 面试核心考点(转) 原文链接 ht ... -
Java注解(Annotation)
2019-02-21 09:42 251一、认识注解 注解 ... -
Java Socket编程
2019-02-21 09:40 271Java最初是作为网络编程 ... -
MySQL中单句实现无限层次父子关系查询
2019-02-19 14:08 2261在 SQL Server 中,使用 CTE 表达式很容易做到无 ... -
Nginx中fastcgi_pass的配置问题
2018-12-26 16:19 932Nginx和PHP-FPM的进程间通信有两种方式,一种是TCP ... -
php rsa加密解密实例(转)
2018-06-01 11:23 365php服务端与客户端交互、提供开放api时,通常需要对敏感的部 ... -
远程管理项目部署(lamp)@Author:Tim Lu
2018-05-08 16:57 418远程管理项目部署(lamp)@Author:Tim Lu 切 ... -
PHP语言 fopen()函数不能打开文件的问题
2018-04-17 11:14 967架了一个Apache服务器,文件目录为/var/www/,今天 ... -
Ubuntu下PHP安装C扩展
2018-04-13 09:04 597一、服务器环境 - Ubuntu 16.04.2 LTS x ... -
linux的nohup命令的用法。
2018-01-04 15:33 375在应用Unix/Linux时,我们一般想让某个程序在后台运行, ... -
golang fmt格式“占位符”
2017-06-01 10:24 459golang 的fmt 包实现了格式化I/O函数,类似于C的 ... -
golang笔记——struct
2017-05-27 08:40 6271、定义一个结构体 type User struct ... -
给MySQL增加mysql-udf-http和mysql-udf-json自定义函数,让MySQL有调用http接口和查询直接回JSON的能力
2017-04-21 14:04 16391、安装mysql-udf-httpyum install ... -
PHP通过Http Post请求发送Json对象数据
2017-03-26 21:47 725public static function httpP ... -
关于node.js和npm,cnpm的安装记录以及gulp自动构建工具的使用(转)
2017-02-08 14:33 738工作环境:window下 在一切的最开始,安装node.j ... -
Phalcon Mac|Window安装扩展
2016-12-05 17:12 1291Mac安装配置Phalcon扩展遇到问题: 在搭建以Ph ... -
自定义php按照指定key进行数组排序
2016-11-01 11:34 1743function sksort(&$array, $ ... -
统计MySQL中某个数据库中有多少张表
2016-10-09 16:09 581SELECT count(*) TABLES, table ... -
避免api以及项目后台调用数据重复,直接可以调用api信息测试
2016-09-14 16:09 617避免api以及项目后台调用数据重复,直接可以调用api信息测 ...
相关推荐
讲解消息队列用于解耦的案例,使用mysql的一个表,做为队列存储,来实现成中间件来解耦订单系统和配送系统。使用订单系统实时写入,并用定时任务启动配送系统的处理程序,对队列进行处理并标记结果,使两个业务系统...
主要介绍了PHP消息队列实现及应用,结合实例形式详细分析了php消息队列的概念、原理及队列处理订单系统和配送系统案例,需要的朋友可以参考下
本文实例讲述了PHP高级编程之消息队列原理与实现方法。分享给大家供大家参考,具体如下: 1. 什么是消息队列 消息队列(英语:Message queue)是一种进程间通信或同一进程的不同线程间的通信方式 2. 为什么使用消息...
RabbitMQ是由erlang语言开发,基于AMQP(Advanced Message Queue 高级消息队列协议)协议实现的消息队列,它是一种应用程序之间的通信方法,消息队列在分布式系统开发中应用非常广泛。 MQ 为Message Queue , 消息...
AMQP,即Advanced Message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。消息中间件主要用于组件之间的解耦,消息的发送者无需知道消息使用者的存在,反之亦然。 AMQP...
AMQP,即Advanced Message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。消息中间件主要用于组件之间的解耦,消息的发送者无需知道消息使用者的存在,反之亦然。 AMQP...
本文实例讲述了PHP PDO和消息队列的个人理解与应用。分享给大家供大家参考,具体如下: 什么是消息队列,百度百科说,···消息队列····是在消息的传输过程中保存消息的容器。 看着网上林林总总的文章,都说是...
现在memcache在服务器缓存应用比较广泛,下面我来介绍memcache实现消息队列等待的一个例子,有需要了解的朋友可参考。
本文实例讲述了PHP使用redis消息队列发布微博的方法。分享给大家供大家参考,具体如下: 在一些用户发布内容应用中,可能出现1秒上万个用户同时发布消息的情况,此时使用mysql可能会出现” too many connections”...
我们通过redis的有序集合zset来实现简单的延迟队列,将消息数据序列化,作为zset的value,把消息处理时间作为score,每次通过zRangeByScore获取一条消息进行处理。 <?php class DelayQueue { protected $prefix...
PHP消息队列的一些实现 目录: 消息队列的简介 性能测试 消息队列的简介 消息队列(Message Queue):把消息按照产生的次序加入队列,而由另外的处理程序/模块将其从队列中取出,并加以处理;从而形成了一个基本的...
php-resque是php环境中一个轻量级的队列服务。具体队列服务是做什么用的,请自行百度! ## 运行环境 ## * PHP 5.2+ * Redis 2.2+ ## 集成方法 ## ### 将源码放到ThinkPHP的Vendor目录中 ### 将源码更新到 ...
AMQP(高级消息队列协议)是一个异步消息传递所使用应用层协议规范,为面向消息中间件设计,基于此协议的客户端与消息中间件可以无视消息来源传递消息,不受客户端、消息中间件、不同的开发语言环境等条件的限制;...
上一篇我们写了如何用 Docker 部署 Laravel 应用,然后这一篇我们写一下如何部署含有队列以及任务调度的 Laravel 应用。 一、 我们首先准备一下我们的 docker/app.cron 文件 注意一下,文件最后的空行是必须的。 #...
软件开发设计:应用软件开发、系统软件开发、移动应用开发、网站开发Node.js、C++、Java、python、web、C#等语言的项目开发与学习资料 硬件与设备:单片机、EDA、proteus、RTOS、包括计算机硬件、服务器、网络设备、...
如果提供队列实现PHP项目开始采用这些通用标准,则使用MQPHP应用程序和项目可以依赖于通用接口,而不是特定的实现。 这促进了高级别的互操作性和灵活性,允许用户使用可以适应这些接口的任何MQ传输实现。 该项目中...
高级消息队列协议(AMQP)是一个异步消息传递所使用的应用层协议规范。作为线路层协议,而不是API(例如JMS),AMQP 客户端能够无视消息的来源任意发送和接受信息。现在,已经有相当一部分不同平台的服务器和客户端...
本文实例讲述了PHP队列用法。分享给大家供大家参考。具体分析如下: 什么是队列,是先进先出的线性表,在具体应用中通常用链表或者数组来实现,队列只允许在后端进行插入操作,在前端进行删除操作。 什么情况下会用...
本文实例讲述了PHP基于数组实现的堆栈和队列功能。分享给大家供大家参考,具体如下: 堆栈和队列是数据结构的两种实现形式,是使用非常广泛的存储数据的容器。下面呢,就分别讲下这两种容器在PHP中的应用: 一、使用...