Apache Kafka

Spark,Hadoop交流群,群QQ号:521066396,欢迎加入共同学习,一起进步~

一、Apache Kafka简介

官方网址:http://kafka.apache.org/
Kafka™ is used for building real-time data pipelines and streaming apps. It is horizontally scalable, fault-tolerant, wicked fast, and runs in production in thousands of companies.
Kafka 是分布式的发布-订阅消息系统。它最初由 LinkedIn公司开发,使用 Scala语言编写,于2010年12月份开源,成为 Apache 项目的一部分。Kafka 是一个高吞吐量的、持久性的、分布式发布订阅消息系统。它主要用于处理活跃的流式数据(登录、浏览、点击、分享、喜欢等)。
高吞吐量:可以满足百万级别消息处理、非常适合产生大量数据的互联网服务的数据收集业务。
持久性:有一套完善的消息存储机制,确保数据的高效安全的持久化。
分布式:基于分布式的扩展、容错机制;Kafka的数据都会复制到几台服务器上。当某一台故障失效时,生产者和消费者转而使用其它的机器。

1、Kafka概述-消息队列

(1)消息队列(Message Queue)
(2)消息:网络中的两台计算机之间传递的数据。例如:文本、音乐、视频等内容。
(3)队列:一种特殊的线性表,特殊之处在于只允许在首部删除元素和在尾部追加元素。入队、出队。
(4)消息队列:保存消息的队列。消息的传输过程中的容器;主要提供生产、消费接口。
(5)主要的MQ产品:RabbitMQ、ActiveMQ、IBM WEBSPHERE MQ、kafka等。

2、MQ分类:点对点(P2P)、发布订阅(Pub/Sub)

1、共同点:
消息生产者生产消息发送到queue中,然后消息消费者从queue中读取并且消费消息。
2、不同点:
P2P模型包含:消息队列(Queue)、发送者(Sender)、接收者(Receiver)
一个生产者生产的消息只有一个消费者(Consumer),一旦被消费,消息就不在消息队列中。
Pub/Sub包含:消息队列(Queue)、主题(Topic)、发布者(Publisher)、订阅者(Subscriber)
每个消息可以有多个消费者,彼此互不影响。

3、Kafka组件

kafka从大的方面分为:主题[存储实现为代理]、生产者、消费者。
Topic:主题,Kafka处理的消息的不同分类。
Producer:消息和数据的生产者,向Kafka的一个topic发布消息。
Consumer:消息和数据的消费者,订阅topic并处理其发布的消息。
Broker:消息的代理,Kafka集群中的一个kafka服务节点称为一个broker,主要存储消息数据。
Partition:Topic物理上的分组,一个topic在broker中被分为1个或者多个partition。
Message:消息,是通信的基本单位,每个消息都属于一个partition。

4、Kafka拓扑

这里写图片描述

二、Kafka的安装

下载 http://kafka.apache.org/downloads.html
解压 tar -zxvf kafka_2.11-0.8.2.2.tgz -C /opt
mv /opt/kafka_2.11-0.8.2.2/ /opt/kafka
启动服务

1、配置和启动zookeeper服务

使用kafka内置zk
配置zk文件:/opt/kafka/config/zookeeper.properties 主要是:dataDir设置
启用zk服务:
./zkServer.sh start
或者/opt/kafka/bin/zookeeper-server-start.sh /opt/kafka/config/zookeeper.properties >> /opt/logs/kafka-zk.log 2>&1 &
netstat -an | grep 2181
使用公共的zk
在/opt/kafka/config/server.properties中的zookeeper.connect配置外界zk的地址

2、启动Kafka-server

配置相关参数/opt/kafka/config/server.properties
主要参数:broker.id、port、log.dirs
启动:bin/kafka-server-start.sh config/server.properties > /dev/null 2>&1 &
或者/opt/kafka/bin/kafka-server-start.sh /opt/kafka/config/server.properties >>/opt/logs/kafka-server.log 2>&1 &

三、操作Kafka-Topic

1、增:新增一个topic:”hello”,为它分配2个分区,保存一个副本

bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 2 --topic hello
replication-factor不能大于broker数
bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 3 --topic world

2、查:查询hello的信息

bin/kafka-topics.sh --describe --zookeeper localhost:2181 --topic hello

Topic:hello PartitionCount:2 ReplicationFactor:1 Configs:
Topic: hello Partition: 0 Leader: 0 Replicas: 0 Isr: 0
Topic: hello Partition: 1 Leader: 0 Replicas: 0 Isr: 0
Leader:partition的leader,主要用的brokerid 0
Replicas:partition的总的副本brokerid的集合 0
Isr:partition的可用的副本brokerid的集合 0
Topic: hello Partition: 0 Leader: 1 Replicas: 1,2,0 Isr: 1,2,0
Topic: hello Partition: 1 Leader: 2 Replicas: 2,0,1 Isr: 2,0,1
Topic: hello Partition: 2 Leader: 0 Replicas: 0,1,2 Isr: 0,1,2
Topic: hello Partition: 3 Leader: 1 Replicas: 1,0,2 Isr: 1,0,2
所有可以使用的topic

bin/kafka-topics.sh --list --zookeeper localhost:2181

3、改:修改hello为2个分区 alter:修改partition数(只能增加)和配置项

bin/kafka-topics.sh --alter --zookeeper localhost:2181 --partitions 3 --topic hello --config segment.bytes=1000000000

4、删:删除world的topic

bin/kafka-topics.sh --delete --zookeeper localhost:2181 --topic world
是否开启topic的删除功能:默认为false。 delete.topic.enable

四、操作Kafka-生产消费

1、创建生产者 producer

创建生产者 producer(往哪些broker生产,生产主题是什么)

bin/kafka-console-producer.sh --broker-list localhost:9092 --topic hello

2、创建消费者 consumer

创建消费者 consumer(上次消费到哪儿了【存在zookeeper上】,消费主题是什么)

bin/kafka-console-consumer.sh --zookeeper localhost:2181 --topic hello --from-beginning

3、标记删除的topic也可以使用

4、生产者:topic、broker-list

5、消费者:topic 、zookeeper

五、broker扩展

Broker:考虑什么问题:数据和硬盘的交互IO。数据的保存期限。
Broker:配置文件server.properties
1、为了减少磁盘写入的次数,broker会将消息暂时buffer起来,当消息的个数达到一定阀值或者过了一定的时间间隔时,再flush到磁盘,这样减少了磁盘IO调用的次数。
配置:Log Flush Policy

log.flush.interval.messages=10000
log.flush.interval.ms=1000

默认都是Long.MAX_VALUE即:9223372036854775807
2、kafka的消息保存一定时间(通常为7天)后会被删除。配置:Log Retention Policy
3、Broker只关心数据存储,不保存消费者的状态,由消息订阅者自己维护。消息订阅者可以rewind back【倒带】到任意位置重新进行消费,当订阅者故障时,可以选择最小的offset(id)进行重新读取消费消息。重新消费数据公司中经常用到。

六、producer扩展

Producer:配置文件:producer.properties

1、自定义partition

Producer也根据用户设置的算法来根据消息的key来计算输入哪个partition:partitioner.class

2、异步或者同步发送

配置项:producer.type

3、批量发送可以很有效的提高发送效率。

Kafka producer的异步发送模式允许进行批量发送,先将消息缓存在内存中,然后一次请求批量发送出去。
具体配置queue.buffering.max.ms、queue.buffering.max.messages。
默认值分别为5000和10000

七、consumer扩展

consumers:配置文件:consumer.properties
1、每个consumer属于一个consumer group,可以指定组id。group.id
2、宏观上看,对于一个Topic的消息,每个消费组消费相同的数据,互不影响;组内的消费者消费同一份数据,各自的内容不同。
3、一个Topic中的一个partions,对于同一个消费者组,只会被一个consumer消费,不过一个consumer可以消费多个partitions中的消息。所以,对于一个topic,同一个group中推荐不能有多于partitions个数的consumer同时消费,否则将意味着某些consumer将无法得到消息。
4、在一个consumer多个线程的情况下,一个线程相当于一个消费者。
例如:partition为3,一个consumer起了3个线程消费另一个后来的consumer就无法消费。
一个partition中的消息只会被group中的一个consumer消费;
每个group中consumer消息消费互相独立;

消费的顺序问题:

在同一个partiton中消费消息是顺序的。
例如:一个消费者在一个partition中的消费顺序和产生的顺序一致。
但是如果一个消费者消费多个partiton的话只能保证消费的顺序在一个partition是顺序的。
比如:一个生产者生产数据:1,2,3,4,5,6
其中1、3、5落在p1,2、4、6落在p2.则一个消费者消费的话顺序不能保证总的顺序是1,2,3,4,5,6。。。也不是消费完p1再消费p2.

问题一:为什么要分组?

(1)增加组内消费者,不会导致数据生产过快,消费不了的问题。
举个例子:一份数据用户的登陆行为。。。
两个部门:实时统计部门、财务部门。2个消费者组。
每个部门内想提高消费效率怎么做?请增加消费者!!!

八、topic、partition、message

1、partition里面的存储层面是append log文件。新消息都会被直接追加到log文件的尾部,每条消息在log文件中的位置称为offset(偏移量)。
2、每条Message包含了以下三个属性:
offset 对应类型:long
MessageSize 对应类型:int32
data 是message的具体内容。
3、每条Message由offset来表示它在这个partition中的偏移量,这个offset不是该Message在partition数据文件中的实际存储位置,而是逻辑上一个值,它唯一确定了partition中的一条Message。因此,可以认为offset是partition中Message的id。
4、越多的partitions意味着可以容纳更多的consumer,有效提升并发消费的能力。
总之:业务区分增加topic、数据量大增加partition。
5、Message的分发
这里写图片描述

九、kafka集群

部署kafka集群:master、slave1、slave2
zk和kafka的存储路径不要和单节点的一致。如果存储路径一致,最好把原来的topic等数据都删掉,防止数据不一致问题。!!!

1、启动zookeeper(可以使用奇数个节点的zk集群)。

注意zk集群,不是简单的把三个节点自带的zk启动!!!!
判断zk集群的方法:
在一个zk的主机上创建一个zk的文件节点在其它机器上查询。
或者/opt/zookeeper/bin/zkServer.sh status

2、修改配置文件

在master节点的配置/opt/kafka/config/server.properties broker.id=0
修改配置log.dirs=/opt/kafka/kafka-logs
zookeeper.connect=master:2181,slave1:2181,slave2:2181

3、同步其它节点:

scp -r /opt/kafka/ root@slave1:/opt/
scp -r /opt/kafka/ root@slave2:/opt/
修改
slave1的/opt/kafka/config/server.properties broker.id=1
slave2/opt/kafka/config/server.properties broker.id=2

4、启动所有server

/opt/kafka/bin/kafka-server-start.sh /opt/kafka/config/server.properties >>/opt/logs/kafka-server.log 2>&1 &

十、kafka的容错和扩展机制

当kafka集群中的一个broker挂掉(fails),则zk会选择新的broker提供服务。
kill -9 杀掉master的进程测试:
杀掉后如果要存在master机器上只是个警告并且会立马转到其它地方去。

十一、kafka开发

1、java操作kafka

添加maven依赖:

org.apache.kafka
kafka_2.11
0.8.2.2

配置hosts文件 做zookeeper服务器的映射配置。[如果我们的hosts中没有做hosts的配置kafka经多次尝试连接不上就会报错误]
生产者配置文件参数
http://kafka.apache.org/082/documentation.html#producerconfigs
消费者配置文件参数
http://kafka.apache.org/082/documentation.html#consumerconfigs

2、java操作kafka-producer

(1)将生产者的配置文件放在程序的资源目录里。
(2)java加载配置文件生产数据

//加载和配置文件
Properties prop=new Properties();
prop.load(ProducerTest.class.getClassLoader().getResourceAsStream("producer.properties"));
// System.out.println(prop.getProperty("metadata.broker.list"));
Producer<String,String> stringProducer=new Producer<String, String>(new ProducerConfig(prop));
//key是作为分区用的
stringProducer.send(new KeyedMessage<String, String>("hello","first"));
stringProducer.close();

3、java操作kafka-partitioner

public class SimplePartitioner implements Partitioner {
    private VerifiableProperties properties;
    public SimplePartitioner(VerifiableProperties properties) {
        this.properties=properties;
    }
    public int partition(Object key, int numPartitions) {
        String key_str= (String) key;
        System.out.println(key_str);
        System.out.println(numPartitions);
        if (key_str.length()<10){
            return 0;
        }else{
            return 1;
        }
    }
}

VerifiableProperties 里面是producer的配置信息。注意一个坑!!!
配置:partitioner.class=com.zenith.kafka.SimplePartitioner
partition测试:
01:key=”keykeykeykeykeykeykey” value:”valuesnew” 消费者打印结果:partition:1 offset:5 message:valuenew
01:key=”key” value:”value” 消费者打印结果:partition:0 offset:1 message:value

4、java操作kafka-consumer

(1)将消费者的配置文件放在程序的资源目录里。
(2)java加载配置文件消费数据
offset消费后自动同步功能auto.commit.enable = true、auto.commit.interval.ms = 1000

//加载和配置文件
Properties prop=new Properties();
prop.load(ProducerTest.class.getClassLoader().getResourceAsStream("consumer.properties"));
//创建连接
ConsumerConnector connector= Consumer.createJavaConsumerConnector(new ConsumerConfig(prop));
Map<String,Integer> topicCountMap=new HashMap<String,Integer>();
//消费者线程数
Integer consumerNum=2;
String topic="hello";
topicCountMap.put(topic,consumerNum);
Map<String, List<KafkaStream<byte[], byte[]>>> topicMessageStreams
        =connector.createMessageStreams(topicCountMap);
List<KafkaStream<byte[], byte[]>> consumers= topicMessageStreams.get(topic);
ExecutorService threadPool= Executors.newFixedThreadPool(consumerNum);
for(KafkaStream<byte[], byte[]> consumer: consumers){
    threadPool.execute(new MessageRunner(consumer));
}
static class MessageRunner implements Runnable{
    private KafkaStream<byte[], byte[]> consumer;
    MessageRunner(KafkaStream<byte[], byte[]> consumer) {
        this.consumer= consumer;
    }
    public void run(){
        ConsumerIterator<byte[], byte[]> it = consumer.iterator();
        while(it.hasNext()){
            MessageAndMetadata<byte[],byte[]> item = it.next();
            System.out.println(String.format("thread:%s   partition:%s    offset:%s   message:%s",Thread.currentThread().getName(),item.partition(),item.offset(),new String(item.message())));
        }
    }
}

测试:当consuemr数大于partition数目时的测试情况。结果是多于partition的消费者未消费。

十二、kafka分布式协调

1、kafka分布式协调-broker

分布式zk主要体现在Producer,Broker,Consumer在zookeeper上的协调;
Broker在zookeeper中保存为一个节点,每个节点会保存对应broker的IP以及端口等信息。
Broker注册信息:/brokers/ids/[0…N]
ls /brokers/ids :[0, 1, 2]
get /brokers/ids/0
{“jmx_port”:-1,”timestamp”:”1451008496749”,”endpoints”:[“PLAINTEXT://master:9092”],”host”:”master”,”version”:2,”port”:9092}

2、kafka分布式协调-topic

一个topic会被分成多个partition并被分到多个broker上,partition的信息以及broker的分布情况都保存在zookeeper中。
topic创建的时候已经确定了partitions和brokers
(1)topic注册信息:/brokers/topics/[topic] :存储某个topic的partitions所有分配信息
ls /brokers/topics:[hello, world]
get /brokers/topics/hello: {“version”:1,”partitions”:{“1”:[0],”0”:[0]}}
(2)partition状态信息:/brokers/topics/[topic]/partitions/[partitionId]/state
ls /brokers/topics/hello/partitions:[0, 1]
get /brokers/topics/hello/partitions/0/state: {“controller_epoch”:3,”leader”:0,”version”:1,”leader_epoch”:1,”isr”:[0]}

3、kafka分布式协调-consumer

消费者以及消费者组的信息topic、partition、offset也存在zookeeper中。
(1)consumers节点下面为sonsumer组。
s /consumers:[console-consumer-96356, console-consumer-61919]
(2)组内的每个consumer都有一个唯一的ID(consumerId可以通过配置文件指定,也可以由系统生成),此id用来标记消费者信息:/consumers/[groupId]/ids/[consumerIdString]
ls /consumers/console-consumer-61919/ids :[console-consumer-61919_master-1451011792045-d7fdc6a5] 消费者在运行才会显示。
get /consumers/console-consumer-61919/ids/console-consumer-61919_master-1451011792045-d7fdc6a5:{“version”:1,”subscription”:{“hello”:1},”pattern”:”white_list”,”timestamp”:”1451011792113”}
(3)一个topic中的一个partition只有一个消费者消费:消费者在运行才会显示。
/consumers/[groupId]/owners/[topic]/[partitionId] -> consumerIdString + threadId索引编号
ls /consumers/console-consumer-61919/owners:[hello]
get /consumers/console-consumer-61919/owners/hello/0:console-consumer-61919_master-1451011792045-d7fdc6a5-0
(4)一个topic中的一个partition中消费的offset记录信息:/consumers/[groupId]/offsets/[topic]/[partitionId] -> long (offset)
ls /consumers/console-consumer-61919/offsets:[hello]
get /consumers/console-consumer-61919/offsets/hello/0:1

十三、存储策略

在kafka中每个topic包含1到多个partition,每个partition存储一部分Message。每条Message包含了以下三个属性,其中有一个是offset。问题:
offset相当于partition中这个message的唯一ID,那么通过id高效的找到message?

两大法宝:分段、索引

具体存储方式:
1、每个partition有多个segment【片段】组成,每个segment中存储多条消息,
2、每个partition在内存中对应一个index,记录每个segment中的第一条消息偏移。
具体的流程:
发布者发到某个topic的 消息会被分布到多个partition上(随机或根据用户指定的函数进行分布),broker收到发布消息往对应part的最后一个segment上添加 该消息,segment达到一定的大小后将不会再往该segment写数据,broker会创建新的segment。
这里写图片描述

存储策略-高效查询

1、每个片段一个文件并且此文件以该片段中最小的offset命名,这样在查找指定offset的Message的时候,用二分查找就可以定位到该Message在哪个段中。
2、为每个分段后的数据文件建立了索引文件,文件名与数据文件的名字是一样的,只是文件扩展名为.index,索引文件里存储的分别为相对offset和此message在文件中的position。
3、index文件中并没有为数据文件中的每条Message建立索引,而是采用了稀疏存储的方式,每隔一定字节的数据建立一条索引。这样避免了索引文件占用过多的空间,从而可以将索引文件保留在内存中。
这里写图片描述

十四、kafka的配置文件

kafka中的配置文件参数主要分为以下三类:
broker配置文件参数
http://kafka.apache.org/082/documentation.html#brokerconfigs
其中有一部分是topic级别的:即可以被topic创建时覆盖。
可以参看:
http://kafka.apache.org/082/documentation.html#topic-config
或者看注释。
生产者配置文件参数
http://kafka.apache.org/082/documentation.html#producerconfigs
消费者配置文件参数
http://kafka.apache.org/082/documentation.html#consumerconfigs
生产环境中根据业务场景来设置参数
主要关注点:生产的方式、存储的策略

十五、Kafka在生产环境中的性能评估

根据自己的集群的配置和业务实际情况来测试性能。
https://cwiki.apache.org/confluence/display/KAFKA/Performance+testing
生产能力:多测试几次求平均。
在kafka的安装目录的bin里有性能的评估工具bin/kafka-producer-perf-test.sh
测试:
bin/kafka-producer-perf-test.sh –broker-list master:9092,slave1:9092,slave2:9092 –topics hello –messages 1000000 –threads 3
2016-01-27 13:43:43:652, 2016-01-27 13:44:01:559, 0, 100, 200, 95.37, 5.3257, 999999, 55844.0275
消费能力:
kafka-consumer-perf-test.sh 多测试几次求平均。
测试:
bin/kafka-consumer-perf-test.sh –zookeeper master:2181,slave1:2181,slave2:2181 –topic hello –messages 1000000 –threads 2
2016-01-27 13:44:55:915, 2016-01-27 13:44:58:350, 1048576, 190.6978, -74.3461, 2000000, -779727.0955

十六、kafka的应用

1、作为消息队列的应用在传统的业务中使用高吞吐、分布式、使得处理大量业务内容轻松自如。
2、作为互联网行业的日志行为实时分析,比如:实时统计用户浏览页面、搜索及其他行为,结合实时处理框架使用实现实时监控,或放到 hadoop/离线数据仓库里处理。
3、作为一种为外部的持久性日志的分布式系统提供服务。主要利用节点间备份数据,文件存储、日志压缩等功能。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值