kafka的简介和入门实践
一、kafka简介
1.简介
Kafka是最初由Linkedin公司开发,是一个分布式、支持分区的(partition)、多副本的(replica),基于zookeeper协调的分布式消息系统,它的最大的特性就是可以实时的处理大量数据以满足各种需求场景:比如基于hadoop的批处理系统、低延迟的实时系统、storm/Spark流式处理引擎,web/nginx日志、访问日志,消息服务等等,用scala语言编写,Linkedin于2010年贡献给了Apache基金会并成为顶级开源 项目。
2.kafka基础组成
Broker:Broker是kafka实例,每个服务器上有一个或多个kafka的实例,我们姑且认为每个broker对应一台服务器。每个kafka集群内的broker都有一个不重复的编号,如图中的broker-0、broker-1等……
Topic:消息的主题,可以理解为消息的分类,kafka的数据就保存在topic。在每个broker上都可以创建多个topic。
Partition:Topic的分区,每个topic可以有多个分区,分区的作用是做负载,提高kafka的吞吐量。同一个topic在不同的分区的数据是不重复的,partition的表现形式就是一个一个的文件夹!
producer:消息生产者,发布消息到kafka集群的终端或服务。
consumer:消费者,从kafka集群中消费消息的终端或服务。
consumer group:hig-level consumer api中,每个consumeer都属于一个consumer group,每条消息只能被consumer group 中的一个consumer消费,但可以被多个consumer group 消费
replica:partition的副本,保障partition的高可用
leader:replica中的一个角色,producer和consumer只跟leader交互
follower:replica中的一个角色,从leader中复制数据
3.Kafka的特性
- 高吞吐量、低延迟:kafka每秒可以处理几十万条消息,它的延迟最低只有几毫秒,每个topic可以分多个partition, consumer group 对partition进行consume操作。
- 可扩展性:kafka集群支持热扩展
- 持久性、可靠性:消息被持久化到本地磁盘,并且支持数据备份防止数据丢失
- 容错性:允许集群中节点失败(若副本数量为n,则允许n-1个节点失败)
- 高并发:支持数千个客户端同时读写
4.Kafka的使用场景
- 日志收集:一个公司可以用Kafka可以收集各种服务的log,通过kafka以统一接口服务的方式开放给各种consumer,例如hadoop、Hbase、Solr等。
- 消息系统:解耦和生产者和消费者、缓存消息等。
- 用户活动跟踪:Kafka经常被用来记录web用户或者app用户的各种活动,如浏览网页、搜索、点击等活动,这些活动信息被各个服务器发布到kafka的topic中,然后订阅者通过订阅这些topic来做实时的监控分析,或者装载到hadoop、数据仓库中做离线分析和挖掘。
- 运营指标:Kafka也经常用来记录运营监控数据。包括收集各种分布式应用的数据,生产各种操作的集中反馈,比如报警和报告。
- 流式处理:比如spark streaming和storm
- 事件源
二、kafka下载与安装启动
1.下载安装
cd要安装的文件夹下
wget http://mirror.bit.edu.cn/apache/kafka/2.1.0/kafka_2.12-2.1.0.tgz
解压
tar -xzvf kafka_2.12-2.1.0.tgz
2.配置与启动
以下是单机启动,如果配置多台可以参考:Zookeeper + Kafka 集群搭建
进入配置文件里
cd kafka_2.12-2.1.0/config/
vim server.properties
主要修改这几个属性
#当前机器在集群中的唯一标识,和zookeeper的myid性质一样
broker.id=0
advertised.listeners=PLAINTEXT://ip:9092
listeners=PLAINTEXT://ip:9092
#zookeeper地址和端口, Kafka支持内置的Zookeeper和引用外部的Zookeeper
zookeeper.connect=localhost:2181
advertised.listeners
保存后
cd kafka_2.12-2.1.0/
启动自带的zookeeper
bin/zookeeper-server-start.sh config/zookeeper.properties
启动kafka
bin/kafka-server-start.sh config/server.properties
三、springboot入门实践kafka实现消息队列
1.导入依赖,注意不需要版本,如果加入版本可能会跟springboot版本冲突报错
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
<!--<version>2.2.7.RELEASE</version>-->
</dependency>
2.application.properties配置
###########################################kafka about config #######################################################
spring.kafka.bootstrap-servers=localhost:9092
##########################producer about config##############################
spring.kafka.producer.acks=1
# 每次批量发送消息的数量
spring.kafka.producer.batch-size=16384
spring.kafka.producer.retries=0
spring.kafka.producer.buffer-memory=33554432
# 指定消息key和消息体的编解码方式
#spring.kafka.producer.key-serializer=org.apache.kafka.common.serialization.StringSerializer.class
#spring.kafka.producer.value-serializer=org.apache.kafka.common.serialization.StringSerializer.class
##########################consumer about config##############################
#是否自动提交
spring.kafka.consumer.enable-auto-commit=true
#消费组
spring.kafka.consumer.group-id=test_1
#连接超时时间
spring.kafka.consumer.session.timeout=20000
spring.kafka.consumer.auto-commit-interval=100
#实时生产,实时消费,不会从头开始消费
spring.kafka.consumer.auto.offset.reset=latest
#spring.kafka.consumer.key-deserializer=org.apache.kafka.common.serialization.StringDeserializer.class
#spring.kafka.consumer.value-deserializer=org.apache.kafka.common.serialization.StringDeserializer.class
生产者代码
/**
* @Author : wjx
* @date : 2020/4/21 19:45
* @description:
*/
@Component
public class KafkaSender {
@Autowired
private KafkaTemplate kafkaTemplate;
//发送消息方法
public void send() {
Message message = new Message();
message.setId(System.currentTimeMillis());
message.setMsg(UUID.randomUUID().toString());
message.setSendTime(new Date());
kafkaTemplate.send("test1", message.toString());
System.out.println("send-消息发送成功:"+ message.toString());
}
}
消费者代码
/**
* @Author : wjx
* @date : 2020/4/21 19:48
* @description:
*/
@Component
public class KafkaReceiver {
@KafkaListener(topics = {"test1"})
public void listen(ConsumerRecord<?, ?> record) {
Optional<?> kafkaMessage = Optional.ofNullable(record.value());
if (kafkaMessage.isPresent()) {
Object message = kafkaMessage.get();
System.out.println("----------------- record =" + record);
System.out.println("------------------ message =" + message);
}
}
}