可靠性保证

  • ACID规范:原子性、一致性、隔离性和持久性
  • kafka可以保证分区内消息的顺序
  • 只有当消息被写入分区的所有同步副本时(但不一定写入磁盘),才被称为“已提交”的消息
  • 只要还有一个副本时活跃的,那么已提交的消息就不会丢失
  • 消费者只能读取已提交的消息

复制

复制功能是kafka架构的核心。在个别节点失效时仍能保证kafka的可用性和持久性。kafka使用topic(逻辑概念)组织数据,每个topic被分为若干了partition(物理概念),每个partition有多个replication,replication保存在broker上,每个broker可以保存成百上千个replication。

副本类型:

  • leader:每个分区只有一个leader。为了保证一致性,所有的producer和consumer请求都会经过leader。
  • follower:不处理请求,只负责从leader复制消息,与leader保持同步,及时复制最新的消息。当leader不可用时,其中一个同步副本将成为新leader。只有同步副本才能成为新leader。

同步副本:

  • 过去6秒(可配置)向ZK发送过心跳
  • 过去10秒(可配置)从leader获取过消息
  • 过去10秒从leader获取过最新的消息

Broker配置

broker有3个配置参数影响kafka消息存储的可靠性:

  • 复制系数:broker级别参数default.replication.factor,topic级别参数replication.factor。默认值3。如果复制系数为N,那么在N-1个broker失效的情况下,仍然能从topic读取或者写入数据。更高的复制系数会带来更高的可用性、可靠性和更少的故障,但复制系数N需要至少N个broker,而且会保存N份数据,占用N倍磁盘空间。故需要在可用性和存储资源之间做出权衡。副本的位置也很重要,kafka确保partition的副本被放在不同的broker上,并把broker分布在多个不同的机架上,从而获得更高的可用性。
  • 不完全首领选举unclean.leader.election只能在broker级别控制,默认值true。在选举新leader时,其他副本都是不同步的,该怎么办?两种选择:
    • 不同步的follower不能选为新的leader。那么,分区在旧的leader恢复前是不可用的,降低了可用性;
    • 不同步的follower可以选为新的leader。那么会造成丢失数据,导致数据不一致的风险。
  • 最少同步副本:broker级别和topic级别参数min.insync.replicas。尽管一个topic配置了3个副本,还是会出现只有一个同步副本的情况,如果这个同步副本变为不可用,就必须在可用性和一致性之间做出两难选择。如果要确保已提交的数据被写入不止一个副本,就需要把最少同步副本参数设置为大一点的值。对于一个包含3个副本的topic,如果min.insync.replicas被设置为2,那么至少要存在两个同步副本才能向partition写入数据。

在可靠的系统里使用producer

  • 发送确认:producer可选择以下3种确认模式:

    • acks=0:producer通过网络把消息发送出去,就认为成功写入kafka。
      • 优点:运行速度快,最高的吞吐率和带宽利用率
      • 缺点:丢失数据
    • acks=1:leader在收到消息并写入分区文件,就认为成功写入kafka。
      • 优点:速度较快,相对较高的吞吐率和带宽利用率
      • 缺点:丢失数据
    • acks=all或-1:leader在返回确认或错误响应之前,会等待所有同步副本都收到消息。
      • 优点:最可靠
      • 缺点:速度最慢,较低的吞吐率和带宽利用率
  • producer的重试发送:producer需要处理的错误包括:producer可以自动处理的错误和需要开发者手动处理的错误。一般情况下,如果目标是不丢失数据,那么最好让producer在遇到错误时保持重试,如leader选举和网络连接问题。但要注意,重试发送一个已经失败的消息会带来一些风险,如果两次重试都写入成功,会导致消息重复——至少保存一次。