【问题标题】:solace - guaranteed ordering with horizontal scalabilitysolace - 水平可扩展性保证排序
【发布时间】:2020-05-15 06:59:03
【问题描述】:

因此,在非排他队列中,我们对消息进行了排序(例如,id 123 更新事件将在 id 123 创建事件之后)。当我们只有一个消费者时一切都好,但需要水平可扩展性。通过产生另一个消费者,我知道代理将在其中进行循环,因此更新事件可以在其创建事件之前处理。

有没有关于如何解决这个问题的现有模式?我知道像 kafka 和 activemq 这样的一些代理支持它,通过在发布期间指定 id 将确保具有该 id 的所有消息将仅在一个消费者上排队;因此,尊重事件的顺序。

【问题讨论】:

    标签: solace solace-mq


    【解决方案1】:

    有序消息传递和水平扩展的想法本质上是相互矛盾的。为了实现顺序,必须在消费下一条消息之前完全消费并确认每条消息。这会导致 serial 消息处理(即没有并发)。但是,水平可扩展性的想法是通过添加可以同时处理消息的消费者来增加消息吞吐量。如您所见,如果您想要有序的消息处理,则不能同时使用消息,这违背了水平扩展的全部目的。

    ActiveMQ(和一般的 JMS)支持您在问题中提到的“消息分组”的想法(同一组中的所有消息共享相同的分组属性 ID 值)。代理选择单个消费者来接收特定组中的所有消息,以便按顺序(即按顺序)处理消息。由于仅对特定的消息组进行排序,因此可以同时使用来自多个组的消息。但是,队列的基本先进先出语义仍然成立,因此如果您在每个组或少数组中有大量消息,您的整体消费者并发性仍然会相当低,而且肯定很多 低于您根本不需要订单的情况。虽然我在这里专门谈论 ActiveMQ,但对于任何消息代理都没有真正的解决方法,因此同样适用于 Solace(假设它甚至首先支持消息分组)。

    【讨论】:

    • 挑战的精彩总结。你是对的,基本上这不能用一个队列来完成,需要做更多的工作才能在 Solace 上实现所需的行为。 (详情见我的回答)
    【解决方案2】:

    (摘自我尚未发布的博客)

    有时要求发布的事件或消息数据包含特定属性 - 例如。客户 ID、订单 ID、产品 ID 等 - 始终按照生产它们的原始订单进行处理。此要求意味着所有相关消息都传递给同一消费者(或可能的消费者组)。也就是说,消息包含一个key,这样具有相同key的后续消息总是被传递给同一个消费者并按顺序处理。这可确保始终按顺序处理有关特定属性的更改或更新。

    消费者群体”一词由 Apache Kafka(一种日志传送应用程序)推广。在 Kafka 中,消费者组是构成“逻辑消费者”以读取单个主题的消费者组。 Kafka 消费者组中的消费者连接到 Kafka 主题内的一个或多个分区,并从分区文件中读取顺序日志记录。当记录(“消息”)附加到 Kafka 主题中的分区时,分区由发布者定义的键属性选择。

    这提供了一种“sticky load-balancing”的形式,使得具有相同键的记录最终在同一个分区中,因此由同一个消费者处理。

    使用分层主题结构和 Solace 的高级主题过滤功能,可以在 Solace 中实现相同(并且更好)的功能。

    使用 Solace 主题进行分区

    在定义主题层次结构或分类时,将主题层次结构的一级指定为分区键。例如。对于订单输入系统,您的主题结构可以是:

    estore/order/[ORDER_ID_PARTITION_KEY]/more/specific/rest/of/topic

    密钥通常是已发布数据的重要属性的哈希值,如前一段所述。在我们的示例中,键控属性是订单 ID,一个大整数。为简单起见,我们假设分区键为: Order ID modulo 8:一个介于 0..7 之间的整数,给出 8 个可能的值,最多 8 个可能的分区。

    要在 Solace 中配置粘性负载平衡,至少要配置与“消费者组”中消费者数量一样多的队列……比如说两个!但是,为了便于将来扩展,请考虑配置更多队列并让消费者绑定到多个队列:

    注意在订阅末尾使用 Solace 多级通配符 >

    在此 eStore 示例中,如果客户网关/API 被增强以允许不同类型的订单事件(例如 newamendcancel),则需要与相同订单 ID 相关的事件去同一个后端处理器。这将确保new 订单不会被一个处理器接收,而cancel 会被路由到另一个处理器。每当发布者生成“订单”类型的事件时,主题的第 3 级用于通过取订单 ID 的模 8(或其他值)将消息键入到特定分区。

    可能有非常大量的分区使用这种方法,基本上不改变架构模式,使用主题来定义分区(因为主题和订阅在 Solace 中是“便宜的” )。这通过在新的队列数量上重新平衡密钥订阅,能够将更多的消费者添加到消费者组中,从而实现未来的灵活性。只需从相当大的散列键空间或模数开始...这样发布者就不必担心更改其分区键算法!

    请注意,这种方法还允许您使用主题层次结构的两个不同级别来键入两个不同的属性。一组队列可以查看一个级别,另一组队列可以分片在不同的级别。

    希望有帮助!

    【讨论】:

      【解决方案3】:

      本质上,您正在寻找的是粘性负载平衡:具有特定键的消息被分配给同一个消费者,而具有不同键的整体消息可以在不同的消费者之间实现负载平衡。 看看我的同事 Mat Hobbis 的这篇博客,它描述了如何使用 Solace PubSub+ 完成此操作: https://solace.com/blog/sticky-load-balancing-in-solace-pubsub-event-broker/

      【讨论】:

        猜你喜欢
        • 2018-08-21
        • 1970-01-01
        • 2022-11-21
        • 1970-01-01
        • 2011-08-05
        • 2017-06-24
        • 1970-01-01
        • 2012-10-18
        • 2017-08-27
        相关资源
        最近更新 更多