一些关于kafka的笔记

来源:互联网 发布:现实爆炸录像软件 编辑:程序博客网 时间:2024/05/19 05:02

kafka存储结构

kafka存储结构

  • 一条kafka消息(message)被定义为: {offset:<long>, MessageSize: <int>, data: <string>}. topic相同的producer们产生的message被集中放到一起, 即以该topic命名的目录下

  • 为使topic中的message可以被多个consumer并行访问, topic又被分为若干partition.

  • 逻辑上, message被存储在partition中, message.offset即此message在其partition中的下标. 因此(topic, partition, offset)可以在kafka中唯一定位一条message.

  • 实现上,若partition被存储为一个文件, 那么这个文件将很大, 随机访问其中的一条消息会由此变得很慢. 因此, 为了加速对partition的访问的过程, partition被分为很多segment, 这样, 每个partition实际上对应一个目录, 而每个segment对应一个文件.

  • partition被命名为<topic-name>-<index>, index为该partition的下标; segment被命名为<offset>.log, offset为该segment中第一条message的offset

  • 这样, 对于存储在.log文件中的message, 其offset字段不必存储其绝对下标, 只要存储其相对该segment中第一条消息的相对下标就可以了. 例如, 若一个segment的文件命名为47.log, 则其中第一条message的offset字段为0, 表示该partition中下标为47的那条消息.

  • kafka还想进一步加速对segment的访问过程, 为此kafka为每个segment生成一个索引文件, 命名为<offset>.index, .index文件很小, 可以直接放在内存中

  • .index文件由消息索引构成, 每条消息索引的结构为{offset, position}, offset是消息下标, position是该消息在.log文件中的字节偏移.

  • .index文件是稀疏索引的, 它并不为每条消息存储消息索引, 而是有选择地为.log文件中的若干消息创建消息索引.

  • 为了在topic中查找消息(topic, partition, offset), kafka会:

    1. 定位到partition目录
    2. 根据offset计算该消息所在的.log文件
    3. 打开.log文件对应的.index文件, 定位到一条消息索引
    4. 打开.log文件, 跳转到消息索引的position位置
    5. 顺序遍历, 找到目标消息

replica

  • kafka将数据存储在hadoop集群中, 集群中的每台服务器被称为一个broker.

  • kafka以partition作为message的基本存储单元, 每个partition都被存储于一台具体的broker上. 一旦borker损坏, 整个partition也随之损坏. 为了避免此类问题, 每个partition实际上有很多副本(replica), 这些replica通常分布在不同的broker上.

  • 同一个partition的replica们分为两种角色, leader和follower. leader负责与producer/consumer交互, 逻辑上代表这个partition. follower则不断从leader同步数据, 保证数据的冗余性. leader所在的broker宕机后, kafka会通过选举算法从follower中选出新的leader.

  • producer将一条message发送到leader(partition)后, leader向ISR(in-sync replica)列表中的所有follower转发此message, 收到message的follower会向leader发送ACK. 当收到所有follower的ACK后, leader增加其HW(high watermark)值, 并向producer发送ACK. 此时, 我们说这条消息已经被提交(commit). 只有commit过的消息才会暴露给consumer, 因此HW实际上对应着partition中可以访问的最新message的下标.

java 中的 kafka

  • kafka有两套api:kafka.api 以及kafka.javaapi, 很多类同时在这两个包中定义, 我的原则是, 优先使用kafka.javaapi.kafka.api貌似与scala有关? 并且是一套旧的api?

  • 在较高层次的抽象上, 从天上看下去, 我们能看到这样几个东西:

    • consumer: 消费消息
    • topic: 频道/消息频道
    • stream: 消息流
    • group: 消费者组
    • partition: topic块

  • 关于消费者组:

    • 消费者组跟消费者的关系跟”进程=线程组”的关系类似
    • 一个topic中的一条消息只能被一个消费者组消费一次
    • 每个partition只能被一个线程消费(所以, consumer多于partition就是浪费)

  • 关于stream:

    • 消费者不是直接从partition中读取消息, 而是从stream中读取
    • stream建立在partition之上, partition将会尽可能平衡得被关联到每个stream.
    • 通常, 一个consumer严格对应于一个stream, 所以我们似乎可以认为consumer与partition是直接对应的
    • 消费者会阻塞在一个空的stream上

两个消费者通过两个stream从4个partition中读取数据

参考资料

  1. Kafka的Log存储解析, http://blog.csdn.net/jewes/article/details/42970799
  2. Kafka设计解析(二): Kafka High Availability (上), http://www.infoq.com/cn/articles/kafka-analysis-part-2/
原创粉丝点击