2026/3/27 22:30:20
网站建设
项目流程
网站建设中的功能模块描述,山东房和城乡建设厅网站,紧急通知网页升级记住我们,鞋子网站建设策划书文章目录Ⅰ. 幂等性保障一、幂等性介绍① 应用程序的幂等性介绍② MQ的幂等性介绍二、解决方案① 全局唯一ID② 业务逻辑判断Ⅱ. 顺序性保障一、顺序性保障介绍二、顺序性保障方案Ⅲ. 消息积压问题一、原因分析二、解决方案Ⅰ. 幂等性保障
一、幂等性介绍
幂等性是数学和计算…文章目录Ⅰ. 幂等性保障一、幂等性介绍① 应用程序的幂等性介绍② MQ的幂等性介绍二、解决方案① 全局唯一ID② 业务逻辑判断Ⅱ. 顺序性保障一、顺序性保障介绍二、顺序性保障方案Ⅲ. 消息积压问题一、原因分析二、解决方案Ⅰ. 幂等性保障一、幂等性介绍幂等性是数学和计算机科学中某些运算的性质它们可以被多次应用而不会改变初始应用的结果。① 应用程序的幂等性介绍在应用程序中幂等性就是指对一个系统进行重复调用相同参数不论请求多少次这些请求对系统的影响都是相同的效果。比如数据库的select操作。不同时间两次查询的结果可能不同但是这个操作是符合幂等性的。幂等性指的是对资源的影响而不是返回结果。查询操作对数据资源本身不会产生影响之所以结果不同可能是因为两次查询之间有其他操作对资源进行了修改。比如i这个操作就是非幂等性的。如果调用方没有控制好逻辑一次流程重复调用好几次结果就会不同。② MQ的幂等性介绍对于 MQ 而言幂等性是指对同一条消息进行多次消费对系统的影响是相同的。一般消息中间件的消息传输保障分为三个层级At most once最多发一次。消息可能会丢失但绝不会重复传输。At least once最少发一次。消息绝不会丢失但可能会重复传输。Exactly once恰好发一次。每条消息肯定会被传输一次且仅传输一次。其中 RabbitMQ 支持 “最多发一次” 和 “最少发一次”。而对于 “恰好发一次”目前 RabbitMQ 还做不到不仅是 RabbitMQ目前市面上主流的消息中间件都做不到这一点。在业务使用中对于可靠性要求比较高的场景建议使用 “最少发一次”以防止消息丢失。“最多发一次” 会因为消息发送过程中网络问题消费出现异常等种种原因导致消息丢失。以下场景可能会导致消息发送重复包含但不限于发送时消息重复当一条消息已被成功发送到服务端并完成持久化此时出现了网络闪断或者客户端宕机导致服务端对客户端应答失败。如果此时 Producer 意识到消息发送失败并尝试再次发送消息Consumer 后续会收到两条内容相同并且MessageID也相同的消息。响应时消息重复消息消费的场景下消息已投递到 Consumer 并完成业务处理当客户端给服务端反馈应答的时候网络闪断。为了保证消息至少被消费一次消息队列服务端将在网络恢复后再次尝试投递之前已被处理过的消息Consumer 后续会收到两条内容相同并且MessageID也相同的消息。但是“最少发一次” 会造成一个问题消费端会收到重复的消息也会造成对同一条消息进行多次处理。一些不重要的业务还好一点对于重要的业务如果不对重复的消息进行处理会造成严重事故。比如当用户对一个订单付款之后因为网络问题付款成功的结果未返回给订单系统当用户再次点击付款时如果系统未做幂等性处理那就会造成两次扣款。二、解决方案MQ 消费者的幂等性的解决方法一般有以下几种① 全局唯一ID为每条消息分配一个唯一标识符消费者收到消息后先用该唯一ID判断该消息是否已经消费过如果已经消费过则放弃处理。如果未消费过消费者开始消费消息业务处理成功后把唯一ID保存起来数据库或Redis等可以使用 Redis 的原子性操作setnx来保证幂等性将唯一ID作为 key 放到 redis 中SETNX messageID 1。返回1说明之前没有消费过正常消费。返回0说明这条消息之前已消费过抛弃。② 业务逻辑判断在业务逻辑层面实现消息处理的幂等性。例如通过检查数据库中是否已存在相关数据记录或者使用乐观锁机制来避免更新已被其他事务更改的数据再或者在处理消息之前先检查相关业务的状态确保消息对应的操作尚未执行然后才进行处理具体根据业务场景来处理。Ⅱ. 顺序性保障一、顺序性保障介绍消息的顺序性是指消费者消费的消息和生产者发送消息的顺序是一致的。比如生产者发送的消息分别是 msg1、msg2、msg3那么消费者也是按照 msg1、msg2、msg3 的顺序进行消费的。很多业务场景下消息的消费是不用保证顺序的比如使用 MQ 实现订单超时的处理。但有些业务场景可能存在多个消息顺序处理的情况。比如用户信息修改对同一个用户的同一个资料进行修改需要保证消息的顺序。一些资料显示 RabbitMQ 的消息能够保障顺序性这是不严谨的。在不考虑消息丢失网络故障等异常的情况下如果只有一个消费者最好也只有一个生产者的情况下是可以保证消息的顺序性。如果有多个生产者同时发送消息无法确定消息到达 RabbitMQ Broker 的前后顺序也就无法验证消息的顺序性。哪些情况可能会打破RabbitMQ的顺序性呢下面介绍几种常见的场景下面以一个生产者的场景为背景多个消费者当队列配置了多个消费者时消息可能会被不同的消费者并行处理从而导致消息处理的顺序性无法保证。网络波动或异常在消息传递过程中如果出现网络波动或异常可能会导致消息确认ACK丢失从而使得消息被重新入队和重新消费造成顺序性问题。消息重试如果消费者在处理消息后未能及时发送确认或者确认消息在传输过程中丢失那么MQ可能会认为消息未被成功消费而进行重试这也可能导致消息处理的顺序性问题。消息路由问题在复杂的路由场景中消息可能会根据路由键被发送到不同的队列从而无法保证全局的顺序性。死信队列消息因为某些原因如消费端拒绝消息被放入死信队列死信队列被消费时无法保证消息的顺序和生产者发送消息的顺序一致。包括但不仅限于以上几种情形会使 RabbitMQ 消息错序如果要保证消息的顺序性需要业务方使用 RabbitMQ 之后做进一步的处理。二、顺序性保障方案消息顺序性保障分为局部顺序性保证和全局顺序性保证。局部顺序性指在单个队列内部保证消息的顺序全局顺序性指在多个队列或多个消费者之间保证消息的顺序在实际应用中全局顺序性很难实现可以考虑使用业务逻辑来保证顺序性比如在消息中嵌入序列号并在消费端进行排序处理。相对而言局部顺序性更常见也更容易实现。RabbitMQ 作为一个分布式消息队列主要优化的是吞吐量和可用性而不是严格的顺序性保证。如果业务场景确实需要严格的消息顺序可能需要在应用层面进行额外的设计和实现。接下来说一下消息的顺序性保证的常见策略1.单队列单消费者最简单的方法是使用单个队列并由单个消费者进行处理。同一个队列中的消息是先进先出的这是RabbitMQ来帮助我们保证的。2. 分区消费单个消费者的吞吐太低了当需要多个消费者以提高处理速度时可以使用分区消费。把一个队列分割成多个分区每个分区由一个消费者处理以此来保持每个分区内消息的顺序性。比如用户修改资料后发送一条用户资料消息。消费者在处理时需要保证消息发送的先后顺序。但这种场合并不需要保证全局顺序。只需要保证同一个用户的消息顺序消费就可以。这时候就可以采用把消费按照一定的规则分为多个区每个分区由一个消费者处理。RabbitMQ 本身并不支持分区消费需要业务逻辑去实现或者借助 spring-cloud-stream 来实现。参考https://docs.spring.io/spring-cloud-stream/reference/rabbit/rabbit_partitions.html3. 消息确认机制使用手动消息确认机制消费者在处理完一条消息后显式地发送确认这样 RabbitMQ 才会移除并继续发送下一条消息。4. 业务逻辑控制在某些情况下即使消息乱序到达也可以在业务逻辑层面实现顺序控制。比如通过在消息中嵌入序列号并在消费时根据这些信息来处理。Ⅲ. 消息积压问题一、原因分析消息积压是指在消息队列中待处理的消息数量超过了消费者处理能力导致消息在队列中不断堆积的现象。通常有以下几种原因基本是消费者的问题消息生产过快在高流量或者高负载的情况下生产者以极高的速率发送消息超过了消费者的处理能力。消费者处理能力不足消费者处理处理消息的速度跟不上消息生产的速度也会导致消息在队列中积压。消费端业务逻辑复杂耗时长消费端代码性能低系统资源限制如CPU、内存、磁盘I/O等也会限制消费者处理消息的效率。异常处理处理不当。消费者在处理消息时出现异常导致消息无法被正确处理和确认。**网络问题**因为网络延迟或不稳定消费者无法及时接收或确认消息最终导致消息积压。RabbitMQ 服务器配置偏低消息积压可能会导致系统性能下降影响用户体验甚至导致系统崩溃。因此及时发现消息积压并解决对于维护系统稳定性至关重要。二、解决方案遇到消息积压时首先要分析消息积压造成的原因。根据原因来调整策略。主要从以下几个方面来解决提高消费者效率增加消费者实例数量比如新增机器优化业务逻辑比如使用多线程来处理业务合理设置prefetchCount当一个消费者阻塞时消息转发到其他未阻塞的消费者。消息发生异常时设置合适的重试策略或者转入到死信队列限制生产者速率流量控制在消息生产者中实现流量控制逻辑根据消费者处理能力动态调整发送速率限流使用限流工具为消息发送速率设置一个上限设置过期时间。如果消息过期未消费可以配置死信队列以避免消息丢失并减少对主队列的压力资源与配置优化比如升级 RabbitMQ 服务器的硬件调整 RabbitMQ 的配置参数等