kafka术语
|
|-1.Broker:消息中间件处理结点,一个Kafka节点就是一个broker,多个broker能够组成一个Kafka集群。
|
|-2.Topic:一类消息,比如page view日志、click日志等都能够以topic的形式存在。Kafka集群能够同一时候负责多个topic的分发。
|
|-3.Partition:topic物理上的分组。一个topic能够分为多个partition,每一个partition是一个有序的队列。
|
|-4.Segment:partition物理上由多个segment组成。
|
|-5.offset:每一个partition都由一系列有序的、不可变的消息组成,这些消息被连续的追加到partition中。
| partition中的每一个消息都有一个连续的序列号叫做offset,用于partition中唯一标识的这条消息。
Kafka文件存储基本结构
|
|-文件名:partiton命名规则为topic名称+有序序号,第一个partiton序号从0开始,序号最大值为partitions数量减1
|
|-每个partion(分区)相当于一个巨型文件被平均分配到多个大小相等segment(段)数据文件中
| 但每个段segment file消息数量不一定相等,这种特性方便old segment file快速被删除。默认保留7天的数据
|
|-每个partiton只需要支持顺序读写就行了,segment文件生命周期由服务端配置参数决定(什么时候创建,什么时候删除)
_____________________________________________________________________________________
| ________________________________________________ |
| Partition 0 |_0_|_1_|_2_|_3_|_4_|_5_|_6_|_7_|_8_|_9_|_10_|_11_| 12 |
| \ |
| ___________________________________ \ |
| Partition 1 |_0_|_1_|_2_|_3_|_4_|_5_|_6_|_7_|_8_| 9 <-------------- Writes(顺序写) |
| / |
| ____________________________________________ / |
| Partition 2 |_0_|_1_|_2_|_3_|_4_|_5_|_6_|_7_|_8_|_9_|_10_| 11 / |
| |
| Old------------------------------------------------->New |
|_____________________________________________________________________________________|
topic中partition存储分布
|
|-如果实验环境中Kafka集群仅仅有一个broker。
|
|-xxx/message-folder为数据文件存储根文件夹。
|
|-在Kafka broker中server.properties文件配置(參数log.dirs=xxx/message-folder)。
|
|-比如创建2个topic名称分别为report_push、launch_info|--存储路径和文件夹规则为:
| partitions数量都为partitions=4 | xxx/message-folder/
| | |–report_push-0
| | |–report_push-1
| | |–report_push-2
| | |–report_push-3
| | |–launch_info-0
| | |–launch_info-1
| | |–launch_info-2
| | |–launch_info-3
partiton中文件存储方式
|
|-每一个partion(文件夹)相当于一个巨型文件被平均分配到多个大小相等segment(段)数据文件里。
|
|-但每一个段segment file消息数量不一定相等,这样的特性方便old segment file高速被删除。(默认情况下每一个文件大小为1G)
|
|-每一个partiton仅仅须要支持顺序读写即可了。segment文件生命周期由服务端配置參数决定。
|
|-这样做的优点就是能高速删除无用文件。有效提高磁盘利用率。
________________________________________
| |
| partition 0 100GB+ |
| ______________ ______________ |
| | | | | |
| |500MB | |500MB | |
| |segment file 1| |segment file 2| |
| |______________| |______________| |
| |
| ______________ |
| | | |
| |500MB | ... |
| |segment file 3| |
| |______________| |
|________________________________________|
partiton中segment文件存储结构
|
|-segment file组成|--index file:后缀”.index”,表示为segment索引文件
| |--data file:后缀“.log” ,表示为segment数据文件
| |--此2个文件一一相应,成对出现
|
|-segment文件命名规则|--partion全局的第一个segment从0開始,
| |--兴许每一个segment文件名称为上一个segment文件最后一条消息的offset值。
| |--数值最大为64位long大小。19位数字字符长度,没有数字用0填充。
|
|-以下文件列表是在Kafka broker上做的一个实验,创建一个topicXXX包括1 partition,
| 设置每一个segment大小为500MB,并启动producer向Kafka broker写入大量数据,
| segment文件列表|--00000000000000000000.index
| |--00000000000000000000.log
| |--00000000000000368769.index
| |--00000000000000368769.log
| |--00000000000000737337.index
| |--00000000000000737337.log
| |--00000000000001105814.index
| |--00000000000001105814.log
| | ...
|
|-索引文件存储大量元数据,数据文件存储大量消息,索引文件里元数据指向相应数据文件里message的物理偏移地址
| 当中以索引文件里元数据3,497为例,依次在数据文件里表示第3个message、以及该消息的物理偏移地址为497
| |________________________________________________________________
| | |
| | 00000000000000368769.index 00000000000000368769.log |
| | 1 , 0 Message368770 0 |
| | 3 , 497 Message368771 139 |
| | 6 , 1407 Message368772 497 |
| | 8 , 1686 Message368773 830 |
| | ... Message368774 1262 |
| | N , position Message368775 1407 |
| | Message368776 1508 |
| | Message368777 1686 |
| | ... ... |
| | Message36877+N position |
| |________________________________________________________________|
|
|-数据文件(.log文件)中,message物理结构\ _________________________
| | | 8 byte offset |
| | | 4 byte message size |
| | | 4 byte CRC32 |
| | | 1 byte "magic" |
| | | 1 byte "attributes" |
| | | 4 byte key length |
| | | K byte key |
| | | 4 byte payload length |
| | | _____________________ |
| | | | | |
| | | | value bytes payload | |
| | | |_____________________| |
| | |_________________________|
| |--8 byte offset 在parition(分区)内的每条消息都有一个有序的id号,这个id号被称为偏移(offset),它能够唯一确定每条消息在parition(分区)内的位置
| |--4 byte message size message大小
| |--4 byte CRC32 用crc32校验message
| |--1 byte "magic" 表示本次公布Kafka服务程序协议版本号
| |--1 byte "attributes" 表示为独立版本号、或标识压缩类型、或编码类型
| |--4 byte key length 表示key的长度,当key为-1时,K byte key字段不填(K byte key 可选)
| |--value bytes payload 表示实际消息数据
Kafka特性
|
|-Kafka执行时间非常少,有大量读磁盘的操作。主要是定期批量写磁盘操作。因此操作磁盘非常高效。
| 这跟Kafka文件存储中读写message的设计是息息相关的。
|
|-Kafka中读写message特点|--写message:消息从java堆转入page cache(即物理内存)。由异步线程刷盘,消息从page cache刷入磁盘。
| |
| |--读message:消息直接从page cache转入socket发送出去。
| | 当从page cache没有找到相应数据时,此时会产生磁盘IO,从磁盘Load消息到page cache,然后直接从socket发出去
|
|-Kafka高效文件存储设计特点|--1.Kafka把topic中一个parition大文件分成多个小文件段。通过多个小文件段,就easy定期清除或删除已经消费完文件。降低磁盘占用。
| |--2.通过索引信息能够高速定位message和确定response的最大大小。
| |--3.通过index元数据所有映射到memory,能够避免segment file的IO磁盘操作。
| |--4.通过索引文件稀疏存储,能够大幅降低index文件元数据占用空间大小。
|
|-kafka为什么快|--Kafka在磁盘上只做Sequence I/O,由于消息系统读写的特殊性,这并不存在什么问题
| |
| |--Kafka使用了底层操作系统提供的PageCache功能。
| | 当上层有写操作时,操作系统只是将数据写入PageCache,同时标记Page属性为Dirty。
| | 当读操作发生时,先从PageCache中查找,如果发生缺页才进行磁盘调度,最终返回需要的数据。
| | 实际上PageCache是把尽可能多的空闲内存都当做了磁盘缓存来使用。
| | 同时如果有其他进程申请内存,回收PageCache的代价又很小,所以现代的OS都支持PageCache。
| | 使用PageCache功能同时可以避免在JVM内部缓存数据,JVM为我们提供了强大的GC能力,同时也引入了一些问题不适用与Kafka的设计。
| |
| |--Kafka为了进一步的优化性能还采用了Sendfile技术(直接在内核区完成数据拷贝)
Kafka部署及使用
|
|-1.download the code|--> tar -xzf kafka_2.11-0.11.0.0.tgz
| |--> cd kafka_2.11-0.11.0.0
|
|-2.Start the Server
| Kafka uses Zookeeper so you need to first start a Zookeeper server
|
|-3.$kafka_home/config/server.properties|--broker.id = 0
| |--listeners
| |--host.name
| |--log.dirs
| |--zookeeper.connect
|
|-4.start|--> bin/zookeeper-server-start.sh config/zookeeper.properties
| |--> bin/kafka-server-start.sh config/server.properties
|
|-5.test|--> bin/kafka-topics.sh --create --zookeeper hadoop000.2181 --replication-factor 1 --partitions 1 --topic test
| |--> bin/kafka-topics.sh --list --zookeeper hadoop000:2181
| |--> bin/kafka-console-producer.sh --broker-list hadoop000.9092 --topic test
| |--> bin/kafka-console-consumer.sh --zookeeper hadoop000.2181 --topic test --from-beginning
| |--> bin/kafka-topics.sh --describe --zookeeper hadoop000:2181
| |--> bin/kafka-topics.sh --describe --zookeeper hadoop000:2181 --topic test
|
|-6.生产者API|--Properties props = new Properties();
| | props.put("metadata.broker.list",KafaPropUtils.BROKER_LIST);
| | props.put("serializer.class","kafka.serializer.StringEncoder");
| | props.put("request.required.acks","1");
| | Producer<Integer,String> producer = new Producer<Integer, String>(new ProducerConfig(props));
| | producer.send(new KeyedMessage<Integer, String>("topic01","message01"));
|
|-7.消费者API|--Properties props = new Properties();
| | props.put("zookeeper.connect",KafaPropUtils.ZK);
| | props.put("group.id",KafaPropUtils.GROUP_ID);
| | ConsumerConnector consumer = Consumer.createJavaConsumerConnector(new ConsumerConfig(props));
| | consumer.createMessageStreams(topicCountMap);