You need to enable JavaScript to run this app.
导航
消息顺序性与可靠性
最近更新时间:2023.11.03 17:39:21首次发布时间:2023.11.03 16:05:48

使用消息队列 Kafka版收发消息时,往往需要关注消息的顺序性与可靠性,本文档介绍实现消息顺序性、保证消息可靠性的推荐方式。

消息顺序性

Kafka 的消息在单个分区中可以保证数据的先入先出,即写入同一分区的消息,若消息 A 先于消息 B 写入,那么在进行消息读取时,消息 A 也一定可以先于消息 B 被客户端读取。但 Kafka 消息的分区顺序性仅保证通过同一生产者先后发送的消息是有序的,不同生产者发送的消息无法确认到达服务端的先后顺序,所以无法保证有序。
基于 Kafka 消息的分区顺序性,如果要保证整体消息顺序性的能力,推荐考虑以下方式实现。

方式

说明

全局有序

创建仅 1 分区的 Topic。如果 Topic 仅有一个分区,服务端收到消息的顺序与生产者客户端发送的消息顺序严格一致。
从单个 Topic 的角度来看,1 分区的 Topic 在消息的写入和读取中都无法发挥集群完整集群性能,只有多个 1 分区的 Topic 同时使用时,才有可能最大限度的发挥集群的性能。

分区有序

Kafka 分区中消息天然有序,您也可以通过将需要保证顺序的消息写入到同一分区的方式来实现消息的有序性。该方式适用于不需要所有消息都保证顺序的场景。

  • 在发送消息时,对有序消息通过指定相同分区编号进行发送的方式来保证最终消息读取的有序性。
  • 对于 Confluent 官方生产者客户端,也可以通过将消息指定相同的消息 key 来实现发送到相同的分区。但是,在分区扩容等 Topic 的分区发生变化的场景中,根据消息 key 计算到的分区编号也会发生变化。

消息可靠性

消息的可靠性受客户端和服务端配置的影响,如果需要保证消息数据安全可靠不丢失,需要客户端和服务端配置相配合。

Kafka 服务端配置

火山引擎消息队列 Kafka版支持通过以下参数提升数据存储的可靠性。

配置

说明

Topic 副本数

写入该 Topic 中的消息所保存的副本数。支持 2 副本和 3 副本,3 副本可靠性更高,但是会占用更多额外的存储资源。

Topic 最小同步副本数

消息写入时至少要存在配置个数的可用副本才允许消息写入。配置值限制只能小于等于 Topic 副本数。如果 Topic 副本数为 3,最小同步副本数为 2,消息仅在至少写入 2 副本的情况下才会返回给客户端成功的响应。此方案在提高数据可靠性的同时,会牺牲一些可用性。

Kafka 生产者客户端

火山引擎消息队列 Kafka版完全兼容开源客户端的消息发送。开源 Kafka 2.2 以上版本的生产者客户端支持的数据可靠性参数如下。

配置

说明

acks

消息写入成功严格性配置。支持设置为 0、1、-1 或 all。其中 -1 和 all 所代表的语义相同。

  • 0 表示客户端无需获取服务端写入的结果。该配置的性能高,数据丢失风险高。
  • 1 表示消息写入主副本则认为写入成功,写入主副本后服务端则返回写入成功。该配置的性能一般,主节点宕机时,存在一定的数据丢失风险。
  • -1 或者 all 表示消息要写入当前所有正在同步中的副本才任务写入成功,仅在写入所有同步中副本后,服务端才会返回写入成功,任意同步中副本写入失败,服务端都会返回写入失败。该配置的性能差,但数据安全风险低,主备节点同时宕机时才会导致数据丢失。

max.in.flight.requests.per.connection

同时发送的最大请求个数。可配置 1 个或多个。若配置大于 1 时,考虑到消息发送失败重试的场景,消息发送在同一个生产者中也无法保证消息有序。

retries

消息发送失败后的重试次数。可配置 0 次、1 次或多次。Apache Java 客户端默认无限次重试。

enable.idempotence

消息幂等性配置。若配置开启,则在生产端会保证消息的幂等性。

Kafka 消费者客户端

通过以上服务端和客户端的参数配置,您可以最大限度地保证数据在发送和存储过程中的可靠性。但在数据消费端,则需要保证客户端能正确处理读取到的消息。您可以在消费者客户端按需配置以下参数。

配置

说明

enable.auto.commit

是否开启自动提交。建议关闭自动提交,保证在消息处理成功后再进行消费提交。

auto.offset.reset

消费组无有效消费记录时将使用此策略进行消费位点初始化。默认为 latest。支持设置为:

  • earliest:从 Topic 中最老的消息进行读取。
  • latest:从 Topic 中最新的消息进行读取。
  • none:抛出错误。