[toc]

可靠数据传递

可靠性保证

关系型数据库可靠性保证一般是ACID(原子、一致、隔离、持久)

那么Kafka提供哪些方面的保证呢

  • 分区消息的顺序,同一个生产者往同一个分区写入消息,那么Kafka会保证消息会按生产者写入的顺序进入分区,且消费者会按这个顺序进行消费
  • 只有当消息被写入分区的所有同步副本时(不一定写入磁盘了,可能是交付给了文件系统缓存),才被认为是已提交
  • 只要还有一个副本是活跃的,那么已经提交的消息就不会丢失
  • 消费者只能读取已提交的消息

Kafka只是提供了这些基础的保证,需要结合场景进行配置来达到数据的可靠性

复制

Kafka的主题被分为多个分区,分区可以是在线的也可以是离线(不可用)的,每个分区可以有多个副本,其中一个为首领,所有事件都由首领处理,其余副本会自动从首领同步数据,跟随者需要满足以下条件才被认为是同步的

  • 与zookeeper见有一个活跃的会话(6s内发送过心跳)
  • 过去10s内从首领获取过消息
  • 过去10s内从首领哪里获取过最新的消息

如果一个或多个副本在同步和非同步间快速切换,通常是因为JVM不恰当的垃圾回收配置导致的;一个滞后的同步副本会导致生产和消费者变慢;非同步副本也滞后,但是不会对性能产生影响

broker配置

broker有3个参数会影响Kafka消息存储的可靠性

复制系数

也就是会有几个副本,默认是3个,更多的副本数量会带来更高的数据可靠性,同时也带来硬件成本的增加,当然如果生产者设置了严格的acks的话,更多的副本也可能带来性能的下降,所以还是要结合数据的重要程度来进行配置

不完全的首领选举

有的情况下,如果首领宕机了,但是没有跟随者副本是完全同步的话,可以通过unclean.leader.election来配置是否允许不同步的副本称为首领,默认是True

最少同步副本

也就是说最少要有几个同步状态的副本时,首领才会继续接收生产者消息

在可靠的系统里使用生产者

  • 配置合适的发送确认参数
  • 配置生产者重试参数
  • 额外的错误处理

在可靠的系统里使用消费者

消费者的可靠性配置

  • group,通过分组来协调消费者
  • auto.offset.reset:指定了在没有偏移量可提交(消费者首次启动时)活着请求的偏移量在broker上不存在时,消费者的行为
    • earliest:从分区的开始位置读取数据
    • latest:从分区的末尾开始读取数据
  • enable.auto.commit:这是一个重要的参数,决定消费者是否自动提交偏移量
    • 自动提交:好处是省事,轮询过程中自动提交已经处理过的偏移量,缺点是可能出现重复消费,比如消费者在自动提交之前停止了,或者消息如果被交到另一个线程去处理,那么很可能还没有被处理完之前偏移量就已经被提交了

显式提交偏移量

  • 总在处理完时间后再提交,如果所有的业务操作都是在轮询里面完成的,且不需要和别的轮询产生耦合,那可以使用自动提交或者在轮询结束时进行手动提交
  • 提交频度,如果每次轮询完成都提交性能会低一些,多次轮询完成后手动提交一次性能高一些,但可能出现重复消费
  • 确保对题啊急哦对偏移量心里有数:确保是在消息被处理完成之后再提交
  • 消费者可能需要重试:一个恶心的场景,2号消息被处理成功了,但是1号消息失败了,这个时候如果提交偏移量2的话,1就被覆盖提交了
    • 第一种处理,遇到可重试错误是,提交最后一个处理成功的偏移量,吧还没处理好的消息保存到缓存中,调用消费者的pause方法确保且他轮询不会返回数据,保持轮询的同时进行重试处理,如果超出重试次数失败那消息会被丢失,且记录错误,调用resume方法继续轮询
    • 第二种处理,把错误写入一个独立的主题进行处理
  • 消费者可能需啊哟维护状态:比如轮询得到平均值,这个时候可以把这个结果值和偏移量一起保存到主题上,Kafka提供这样的一个极致
  • 长时间处理:如果消费逻辑非常耗时,那不能一直处理,这样没有心跳broker会认为消费者消亡了,这个时候可以使用连接池
  • 仅一次传递:指一次消费,介绍了几种方式都是依赖外部容器进行唯一性校验,本质上Kafka没有单次消费策略

验证系统可靠性

就是通过各种边界情况去对系统进行测试

  • 配置验证
  • 应用程序验证
  • 在生产环境监控可靠性