注意:从kafka-0.9版本及以后,kafka的消费者组和offset信息就不存zookeeper了,而是存到broker服务器上,所以,如果你为某个消费者指定了一个消费者组名称(group.id),那么,一旦这个消费者启动,这个消费者组名和它要消费的那个topic的offset信息就会被记录在broker服务器上

1.概述
Kafka版本[0.10.1.1],已默认将消费的 offset 迁入到了 Kafka 一个名为 __consumer_offsets 的Topic中。其实,早在 0.8.2.2 版本,已支持存入消费的 offset 到Topic中,只是那时候默认是将消费的 offset 存放在 Zookeeper 集群中。那现在,官方默认将消费的offset存储在 Kafka 的Topic中,同时,也保留了存储在 Zookeeper 的接口,通过 offsets.storage 属性来进行设置。

2.内容
其实,官方这样推荐,也是有其道理的。之前版本,Kafka其实存在一个比较大的隐患,就是利用 Zookeeper 来存储记录每个消费者/组的消费进度。虽然,在使用过程当中,JVM帮助我们完成了一些优化,但是消费者需要频繁的去与 Zookeeper 进行交互,而利用ZKClient的API操作Zookeeper频繁的Write其本身就是一个比较低效的Action,对于后期水平扩展也是一个比较头疼的问题。如果期间 Zookeeper 集群发生变化,那 Kafka 集群的吞吐量也跟着受影响。

在此之后,官方其实很早就提出了迁移到 Kafka 的概念,只是,之前是一直默认存储在 Zookeeper集群中,需要手动的设置,如果,对 Kafka 的使用不是很熟悉的话,一般我们就接受了默认的存储(即:存在 ZK 中)。在新版 Kafka 以及之后的版本,Kafka 消费的offset都会默认存放在 Kafka 集群中的一个叫 __consumer_offsets 的topic中。

当然,其实她实现的原理也让我们很熟悉,利用 Kafka 自身的 Topic,以消费的Group,Topic,以及Partition做为组合 Key。所有的消费offset都提交写入到上述的Topic中。因为这部分消息是非常重要,以至于是不能容忍丢数据的,所以消息的 acking 级别设置为了 -1,生产者等到所有的 ISR 都收到消息后才会得到 ack(数据安全性极好,当然,其速度会有所影响)。所以 Kafka 又在内存中维护了一个关于 Group,Topic 和 Partition 的三元组来维护最新的 offset 信息,消费者获取最新的offset的时候会直接从内存中获取。

kafka 提供三种语义的传递:

1至少一次

2至多一次

3精确一次

  首先在 producer 端保证1和2的语义是非常简单的,至少一次只需要同步确认即可(确认方式分为只需要 leader 确认以及所有副本都确认,第二种更加具有容错性),至多一次最简单只需要异步不断的发送即可,效率也比较高。目前在 producer 端还不能保证精确一次,在未来有可能实现,实现方式如下:在同步确认的基础上为每一条消息加一个主键,如果发现主键曾经接受过,则丢弃

  在 consumer 端,大家都知道可以控制 offset,所以可以控制消费,其实 offset 只有在重启的时候才会用到。在机器正常运行时我们用的是 position,我们实时消费的位置也是 position 而不是 offset。我们可以得到每一条消息的 position。如果我们在处理消息之前就将当前消息的 position 保存到 zk 上即 offset,这就是只多一次消费,因为我们可能保存成功后,消息还没有消费机器就挂了,当机器再打开时此消息就丢失了;或者我们可以先消费消息然后保存 position 到 zk 上即 offset,此时我们就是至少一次,因为我们可能在消费完消息后offset 没有保存成功。而精确一次的做法就是让 position的保存和消息的消费成为原子性操作,比如将消息和 position 同时保存到 hdfs 上 ,此时保存的 position 就称为 offset,当机器重启后,从 hdfs重新读入offset,这就是精确一次。

  • consumer可以先读取消息,然后将offset写入日志文件中,然后再处理消息。这存在一种可能就是在存储offset后还没处理消息就crash了,新的consumer继续从这个offset处理,那么就会有些消息永远不会被处理,这就是上面说的“最多一次”。
  • consumer可以先读取消息,处理消息,最后记录offset,当然如果在记录offset之前就crash了,新的consumer会重复的消费一些消息,这就是上面说的“最少一次”。
  • “精确一次”可以通过将提交分为两个阶段来解决:保存了offset后提交一次,消息处理成功之后再提交一次。但是还有个更简单的做法:将消息的offset和消息被处理后的结果保存在一起。比如用Hadoop ETL处理消息时,将处理后的结果和offset同时保存在HDFS中,这样就能保证消息和offser同时被处理了。

kafka offset的存储问题的更多相关文章

  1. kafka offset存储

    存储方式 方式 方式来源 存储位置 自动提交 kafka kafka 异步提交 kafka kafka checkpoint spark streaming hdfs hbase存储 程序开发 hba ...

  2. kafka的log存储解析——topic的分区partition分段segment以及索引等

    转自:http://blog.csdn.net/jewes/article/details/42970799 引言 Kafka中的Message是以topic为基本单位组织的,不同的topic之间是相 ...

  3. Kafka深入理解-2:Kafka的Log存储解析

    摘自http://blog.csdn.net/jewes/article/details/42970799 引言 Kafka中的Message是以topic为基本单位组织的,不同的topic之间是相互 ...

  4. Kafka文件的存储机制

    Kafka文件的存储机制 同一个topic下有多个不同的partition,每个partition为一个目录,partition命名的规则是topic的名称加上一个序号,序号从0开始. 每一个part ...

  5. Kafka(3)--kafka消息的存储及Partition副本原理

    消息的存储原理: 消息的文件存储机制: 前面我们知道了一个 topic 的多个 partition 在物理磁盘上的保存路径,那么我们再来分析日志的存储方式.通过 [root@localhost ~]# ...

  6. Kafka#4:存储设计 分布式设计 源码分析

    https://sites.google.com/a/mammatustech.com/mammatusmain/kafka-architecture/4-kafka-detailed-archite ...

  7. kafka的log存储解析——topic的分区partition分段segment以及索引等(转发)

    原文 https://www.cnblogs.com/dorothychai/p/6181058.html 引言 Kafka中的Message是以topic为基本单位组织的,不同的topic之间是相互 ...

  8. Kafka的Log存储解析

    引言 Kafka中的Message是以topic为基本单位组织的,不同的topic之间是相互独立的.每个topic又可以分成几个不同的partition(每个topic有几个partition是在创建 ...

  9. Kafka消息文件存储

    在对消息进行存储和缓存时,Kafka依赖于文件系统.(Page Cache) 线性读取和写入是所有使用模式中最具可预计性的一种方式,因而操作系统采用预读(read-ahead)和后写(write-be ...

随机推荐

  1. 2015 Multi-University Training Contest 3 hdu 5323 Solve this interesting problem

    Solve this interesting problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K ...

  2. BeautifulSoup的高级应用 之.parent .parents .next_sibling.previous_sibling.next_siblings.previous_siblings

    继上一篇BeautifulSoup的高级应用,主要解说的是contents children descendants string strings stripped_strings.本篇主要解说.pa ...

  3. 【Android UI】案例02 圆角边框、圆角背景的实现(shape)

    本文主要分享圆角边框与圆角背景的实现方式.该方式的实现,须要了解shape的使用.该部分的具体介绍,请阅读博客http://blog.csdn.net/mahoking/article/details ...

  4. Constructor call must be the first statement in a constructor

    super()和this ()不能共存.否则编译时会报异常. Constructorcall must be the first statement in a constructor 换句话说就是su ...

  5. CMD应用 qtp/winshell/cmd的交互

    =================================================================== '採用windows.shell的 sendkeys 方式: s ...

  6. zzulioj--1827--石锅全拌(区间求和水题)

    1827: 石锅全拌 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 6  Solved: 3 SubmitStatusWeb Board Descri ...

  7. 6. MongoDB——Java操作(增删改查)

    转自:https://blog.csdn.net/kai402458953/article/details/79626148 import java.net.UnknownHostException; ...

  8. Oracle数据库Helper类

    using System;using System.Collections.Generic;using System.Data;using System.Data.OleDb;using System ...

  9. 请问Typecho Mysql 数据库和Sqlite数据库我该如何选择。

    纠结如我,又纠结了,请大家帮忙看一下我该如何选择.就一个没有文章的博客.一直用VPS太浪费,现在换成了虚拟主机.但是虚拟主机的MYSQL数据库限制连接数30个,我不懂这是个什么概念,但是我觉得30太少 ...

  10. html页面颜色名称和颜色值转换

    public static string ToHtmlColor(string colorName) { try { if (colorName.StartsWith("#")) ...