首页 > 其他分享 >系统设计-消息队列篇

系统设计-消息队列篇

时间:2024-01-17 11:01:14浏览次数:26  
标签:消费 队列 Kafka 处理 消息 设计 ID

消息队列:秒杀时如何处理每秒上万次的下单请求?

用户查询的是少量的商品数据,属于查询的热点数据,你可以采用缓存策略将请求尽量挡在上层的缓存中,能被静态化的数据(比如商城里的图片和视频数据)尽量做到静态化,这样就可以命中 CDN 节点缓存减少 Web 服务器的查询量和带宽负担。Web 服务器比如 Nginx 可以直接访问分布式缓存节点,从而避免请求到达 Tomcat 等业务服务器。

真正下单的请求只有少数的能通过,但是会绕过缓存直接跟数据库交互。将秒杀请求暂存在消息队列中,然后业务服务器会响应用户“秒杀结果正在计算中”,释放了系统资源之后再处理其它用户的请求。

这就是消息队列在秒杀系统中最主要的作用:削峰填谷;另外在使用消息队列应对流量峰值时,需要对队列处理的时间、前端写入流量的大小、数据库处理能力做好评估,然后根据不同的量级来决定部署多少台队列处理程序。

异步处理、解耦合和削峰填谷是消息队列在秒杀系统设计中起到的主要作用,其中异步处理可以简化业务流程中的步骤,提升系统性能;削峰填谷可以削去到达秒杀系统的峰值流量,让业务逻辑的处理更加缓和;解耦合可以将秒杀系统和数据系统解耦开,这样两个系统的任何变更都不会影响到另一个系统。

消息投递:如何保证消息仅仅被消费一次?

消息为什么会丢失

消息从生产者写入到消息队列的过程;消息在消息队列中的存储场景;消息被消费者消费的过程。

1.业务服务器因网络抖动未发送成功到消息队列,采用消息重传解决,但可能导致消息重复发送,从而在消费分时候重复消费同样的消息。

2.消息队列本身丢失消息。拿 Kafka 举例,消息在 Kafka 中是存储在本地磁盘上的,而为了减少消息存储时对磁盘的随机 I/O,我们一般会将消息先写入到操作系统的 Page Cache 中,然后再找合适的时机刷新到磁盘上。因断电或者机器异常重启,Page Cache还没来得及刷盘就丢失了。解决方案只能采用更复杂的集群和"acks=all"

3.消费者接受消息的时候网络抖动导致消息并没有正确地接收到。一定要等到消息接收和处理完成后才能更新消费进度,但是这也会造成消息重复的问题,比方说某一条消息在处理之后消费者恰好宕机了,那么因为没有更新消费进度,所以当这个消费者重启之后还会重复地消费这条消息。

如何保证消息只被消费一次

为了避免消息丢失我们需要付出两方面的代价:一方面是性能的损耗,一方面可能造成消息重复消费。在生产、消费过程中增加消息幂等性的保证。

在消息生产过程中,在 Kafka0.11 版本和 Pulsar 中都支持“producer idempotency”的特性,翻译过来就是生产过程的幂等性,这种特性保证消息虽然可能在生产端产生重复,但是最终在消息队列存储时只会存储一份。

它的做法是给每一个生产者一个唯一的 ID,并且为生产的每一条消息赋予一个唯一 ID,消息队列的服务端会存储 < 生产者 ID,最后一条消息 ID> 的映射。当某一个生产者产生新的消息时,消息队列服务端会比对消息 ID 是否与存储的最后一条 ID 一致,如果一致就认为是重复的消息,服务端会自动丢弃。

而在消费端,幂等性的保证会稍微复杂一些,你可以从通用层和业务层两个层面来考虑。

在通用层面,你可以在消息被生产的时候使用发号器给它生成一个全局唯一的消息 ID,消息被处理之后把这个 ID 存储在数据库中,在处理下一条消息之前先从数据库里面查询这个全局 ID 是否被消费过,如果被消费过就放弃消费。你可以看到,无论是生产端的幂等性保证方式还是消费端通用的幂等性保证方式,它们的共同特点都是为每一个消息生成一个唯一的 ID,然后在使用这个消息的时候,先比对这个 ID 是否已经存在,如果存在则认为消息已经被使用过。所以这种方式是一种标准的实现幂等的方式。

在操作数据库的时候采用乐观锁和事务保证只消费一次数据。

消息队列:如何降低消息队列系统中消息的延迟?

监控

首先,Kafka 提供了工具叫做“kafka-consumer-groups.sh”(它在 Kafka 安装包的 bin 目录下)。可以查看Kafka当前队列消息的堆积数。

Kafka 通过 JMX 暴露了消息堆积的数据,可以写代码来获取,这样也可以方便地输出到监控系统中。

减少消息延迟的正确姿势

想要减少消息的处理延迟,我们需要在消费端和消息队列两个层面来完成。但Kafka一般不能增加消费者数量达到目的。因为在 Kafka 中,一个 Topic(话题)可以配置多个 Partition(分区),数据会被平均或者按照生产者指定的方式写入到多个分区中,那么在消费的时候,Kafka 约定一个分区只能被一个消费者消费,为什么要这么设计呢?在我看来,如果有多个 consumer(消费者)可以消费一个分区的数据,那么在操作这个消费进度的时候就需要加锁,可能会对性能有一定的影响。

所以说,话题的分区数量决定了消费的并行度,增加多余的消费者也是没有用处的,你可以通过增加分区来提高消费者的处理能力。

虽然不能增加 consumer,但你可以在一个 consumer 中提升处理消息的并行度,所以可以考虑使用多线程的方式来增加处理能力:你可以预先创建一个或者多个线程池,在接收到消息之后把消息丢到线程池中来异步地处理,这样,原本串行的消费消息的流程就变成了并行的消费,可以提高消息消费的吞吐量,在并行处理的前提下,我们就可以在一次和消息队列的交互中多拉取几条数据,然后分配给多个线程来处理。

选择高性能的数据存储方式配合零拷贝技术,可以提升消息的消费性能。

 

标签:消费,队列,Kafka,处理,消息,设计,ID
From: https://www.cnblogs.com/twh233/p/17969455

相关文章

  • 基于SpringBoot+Vue的校园招聘系统设计实现(源码+lw+部署文档+讲解等)
    (文章目录)前言:heartpulse:博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌:heartpulse:......
  • 模拟适配器设计方案:360-基于10G以太网的模拟适配器
     基于10G以太网的模拟适配器一、产品概述   基于10G以太网的模拟适配器是一款分布式高速数据采集系统,实现多路AD的数据采集,并通过10G以太网光纤远距离传输到存储计算服务器,计算控制指令能通过光纤返回给数据卡进行IO信号控制。产品基于10G太网络,可迅......
  • 苏宁OLAP架构设计
    一.功能综述OLAP引擎为存储和计算二合一的引擎,自身内部涵盖了对数据的管理以及提供查询能力。底层数据完全规划在引擎内部,外部系统不允许直接操作底层数据,而是需要通过暴露出来的接口来读写引擎内部数据。目前整体来说OLAP功能由两部分组成:数据管理,查询引擎。1.1数据管理引......
  • 可靠消息服务事务(RocketMQ的分布式事务解决方案)
    系统环境Java:openjdkversion“1.8.0_382”rocketmq-all-5.1.4整体机制使用rocketmq的事务消息,分两个阶段保证分布式事务的最终一致性;一阶段:消息生产者(分布式事务发起方)发送半消息(消费者不接收半消息),之后完成本地事务的执行,根据执行结果选择将半消息投递给消费者或撤回半......
  • Spring Boot 整合工厂设计模式完成服务调用的一种实现
    工厂模式是一种创建型设计模式,其主要目的是提供一个创建对象的接口,但将具体类的实例化延迟到子类中。这样,客户端代码就不需要知道要实例化的具体类,只需要知道使用的工厂接口。项目结构如下代码实例如下所有水果都要实现这个接口publicinterfaceAllFruits{voideatFru......
  • 界面设计规范
    ......
  • 采用模块化方法设计的LMK1C1104DQFR、LMK1C1106PWR、LMK1C1108PWR(LVCMOS)时钟缓冲器系
    LMK1C110x1.8V、2.5V和3.3VLVCMOS时钟缓冲器系列1、概述LMK1C110x是的一款模块化、高性能、低偏斜、通用时钟缓冲器系列器件。整个系列采用模块化方法设计。提供三个不同的扇出选项:1:2、1:3、1:4。该系列所有器件均互相引脚兼容,并向后兼容CDCLVC110x系列,便于操作。该系列所......
  • 计划任务 显示消息 已弃用 计划任务弹出提示
    简介:计划任务的显示消息已弃用了。但是我这里需要一个每周一早上8点重启的任务,太多懒人不关电脑了,更新不执行,稳定下降,很多需要重启才能完成的功能均不正常,只好计划任务每周重启一下吧。但是各个终端用户又有着不同的使用习惯:长期开着excel不关,不保存……组策略定时重启吧。解......
  • 设计之道:图片素材选择与创意运用
    在现代设计领域,图片素材的选择与运用至关重要。一张优质的图片素材可以为设计增色添彩,提升作品的品质和视觉效果。那么,如何挑选合适的图片素材,并将其巧妙地融入设计中呢?本文将为您一一解答。免版素材库|一个覆盖广泛主题工具的高效在线平台(amd794.com)https://amd794.com......
  • Web 实时消息推送
    总结以下内容为JavaGuide补充 介绍优点缺点短轮询客户端定时向服务端发送请求,服务端直接返回响应数据(即使没有数据更新)简单、易理解、易实现实时性太差,无效请求太多,频繁建立连接太耗费资源长轮询与短轮询不同是,长轮询接收到客户端请求之后等到有数据更新才......