当前位置: 首页 > news >正文

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

转载于:https://www.cnblogs.com/be-thebest/p/9988827.html

相关文章:

  • 实验05博客园总结
  • 华为S5700系列交换机配置通过Telnet登录设备
  • 4g伪基站如何实现的
  • logStash安装
  • 在树莓派上安装Ubuntu Core
  • Java国际化处理
  • 撩课大前端-面试宝典-第九篇
  • C# 后台获取前台交互判断
  • 《转》完美解决微信video视频隐藏控件和内联播放问题
  • 微信浏览器播放音频的问题:preload属性
  • Java并发编程之锁机制之(ReentrantLock)重入锁
  • Python:asyncio模块学习
  • Spring Security中异常上抛机制及对于转型处理的一些感悟
  • python学习记录-打印九九乘法表
  • Oracle数据库查看表空间是否为自增的
  • 77. Combinations
  • CSS3 变换
  • Eureka 2.0 开源流产,真的对你影响很大吗?
  • JavaScript/HTML5图表开发工具JavaScript Charts v3.19.6发布【附下载】
  • java第三方包学习之lombok
  • JS 面试题总结
  • scrapy学习之路4(itemloder的使用)
  • Spark VS Hadoop:两大大数据分析系统深度解读
  • vue--为什么data属性必须是一个函数
  • vue自定义指令实现v-tap插件
  • 关于extract.autodesk.io的一些说明
  • 理解在java “”i=i++;”所发生的事情
  • 算法-插入排序
  • 一、python与pycharm的安装
  • 用mpvue开发微信小程序
  • ​MySQL主从复制一致性检测
  • #多叉树深度遍历_结合深度学习的视频编码方法--帧内预测
  • $.type 怎么精确判断对象类型的 --(源码学习2)
  • (01)ORB-SLAM2源码无死角解析-(66) BA优化(g2o)→闭环线程:Optimizer::GlobalBundleAdjustemnt→全局优化
  • (TOJ2804)Even? Odd?
  • (vue)页面文件上传获取:action地址
  • (分布式缓存)Redis分片集群
  • (九)信息融合方式简介
  • (三)模仿学习-Action数据的模仿
  • (转)mysql使用Navicat 导出和导入数据库
  • .mat 文件的加载与创建 矩阵变图像? ∈ Matlab 使用笔记
  • .Net IE10 _doPostBack 未定义
  • .net MVC中使用angularJs刷新页面数据列表
  • .NET 使用 JustAssembly 比较两个不同版本程序集的 API 变化
  • .net和jar包windows服务部署
  • .net生成的类,跨工程调用显示注释
  • /usr/bin/env: node: No such file or directory
  • @Builder用法
  • @hook扩展分析
  • [2016.7 test.5] T1
  • [AndroidStudio]_[初级]_[修改虚拟设备镜像文件的存放位置]
  • [AX]AX2012 R2 出差申请和支出报告
  • [BUG] Authentication Error
  • [C#]winform使用引导APSF和梯度自适应卷积增强夜间雾图像的可见性算法实现夜间雾霾图像的可见度增强
  • [CQOI 2010]扑克牌