Hadoop学习日记(十六)
2019.07.08、07.09
主题:Kafka
学习过程主要参考段海涛大数据p61
注:因项目需要,故提前学习视频中Kafka相关内容,Hadoop HA机制以及Hive、HBase、Storm后续再补充。
1. Kafka要点
1. Kafka是一个分布式的消息缓存系统;
2. Kafka集群中的服务器都叫做broker;
3. Kafka有两类客户端,一类叫作producer(消息生产者),一类叫作consumer(消息消费者),客户端和broker之间采用TCP协议连接;
4. Kafka中不同业务系统的消息可以通过topic进行区分,而且每一个消息topic都会被分区(partition),以分担消息读写的负载;
5. 每一个分区都可以由多个副本,以防止数据的丢失;
6. 某一给分区中的数据如果需要更新,都必须通过该分区所有副本中的leader来更新;
7. 消费者可以分组,例如两个消费者组A和B,共同消费一个topic:order_info,A和B所消费的消息不会重复,比如order_info中有100个消息,每一个消息有一个id,编号从0-99,那么如果A组消费0-49,B组就消费50-99;
8. 消费者在消费某个具体topic中的消息时,可以指定其实偏移量。
2.Kafka单节点测试
Kafka主目录的bin目录下提供了一些脚本可供单节点测试kafka(Kafka单节点测试),但是在输入“bin
/zookeeper-server-start
.sh config
/zookeeper
.properties
”时,总是提示"Classpath is empty. Please build the project first e.g. by running ......"。刚开始受这个讨论的误导,正确的解决方案在另一个讨论里。刚开始下载的Kafka是source版本的,应该是没有经过编译的,后来下载了binary版本的是编译好的,如果编译source版本的应该也是可行的。
Kafka具体的单节点测试流程见官方文档Kafka单节点测试。
3.Kafka集群配置
集群配置主要在config/server.propertities中修改broker id以及zookeeper.connect两项。
三台虚拟机,broker id依次为0,1,2.
zookeeper.connect=slave1:2181,slave2:2181,slave3:2181
以上两项参数配置好之后,在每个节点上都执行bin
/kafka-server-start
.sh config
/server.properties
即可启动有3个节点的Kafka集群。
需要注意的是,对于每一个topic的每一个partition都会有不同的leader。
4. Kafka常用命令行操作
首先要启动zookeeper集群:zkServer.sh start (每个zookeeper节点都要执行)
然后启动Kafka集群:bin
/kafka-server-start
.sh config
/server
.properties (每个节点都要执行)
创建Topic:bin
/kafka-topics
.sh --create --bootstrap-server localhost:9092 --replication-factor 3 --partitions 1 --topic my-replicated-topic
查看Topic信息:bin
/kafka-topics
.sh --describe --bootstrap-server localhost:9092 --topic my-replicated-topic
删除Topic:bin/kafka-topics.sh --delete --bootstrap-server localhost:9092 --topic my-replicated-topic
创建生产者:bin
/kafka-console-producer
.sh --broker-list localhost:9092 --topic my-replicated-topic
创建消费者:bin
/kafka-console-consumer.sh --bootstrap-server localhost:9092 --from-beginning --topic my-replicated-topic (注意是否有--from-beginning)
列出所有Topic:bin/kafka-topics.sh --list --bootstrap-server 220.113.20.21:9092
5. Kafka与zookeeper的关系
Kafka使用zookeeper管理元数据,例如:记录topic名称、分区以及其副本分配等信息,用户权限控制的相关数据等。Kafka还会再zookeeper的某些上添加相应的监听器,用于监听集群的状态,例如:集群中所有broker通过zookeeper监听controller leader的状态。可以通过Kafka自带的脚本修改zookeeper触发相应操作,例如:优先副本选举。
6. Java客户端编程
参考了视频段海涛大数据p62、p63,需要注意的是本次测试用的Kafka版本是2.3.0,视频中的版本较老,编程接口已经不适用。
下面将代码贴出:
首先是producer:
import java.util.Properties;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.Producer;
import org.apache.kafka.clients.producer.ProducerRecord;
public class ProducerDemo {
public static void main(String[] args) throws InterruptedException {
Properties props=new Properties();
props.put("bootstrap.servers","slave1:9092");
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
Producer<String, String> producer =new KafkaProducer<>(props);
for(int i=1;i<=20;++i)
{
Thread.sleep(500);
producer.send(new ProducerRecord<String, String>("mygirls", "i said i love you for"+i+"times"));
}
}
}
接下来是consumer:
import java.util.Arrays;
import java.util.Properties;
import org.apache.kafka.clients.consumer.Consumer;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.ConsumerRecord;
public class ConsumerDemo {
public static void main(String[] args)
{
Properties props=new Properties();
props.put("bootstrap.servers","slave1:9092");
props.setProperty("group.id", "test");
props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
Consumer<String, String> consumer =new KafkaConsumer<>(props);
consumer.subscribe(Arrays.asList("mygirls","myboys"));
while(true) {
ConsumerRecords<String, String> records = consumer.poll(100);
for(ConsumerRecord<String, String> record : records)
{
System.out.println(record.topic()+"--"+record.value());
}
}
}
}
带回调函数的生产者:
producer.send(new ProducerRecord<String, String>("routepoint", str),new Callback() {
@Override
public void onCompletion(RecordMetadata arg0, Exception arg1) {
// TODO Auto-generated method stub
if(arg1==null) {
System.out.println(arg0);
}
}
});