热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

用户请求队列化_消息队列知识点讲解

一、什么是消息队列?当我试图用一则通俗的比喻来说明这个概念的时候,我想到一个有意思的比喻:如果把队列抽象成一个集合体,那么消
一、什么是消息队列?
63f946d7d1d08471f49eae44023ca860.png

当我试图用一则通俗的比喻来说明这个概念的时候,我想到一个有意思的比喻:如果把队列抽象成一个集合体,那么消息队列也就是一堆消息的集合。按照这个思路我想到了「杂志」。这不就是一堆消息的集合吗,关心这些消息的人都能通过「购买」来获得这些消息,而我可以通过不同种类的「杂志」或许到不同的消息。并且如果我作为出版方,我可以提供所有出版过的「杂志」,也可以选择让读者只能购买近期的。

二、为什么需要消息队列?

好处一:解耦

假设我们做了一个会议室预定系统,我们的一个设备坏了。我们需要通知预定这个会议室的所有人,于是我们需要发邮件,伪代码如下:

@Servicepublic class EquipmentServiceImpl implements EquipmentService { @Autowired private EmailService emailService; @Autowired private EquipmentRepository equipmentRepository; public void setEquipmentBroken(Long id) { Equipment equipment = equipmentRepository.findById(id); equipment.setStatus(Equipment.StatusEnum.BROKEN); emailService.sendEmail(); }}

问题来了,如果我们后来发现设备坏了并且需要更改可用库存的数量,这时候我们是不是要在这里加入 InventoryService 库存服务的代码呢?后来如果经理说设备坏了应该通知他才对啊,所以我们要不要加入 emailService.sendEmailTo(Manager) 这样的代码呢?

随着我们业务模块接入越来越多,我们的代码与其他模块越来越耦合,修改代码的难度也指数级的增加,所以我们引入「消息队列」,把「设备坏了」这样的消息发送到队列中,其他关心这条消息的业务就会得到这样的「通知」,然后就会去做对应的事,这样各个模块之间就解耦了。伪代码看上去如下:

public void setEquipmentBroken(Long id) { Equipment equipment = equipmentRepository.findById(id); equipment.broken(); eventBus.publish(new EquipmentBrokenEvent(equipment.id));}

好处二:异步处理

接着上面的例子,假设我们已经把「发送邮件」、「修改库存」以及「通知经理」的代码都写入了我们的 Service 代码中,它们分别耗时:30ms、50ms、80ms,并且我们得知,原本最主要的功能其实是「发送邮件」,但我们完成主要的功能之后却等待了更多的额外时间,这显示是不合理的。

所以我们为了提高用户体验&提高吞吐量,我们其实可以引入「消息队列」来进行异步的操作。

好处三:削峰/限流

f6db9d3cd493f9ecc7f4b99218d380ea.png

假设我们的服务器最多能支持每秒 1000 个请求,而我们公司在节日要搞促销,为了避免服务器挂掉我们额外申请了两台服务器做了负载均衡,于是我们现在的机器最理想的情况能够支持每秒 3000 个请求,但奈何活动太火爆了,每秒来的请求有大概 4000 个,这些多出来的请求就可能导致服务器给直接挂掉了。

ca17395dada6fe742502b66f62a77f1e.png

所以我们就引入了一个「消息队列」,让消息不直接到达服务器,而是先让「消息队列」保存这些数据,然后让下面的服务器每一次都取各自能处理的请求数再去处理,这样当请求数超过服务器最大负载时,就不至于把服务器搞挂了。

三、消息队列适用的场景

基于上面的描述,我们大概能想到「消息队列」的局限性,例如当「生产者」需要「从消费者获得反馈」时,就会出现一定的问题。例如我之前尝试着使用「事件驱动」的方式编码时,我想要把 Service 的一些主逻辑给转移到关注该事件的监听器上时,发现有点问题,我原本的意图是想让一部分代码解耦,但作为主逻辑的一部分我需要保证它们准确的执行,当我使用「消息」的方式传递出去时,我无法得到消费者的反馈,所以最终我还是把主逻辑给迁回来了,算是一次失败的尝试吧。

场景一:异步处理

通过上述的问题你也看到了,「消息队列」适用于异步处理,并且是那些不期望从消费者得到反馈的处理。就好像一开始说到的设备坏了的问题,我只需要通知设备坏了,至于之后需要做什么事,关心的人自然会去做相应的处理。

场景二:日志收集

上面提到的异步处理,跟日志系统似乎搭配起来也很好。特别是当你需要把日志发往单独的数据平台的时候,「消息队列」尤为有用,我们不再需要在业务代码里面侵入我们的各种打点or日志,只需要简单的发布一条消息,再去关注做处理就好了。

场景四:应用解耦

基于上面的例子你应该也能感受一二了。

场景三:流量削峰

这也是「消息队列」常见的场景,通过引入「消息队列」,我们一来可以控制请求的人数,二来也可以缓解短时间内高流量的压力。

场景四:消息通讯

消息通讯是指,消息队列一般都内置了高效的通信机制,因此也可以用在纯的消息通讯。比如实现点对点消息队列,或者聊天室等。

四、常见消息队列中间件

如果自己设计一个?

我们在讨论市面上常见的「消息队列」中间件之前,我们先来考虑自己造一个怎么样?如果是你自己来设计,你会怎么做?乍一想,似乎每个语言都会有自己实现的「队列」,往队列里塞数据,再从队列里面挨个取就行了?

79ab2bba82d8825adf12bce57e871a62.png

但是一细想好像事情并不简单。作为一个「消息队列」,你首先要保证数据不能给人家弄丢了吧?存内存?万一断电了怎么办?写磁盘?消息量超过系统写磁盘速率上限了怎么办?备份又该怎么做呢?

好,假设我一整捣鼓,保证了我的数据不会丢失了,下一个问题,生产者怎么往「消息队列」里面塞数据?我的意思是,生产者可能不止一个,把全量的消息放在一个队列似乎不太合适,我需要给这些消息分个类吧?新来了一个分类的消息我怎么动态的扩容呢?消费者又如何消费这些数据呢?多个消费者之间又如何进行协调呢?

好吧..总之问题挺多的..并不像表面那么简单。

RabbitMQ

21354e56ca1e3bb5a6d112933f805281.png

RabbitMQ 是使用 Erlang 编写的一个开源的消息队列,本身支持很多的协议:AMQP,XMPP, SMTP, STOMP,也正因如此,它非常重量级,更适合于企业级的开发。同时实现了 Broker 构架,这意味着消息在发送给客户端时先在中心队列排队。对路由,负 载均衡或者数据持久化都有很好的支持。

Redis

Redis 也能用来做「消息队列」。Redis 是一个基于 Key-Value 对的 NoSQL 数据库,开发维护很活跃。虽然它是一个 Key-Value 数据库存储系统,但它本身支持 MQ 功能, 所以完全可以当做一个轻量级的队列服务来使用。对于 RabbitMQ 和 Redis 的入队和出队操作,各执行 100 万次,每 10 万次记录一次执行时间。测试 数据分为 128 Bytes、512 Bytes、1 K和 10 K四个不同大小的数据。实验表明:入队时,当数据比较小时 Redis 的性能要高于 RabbitMQ,而如果数据大小超过了 10 K,Redis 则慢的无法忍受;出队时,无论数据大小,Redis 都表现出非常好的性能,而 RabbitMQ 的出队性能则远低于Redis。

Kafka/Jafka

Kafka 是 Apache 下的一个子项目,是一个高性能跨语言分布式 Publish/Subscribe 消息队列系统,而 Jafka 是在 Kafka 之上孵化而来的,即 Kafka 的一个升级版。

具有以下特性:

  • 快速持久化,可以在O(1)的系统开销下进行消息持久化;
  • 高吞吐,在一台普通的服务器上既可以达到 10 W/s的吞吐速率;
  • 完全的分布式系统,Broker、Producer、Consumer都原生自动支持分布式,自动实现复杂均衡;
  • 支持 Hadoop 数据并行加载,对于像Hadoop的一样的日志数据和离线分析系统,但又要求实时处理的限制,这是一个可行的解决方案。

Kafka 通过 Hadoop 的并行加载机制来统一了在线和离线的消息处理。Apache Kafka 相对于 ActiveMQ 是一个非常轻量级的消息系统,除了性能非常好之外,还是一个工作良好的分布式系统。

ZeroMQ

ZeroMQ 号称最快的消息队列系统,尤其针对大吞吐量的需求场景。ZeroMQ 能够实现 RabbitMQ 不擅长的高级 / 复杂的队列,但是开发人员需要自己组合多种技术框架,技术上的复杂度是对这 MQ 能够应用成功的挑战。ZeroMQ 具有一个独特的非中间件的模式,你不需要安装和运行一个消息服务器或中间件,因为你的应用程序将扮演这个服务器角色。你只需要简单的引用 ZeroMQ 程序库,可以使用 NuGet 安装,然后你就可以愉快的在应用程序之间发送消息了。但是 ZeroMQ 仅提供非持久性的队列,也就是说如果宕机,数据将会丢失。其中,Twitter 的 Storm 0.9.0 以前的版本中默认使用 ZeroMQ 作为数据流的传输(Storm 从 0.9 版本开始同时支持 ZeroMQ 和 Netty 作为传输模块)。

ActiveMQ

ActiveMQ 是 Apache 下的一个子项目。 类似于 ZeroMQ,它能够以代理人和点对点的技术实现队列。同时类似于 RabbitMQ,它少量代码就可以高效地实现高级应用场景。

原文:https://www.cnblogs.com/wmyskxz/p/11193189.html

作者独立域名博客:https://www.wmyskxz.com/2019/07/16/xiao-xi-dui-lie-kan-guo-lai/



推荐阅读
  • 本文将深入探讨MySQL与MongoDB在游戏账户服务中的应用特点及优劣。通过对比这两种数据库的性能、扩展性和数据一致性,结合实际案例,帮助开发者更好地选择适合游戏账户服务的数据库方案。同时,文章还将介绍如何利用Erlang语言进行高效的游戏服务器开发,提升系统的稳定性和并发处理能力。 ... [详细]
  • 本文将介绍一种扩展的ASP.NET MVC三层架构框架,并通过使用StructureMap实现依赖注入,以降低代码间的耦合度。该方法不仅能够提高代码的可维护性和可测试性,还能增强系统的灵活性和扩展性。通过具体实践案例,详细阐述了如何在实际开发中有效应用这一技术。 ... [详细]
  • vsftpd配置(虚拟用户、匿名用户登录)
    一、ftp服务搭建(一)概述1.ftp连接及传输模式(1)控制连接TCP21,用于发送FTP命令信息 ... [详细]
  • 从0到1搭建大数据平台
    从0到1搭建大数据平台 ... [详细]
  • 在CentOS 7环境中安装配置Redis及使用Redis Desktop Manager连接时的注意事项与技巧
    在 CentOS 7 环境中安装和配置 Redis 时,需要注意一些关键步骤和最佳实践。本文详细介绍了从安装 Redis 到配置其基本参数的全过程,并提供了使用 Redis Desktop Manager 连接 Redis 服务器的技巧和注意事项。此外,还探讨了如何优化性能和确保数据安全,帮助用户在生产环境中高效地管理和使用 Redis。 ... [详细]
  • 本文深入探讨了NoSQL数据库的四大主要类型:键值对存储、文档存储、列式存储和图数据库。NoSQL(Not Only SQL)是指一系列非关系型数据库系统,它们不依赖于固定模式的数据存储方式,能够灵活处理大规模、高并发的数据需求。键值对存储适用于简单的数据结构;文档存储支持复杂的数据对象;列式存储优化了大数据量的读写性能;而图数据库则擅长处理复杂的关系网络。每种类型的NoSQL数据库都有其独特的优势和应用场景,本文将详细分析它们的特点及应用实例。 ... [详细]
  • 基于Dubbo与Zipkin的微服务调用链路监控解决方案
    本文提出了一种基于Dubbo与Zipkin的微服务调用链路监控解决方案。通过抽象配置层,支持HTTP和Kafka两种数据上报方式,实现了灵活且高效的调用链路追踪。该方案不仅提升了系统的可维护性和扩展性,还为故障排查提供了强大的支持。 ... [详细]
  • 本文详细介绍了使用 Python 进行 MySQL 和 Redis 数据库操作的实战技巧。首先,针对 MySQL 数据库,通过 `pymysql` 模块展示了如何连接和操作数据库,包括建立连接、执行查询和更新等常见操作。接着,文章深入探讨了 Redis 的基本命令和高级功能,如键值存储、列表操作和事务处理。此外,还提供了多个实际案例,帮助读者更好地理解和应用这些技术。 ... [详细]
  • 第二章:Kafka基础入门与核心概念解析
    本章节主要介绍了Kafka的基本概念及其核心特性。Kafka是一种分布式消息发布和订阅系统,以其卓越的性能和高吞吐量而著称。最初,Kafka被设计用于LinkedIn的活动流和运营数据处理,旨在高效地管理和传输大规模的数据流。这些数据主要包括用户活动记录、系统日志和其他实时信息。通过深入解析Kafka的设计原理和应用场景,读者将能够更好地理解其在现代大数据架构中的重要地位。 ... [详细]
  • Spring框架中的面向切面编程(AOP)技术详解
    面向切面编程(AOP)是Spring框架中的关键技术之一,它通过将横切关注点从业务逻辑中分离出来,实现了代码的模块化和重用。AOP的核心思想是将程序运行过程中需要多次处理的功能(如日志记录、事务管理等)封装成独立的模块,即切面,并在特定的连接点(如方法调用)动态地应用这些切面。这种方式不仅提高了代码的可维护性和可读性,还简化了业务逻辑的实现。Spring AOP利用代理机制,在不修改原有代码的基础上,实现了对目标对象的增强。 ... [详细]
  • 在CentOS上部署和配置FreeSWITCH
    在CentOS系统上部署和配置FreeSWITCH的过程涉及多个步骤。本文详细介绍了从源代码安装FreeSWITCH的方法,包括必要的依赖项安装、编译和配置过程。此外,还提供了常见的配置选项和故障排除技巧,帮助用户顺利完成部署并确保系统的稳定运行。 ... [详细]
  • 修复一个 Bug 竟耗时两天?真的有那么复杂吗?
    修复一个 Bug 竟然耗费了两天时间?这背后究竟隐藏着怎样的复杂性?本文将深入探讨这个看似简单的 Bug 为何会如此棘手,从代码层面剖析问题根源,并分享解决过程中遇到的技术挑战和心得。 ... [详细]
  • 开发心得:利用 Redis 构建分布式系统的轻量级协调机制
    开发心得:利用 Redis 构建分布式系统的轻量级协调机制 ... [详细]
  • NoSQL数据库,即非关系型数据库,有时也被称作Not Only SQL,是一种区别于传统关系型数据库的管理系统。这类数据库设计用于处理大规模、高并发的数据存储与查询需求,特别适用于需要快速读写大量非结构化或半结构化数据的应用场景。NoSQL数据库通过牺牲部分一致性来换取更高的可扩展性和性能,支持分布式部署,能够有效应对互联网时代的海量数据挑战。 ... [详细]
  • 为何Serverless将成为未来十年的主导技术领域?
    为何Serverless将成为未来十年的主导技术领域? ... [详细]
author-avatar
无内功不5功
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有