• 利见大人
    2023-08-11 来自上海
    老师您好,您好像忘更了关于解决消息堆积的章节哈! 这章我有两个疑问? 异步消费方案中的队列和多分区方案中的分区有什么分别? 异步消息方案中的队列不会出现数据不均匀的问题吗?

    作者回复: 1. 你是说那个内存队列?就是载体不同。如果是内存队列,那么宕机就没了。 2. 一样会有数据不均匀的问题,但是更加容易解决,因为你开启队列的时候,自己应用一下一致性哈希之类的算法就可以解决了。 不过其实你可以考虑只用一个队列,线程都从这里面取。就是在最后要协调大家停下来批量提交麻烦一点,倒也还可以接受。

    
    1
  • H·H
    2023-09-11 来自上海
    消息重试这个怎么保证有序?

    作者回复: 老大难的问题了,哈哈哈哈。 说实在的,我也没特别好的的办法。如果你们本身就有那种排序机制,比如说我可以通过状态来判定消息是不是失序了,比如说当状态还是未支付的时候,你收到取消消息,这肯定是乱序了。那么你就可以尝试把取消消息重新发回去原本的消息队列上。 另外一种有漏洞的做法就是借助延迟消息。比如说你 A1 消息在重试,A2 不管知不知道 A1 在重试,直接自己延迟一分钟发送。“一分钟”是假定你的 A1 肯定能在一分钟之内重试完成。 当然,如果 A2 的发送者有办法知道 A1 还没发,那么就可以优化成只有当 A1 没发,A2 才会延迟,当然 A3,A4... 显然也要跟着延迟。 比如说,你可以借助 redis,假设 key1=1 的时候,代表 A1 还没发。key1=2 的时候,A1 已经发了。那么 A2 的发送者看一眼 Redis 就知道了。 不过,我的个人看法是……除非是面试吹牛,不然实践中直接告警拉到。就是在真的发现消息失序的时候,告警,人手工微调一下就可以。可用性高的话,你可能一个月才有一个两个这种失序的问题。

    
    
  • itschenxiang
    2023-08-29 来自广东
    多分区,哈希槽方案我有点不太理解,通过crc16(key) & 1024是能够比较均匀地分配到每个槽中吗?

    作者回复: 不不不,这个的关键点是你可以引入逻辑上槽的概念,你不一定非得用 CRC16 来计算槽。你可以说选择你的业务特征,用几个哈希函数,一通猛算,得到一个值,这个值就是你的槽的号。我这里用 1024 只是举个例子。 更好的做法是固定分配。比如说我直接指定,一通猛算出来的值如果是 1,2,1023,345 就到分区 0。就有点你手动分配槽到 Redis 节点上的意思。借助配置中心还可以动态更新这个分配,也很方便。

    共 2 条评论
    
  • Sampson
    2023-08-28 来自上海
    老师这里有在使用kafka的多分区方案的时候有一个点,如果某个分区挂了,或者出发了rebalance,那消息岂不是无序了,而且对于其他业务来说也是不友好的。我之前会经常遇到这个问题,请教下这里改怎么弄呢

    作者回复: 分区挂了倒还好,毕竟生产者都发不出来。要解决 rebalance,有一个不太好的办法,但是勉强能用。就是消费者这边手动指定分区。 这样做的话,就是要做好监控。一旦消费特定分区的消费者崩溃了,要及时启动另外一个消费者来消费同样地分区。

    
    
  • ZhiguoXue_IT
    2023-08-24 来自北京
    在订单的业务场景下,有下单消息,退单退款消息,按照订单号进行分区,保证同一个订单的数据一致性,如果是分布式环境下,退单的消息比下单的消息先到,业务一般如何处理呢

    作者回复: 好问题。盲猜你是用了不同的 topic 是不是?就是退单的消息用了一个 topic,但是下单的用了另外一个 topic。 如果你是这种的话,只能用我提到的跨 topic 有序的方案,要有一个协调者进来,这个协调者在收到退单的时候,要先去看看有没有收到下单的消息。 但是一般用不着这样,以为你只需要检测有没有这个订单,或者状态是否符合,不符合你就丢回去原本的 topic 里面。或者你设定一个时间,比如说三十分钟之后再处理这个退单消息,然后预期三十分钟内应该能收到下单消息。

    
    
  • Zwh
    2023-08-21 来自中国台湾
    对于多分区下可能会出现的消息失序问题,新增一个乱序队列,消费者判断业务前置条件是否达成,若否就放入乱序队列,考虑增加延时和重试次数控制,乱序队列消费者收到消息后根据业务状态判断是否进行处理还是继续乱序,请问老师这个方案可行吗

    作者回复: 可以。你的思路就是,如果我前置消息不满足,我就临时放一个地方。控制住重试就可以。

    共 2 条评论
    
  • 陈斌
    2023-08-13 来自广东
    老师你好~ 1、如果某个分区消息积压了就启用异步消费,我认为思路整体方向肯定可行的,这个解决方案也会引入更多的思考点。 例如:这个解决思路就是使用线程池去异步处理消息,这就有会引出一个问题:线程池的核心线程数的问题(需要根据处理消息是CPU密集型还是IO密集型来设置核心线程个数)。还有如果要求业务内消息有序,需要考虑到同一个业务的消息应该被同一个线程执行,这个时候是否还能使用线程池去异步处理消息,线程池没有指定那个消息被那个线程消费的能力。只能手动给线程编号,然后根据业务ID去分配消息被那个线程处理,同样如果消息又被积压,一样会有增加线程数而引起消息失序的问题。还有一个问题就是如果该分区处理了10个业务的消息,其中只有2个业务消息特别多,我需要怎么把其他8个不怎么忙的业务通过异步消费的方式隔离出来,怎么做到业务之间相互解耦。 (说的有点乱) 2、数据分布不均匀:例如分库分表怎么使得分片后的数据均匀分布。流量分布不均匀:初步想到是Nginx的负载均衡算法会用到这个。

    作者回复: 你的思考很有深度! 你说的是两件事,但是可以通过一个手段来解决。要保持异步消费还要有序,是不能用线程池的,理由你已经分析到了。你只能考虑手动启动多个线程。当然,如果你用的是 JAVA,那么你可以用只有一个线程的线程池。而后,剩下的事情就都是你分发的事情了,比如说你可以说编号为 1,2,3 的线程池就是给你不忙的业务用的,其它就是给你忙的业务用的。

    共 2 条评论
    
  • peter
    2023-08-12 来自北京
    请教老师两个问题: Q1:借用Redis槽的思想来解决数据分布不均匀的问题,那么,同一个业务的消息会被分配到不同的分区上吗?如果同一个业务的消息被分配到不同的分区上,那么,会产生消息失序的问题吗? Q2:有个说法是:kafka是专门用于大数据处理的消息队列,是专为大数据而生的。这个说法成立吗?(这个问题在第22课提问过了,当时打错了几个关键字,导致老师不理解,抱歉)

    作者回复: 1. 你在设计槽的时候,根据业务特征来确定的槽,那就不会。比如说你用 ID % 1024 来选择槽,那么同一个 ID 的肯定在同一个槽。 2. 不成立……我没听 Kafka 的团队出来说我们就是为了大数据搞出来的。相反,先在稍微有点规模的公司,都会使用。但是也得承认, Kafka 在大数据下表现极其优异。

    共 2 条评论
    
  • 进击的和和
    2023-08-11
    老师你好 (1)如果 msg2 先到了,但是 msg1 还没出来,那么这个协调者要有办法让 msg2 的消费者 B 停下来,暂时不消费 msg1。这里好像想表达的是描述的写反了。 (2)如果想保证一个topic在多个分区有序还有什么别的思路和方法吗? (3)关于多分区数据不均匀。因为发送方要按照业务特征来选择分区,可能造成数据不均匀,如果使用了redis的哈希槽,只是槽多了,但是这个特征还是会分配到某些槽上,这些槽对应的映射还是数据较多的那几个分区,这里还要用方式或方法来计算下呢 (4)增加分区引起消息失序。假设分区里的数据很少,等三分钟这个只是概率上会降低失序的可能,还可以监控发现问题,手动修复一下就好了。这里能不能用某种方式监控分区了没有数据才加入分区,或者说才开始给新的分区分配数据。但是就是因为消息积压严重,才需要立刻增加分区减轻消极积压分区的负担,所以不应该等消息积压分区消费完成才进行分配。这里可以在业务msg2的业务中增加逻辑,某个topic下最近一次的分区数,如发现某个topic下分区数发生变化,这个消息还是发给之前那个分区,然后修改最近一次的分区数,不知道这样行不行,并且业务逻辑太麻烦了,还有什么好的方式吗
    展开

    作者回复: 1. 感谢勘误! 2. 没……应该说思路都是要协调,不过怎么协调是有很多做法的。比如说可以考虑事件驱动中的前置事件检测,也可以考虑中间引入一个什么东西来辅助排队。不过都是协调者的事情。 3. 答案就是你的槽只要足够多,就不会有均匀性问题。如果你只有十个槽,那么可能某个槽数据很多。但是你有一万个槽,那么你就可以通过合理分配业务到不同的槽上,保证数据均匀分散了。 4. 哈哈哈,虽然没用过你的思路,但是我一琢磨还是可以的,这个东西可以让中间件研发的人来封装。难点我觉得应该是我发现 topic 数量修改了之后,我该发消息到原本的分区,那么什么时候发到新的分区呢?

    
    