Kafka 学习 -- Topic的创建

来源:互联网 发布:淘宝如何缴纳保证金 编辑:程序博客网 时间:2024/06/15 19:58
1. 使用命令行方式:

[lch@linux129 bin]$ ./kafka-topics.sh --create --zookeeper hadoop221:2181,hadoop222:2181 --replication-factor 2 --partitions 2 --topic TEST_TTT

参数说明:
--replication-factor : 表明 副本的个数, 这里写成2,表明会有两个副本
--partitions              :  表明会有两个partition, 表现在log日志中,就是是有两个文件夹

即这TEST_TTT-0与TEST_TTT-1  
注: 在leader节点上面才是两个文件,如果是从节点上面,可能只有一个
--topic                      :   topic的名称 

2. 使用Java代码的方式:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class KafkaAdmin{
    public static void main(String[] args) {
        String[] arrys = new String[6];
        arrys[0] = "--replication-factor";
        arrys[1] = "1";
        arrys[2] = "--partitions";
        arrys[3] = "1";
        arrys[4] = "--topic";
        arrys[5] = "EFGH";
        ZkClient client =  new ZkClient("192.168.8.222:2181"3000030000);
        client.setZkSerializer(new ZKStringSerialize());   //一定要加上ZkSerializer
      
        TopicCommandOptions opts = new TopicCommandOptions(arrys);     
        TopicCommand.createTopic(client, opts); 
    }
}
    
对于scala不是太熟,不知道怎么调用scala中的Object,因此依照scala中的ZKStringSerializer,实现了一个
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class ZKStringSerialize implements ZkSerializer {
    @Override
    public byte[] serialize(Object data) throws ZkMarshallingError {
        if(data instanceof String){
            try {
                return ((String)data).getBytes("UTF-8");
            catch (UnsupportedEncodingException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return null;
    }
    @Override
    public Object deserialize(byte[] bytes) throws ZkMarshallingError {
        if (bytes == null)
          return null;
        else
            try {
                return new String(bytes, "UTF-8");
            catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        return null;
    }
}
   
3. Topic创建的过程
不管是命令行还是代码创建,最终都是调用createTopic:: createTopic(),查看其代码
1
2
3
4
5
6
7
8
  def createTopic(...) {
    //从zookeeper的/brokers/ids目录下面获取broker的列表信息
    val brokerList = ZkUtils.getSortedBrokerList(zkClient)
    //此处会根据副本个数以及partition的个数,来分配broker节点, 即partition 0在哪几个节点上
    val replicaAssignment = AdminUtils.assignReplicasToBrokers(brokerList, partitions, replicationFactor)
    //分配完成后,就开始创建节点信息
    AdminUtils.createOrUpdateTopicPartitionAssignmentPathInZK(zkClient, topic, replicaAssignment, topicConfig)
  }
再查看AdminUtils.createOrUpdateTopicPartitionAssignmentPathInZK的代码:
1
2
3
4
5
6
7
8
 def createOrUpdateTopicPartitionAssignmentPathInZK(...) {
        .... ....
    // write out the config if there is any, this isn't transactional with the partition assignments
    writeTopicConfig(zkClient, topic, config)
     
    // create the partition assignment
    writeTopicPartitionAssignment(zkClient, topic, partitionReplicaAssignment, update)
  }
从上面可以看到,它会在zookeeper上面创建两个path,第一次:
  writeTopicConfig(zkClient, topic, config)
它创建的目录在zookeeper中的:


在config目录创建完成后,会在brokers中创建,即代码: writeTopicPartitionAssignment(zkClient, topic, partitionReplicaAssignment, update)
创建完成后,就会在zookeeper中看到下面的这些东西。


当创建代码完成这一步之后,就会返回成功,但是对于kafka来说还有一步没有完成,就是它还需要在log目录下面,针对每个topic创建相应的目录,以后的数据就会保存在这个目录下面。
创建目录的过程是通过zookeeper的文件监听来完成的。从controller.log中可以看得很清楚:
[2015-12-29 18:27:26,801] DEBUG [TopicChangeListener on Controller 0]: Topic change listener fired for path /brokers/topics with children MNPQ (kafka.controller.PartitionStateMachine$TopicChangeListener)
[2015-12-29 18:27:26,814] INFO [TopicChangeListener on Controller 0]: New topics: [Set(MNPQ)], deleted topics: [Set()], new partition replica assignment [Map([MNPQ,0] -> List(3))] (kafka.controller.PartitionStateMachine$TopicChangeListener)

4. 问题记录
1) 使用java代码创建topic的时候,程序返回成功了,但是log目录中没有创建相应的文件夹。 查看zookeeper中的信息:

原因:  client.setZkSerializer(new ZKStringSerialize());    没有设置字符串序列化函数,导致topic创建目录失败,而kafka的listen线程发现有文件夹变化后,在创建时,无法获取相应的broker信息,因此创建失败了

2) producer产生的数据,只放在partiton 0中,而partition 1中总是没有数据。
原因: producer产生的数据会根据key来选择partition,而我的代码:
1
     KeyedMessage km = new KeyedMessage<String, String>(this.topic, "123" ,data);
从网上下载下来,也没有弄清楚它的含义,直接将key设置为123,即key总是一样的,而kafka在计算的时候,也就总是算出同一个值。 

3) topic无法删掉
[root@hadoop221 bin]# ./kafka-topics.sh --delete  --zookeeper hadoop222:2181 --topic TEST
Topic TEST is marked for deletion.
Note: This will have no impact if delete.topic.enable is not set to true.
[root@hadoop221 bin]# ./kafka-topics.sh --list --zookeeper hadoop222:2181
TEST - marked for deletion
TEST_TTT - marked for deletion
[root@hadoop221 bin]# 

需要增加配置参数:delete.topic.enable=true


0 0