kafka入门

一、什么是kafka?
  
Kafka是一种分布式,基于发布/订阅的消息系统。  
高吞吐量:每秒可处理几十万条记录  
分布式:支持热扩展  
持久化:消息持久化到磁盘
容错:副本容错  
高并发:客户端同时高并发读写
  
使用背景:  
峰值处理能力
统一接口服务
解耦
  
消息系统介绍:  
一个消息系统负责将数据从一个应用传递到另外一个应用,应用只需关注于数据,无需关注数据在两个或多个应用间是如何传递的。
分布式消息传递基于可靠的消息队列,在客户端应用和消息系统之间异步传递消息。  
有两种主要的消息传递模式:点对点传递模式、发布-订阅模式。  
大部分的消息系统选用发布-订阅模式。Kafka就是一种发布-订阅模式。  
  
点对点模式:  
在点对点消息系统中,消息持久化到一个队列中。此时,将有一个或多个消费者消费队列中的数据。  
但是一条消息只能被消费一次。当一个消费者消费了队列中的某条数据之后,该条数据则从消息队列中删除。  
该模式即使有多个消费者同时消费数据,也能保证数据处理的顺序。
 
发布-订阅模式:  
在发布-订阅消息系统中,消息被持久化到一个topic中。与点对点消息系统不同的是,  
消费者可以订阅一个或多个topic,消费者可以消费该topic中所有的数据,同一条数据可以被多个消费者消费,  
数据被消费后不会立马删除。在发布-订阅消息系统中,消息的生产者称为发布者,消费者称为订阅者.
发布者发送到topic的消息,只有订阅了topic的订阅者才会收到消息。  
  
二、kafka-基本概念  
生产者(Producer):负责发布消息到Kafka broker  
消费者(Consumer):从消息队列中请求消息的客户端应用程序
代理(Borker): kafka集群包含一个或多个服务器,这种服务器被称为broker,准确来讲是一个kafka的服务进程。  
生产者推送消息到broker上,消费者可以订阅一个或多个主题(topic),并从Broker拉数据,从而消费这些已发布的消息。
  
Topic  
在实际业务中,通常一个业务对应一个topic  
kafka使用topic来组织消息  
一个topic消息可以包含多个partition,分布在不同的broker上  
一个partition可以指定多个副本  
生产消息、订阅消息都需要指定topic  
  
Partition(分区)  
一个topic按照多个分区组织消息,每个分区都是一个顺序的,不可变的消息队列,且持续在队列末尾添加,而不是随机读写。
producer生产的消息按照一定的算法分配到不同的分区中,添加到分区末尾。所有的partition当中的数据全部合并起来,就是一个topic当中的所有的数据。
一个broker服务下,可以创建多个分区,broker数与分区数没有关系;在kafka中,每一个分区会有一个编号:编号从0开始。
每一个分区内的数据是有序的,但全局的数据不能保证是有序的。(有序是指生产什么样顺序,消费时也是什么样的顺序)
增加partition数量,可以提升读写并发  
一个partition对应的物理文件:log文件和index文件,每个log文件又被称为segment,索引文件分为offset索引文件和时间戳索引文件
一个partition可以指定多个副本,但是只有一个副本是leader,partition的读写只能通过leader。


Message(消息)
一个消息对应kafka的一个offset
消息只会追加到segment上面,不能修改删除
segment会定期删除(配置项log.retention.{ms,minutes,hours}和log.retention.bytes)
segment默认配置保留时间为7天

Message物理结构
8 bytes offset(表示消息在partition中第几条)
4 bytes message size(消息的大小)
1 byte magic size(kafka程序服务协议号)
4 bytes crc(crc32校验)
其他(压缩、编码,key等信息)
payload(实际消息的数据)

segment/index文件(log文件)命名规范:文件中第一条信息的offset -1
index 文件包括序号和地址,序号就是message在日志文件中的相对偏移量(即第几条)
地址是指文件中的偏移字节。
OffsetIndex是稀疏索引,不会存储所有的消息相对offset和position

消息检索过程:
以这个partition目录下面,00000000001560140916为例
定位offset 为1560140921的message
1. 定位到具体的segment日志文件
由于log日志文件的文件名是这个文件中第一条消息的offset-1. 因此可以根据offset定位到这个消息所在日志文件:00000000001560140916.log
2. 计算查找的offset在日志文件的相对偏移量
segment文件中第一条消息的offset = 1560140917
计算message相对偏移量:需要定位的offset - segment文件中第一条消息的offset + 1 = 1560140921 - 1560140917 + 1 = 5
查找index索引文件, 可以定位到该消息在日志文件中的偏移字节为456. 综上, 直接读取文件夹00000000001560140916.log中偏移456字节的数据即可。
1560140922 -1560140917 + 1 = 6
如果查找的offset在日志文件的相对偏移量在index索引文件不存在, 可根据其在index索引文件最接近的上限
偏移量, 往下顺序查找


Offset(偏移量)
Offset是一个有序的序列
一个消息对应kafka的一个offset
offset的最大长度为8字节

Consumer Group(消费组)
消费者组由一个或者多个消费者组成,同一个组中的消费者对于同一条消息只消费一次。
每个消费者都属于某个消费者组,如果不指定,那么所有的消费者都属于默认的组。
每个消费者组都有一个ID,即group ID。组内的所有消费者协调在一起来消费一个订阅主题(topic)的所有分区(partition)。
当然,每个分区只能由同一个消费组内的一个消费者(consumer)来消费,可以由不同的消费组来消费。
某一个主题下的分区数,对于消费者来说,应该小于等于该主题下的分区数。

partition replicas(分区副本)
副本数(replication-factor): 控制消息保存在几个broker(服务器)上,一般情况下副本数等于broker的个数。
一个broker服务下,不可以创建多个副本因子。创建主题时,副本因子应该小于等于可用的broker数。
副本因子操作以分区为单位的。每个分区都有各自的主副本和从副本;
主副本叫做leader,从副本叫做 follower。follower通过拉的方式从leader同步数据。
消费者和生产者都是从leader读写数据,不与follower交互。

消费模型
High Level Consumer API
不需要自己管理offset
默认实现最少一次消息传递语义(At least once)
consumer数量大于partition数量,浪费
consumer数量小于partition数量,会导致一个consumer对应多个partition
最好partition的数量是consumer数目的整数倍

Low Level Consumer API(Simple Consumer API)
需要自己管理offset
可以实现各种消息传递语义
生产上常用

三、运行架构
1.如何消费消息?
producer选择一个topic,生产消息,消息会通过分配策略append到某个partition末尾。
consumer选择一个topic,通过id指定从哪个位置开始消费消息。消费完成之后保留id,下次可以从这个位置开始继续消费,也可以从其他任意位置开始消费。
上面的id在kafka中称为offset,这种组织和处理策略提供了如下好处:
1.1 消费者可以根据需求,灵活指定offset消费
1.2 保证了消息不变性,为并发消费提供了线程安全的保证。每个consumer都保留自己的offset,互相之间不干扰,不存在线程安全问题。
1.3 消息访问的并行高效性。每个topic中的消息被组织成多个partition,partition均匀分配到集群server中。生产、消费消息的时候,
    会被路由到指定partition,减少竞争,增加了程序的并行能力。
1.4 增加消息系统的可伸缩性。每个topic中保留的消息可能非常庞大,通过partition将消息切分成多个子消息,并通过负责均衡策略将partition分配到不同server。
    这样当机器负载满的时候,通过扩容可以将消息重新均匀分配。
1.5 保证消息可靠性。消息消费完成之后不会删除,可以通过重置offset重新消费,保证了消息不会丢失。
1.6 灵活的持久化策略。可以通过指定时间段(如最近一天)来保存消息,节省broker存储空间。
1.7 备份高可用性。消息以partition为单位分配到多个server,并以partition为单位进行备份。
    备份策略为:1个leader和N个followers,leader接受读写请求,followers被动复制leader。leader和followers
    会在集群中打散,保证partition高可用。

2.为什么说是分布式和冗余备份的?
分区被分布到集群中的各个服务器中,每个服务器处理它所拥有的分区。根据配置,每个分区还可以复制到其他服务器作为备份容错。
每个分区拥有一个leader,有一个或者多个follower(冗余备份的)。一个broker可以是一个分区的leader,同时也可以是别的分区的follwer,
避免了所有的请求只让一个或者几个服务器处理,负载均衡。
某个broker如果是一个分区的leader,那么它处理这个分区上的所有读写请求,而follwer分区被动的复制数据。
如果leader宕机,则follwer就可以被推举为leader。

3.为什么说是持久性的:
kafka使用文件存储消息,并且会保存所有消息直到它过期,无论是否消费。

四、kafka安装及使用
kafka_2.11-2.1.0.tgz
zookeeper-3.4.5.tar.gz
1.kafka依赖于zookeeper,先安装zookeeper

#1.1 解压文件
tar -zxvf zookeeper-3.4.5.tar.gz
#1.2 移动文件到合适的位置
mv zookeeper-3.4.5 /usr/local/zk
#1.3 修改配置文件
cd conf
cp zoo_sample.cfg zoo.cfg
vim zoo.cfg
#dataDir是存放snapshot,zookeeper的datatree在内存中某一时刻的影像
dataDir=/usr/local/zk/data
:wq
#启动zookeeper
cd bin
./zkServer.sh start
2.安装jdk8
#解压文件
tar -zxvf jdk-8ul8l-linux-x64.gz
#移动文件
mv jdk1.8.0_181 /usr/local/jdk
#配置环境变量
vim /ect/profile
export JAVA_HOME=/usr/local/jdk
export ZK_HOME=/usr/local/zk
export PATH=.:$PATH:$JAVA_HOME/bin:$ZK_HOME/bin
:wq
#生效配置文件
source /etc/profile
#查看当前服务器进程
jps
#查看zookeeper的状态
zkServer.sh status
3.安装kafka
#解压文件
tar -zxvf kafka_2.11-2.0.1.tgz
#移动文件
mv kafka_2.11-2.1.0 /usr/local/kafka
#修改配置文件
cd /usr/local/kafka
cd config
vim server.properties
#修改日志存放目录
log.dirs=/usr/local/kafka/data/kafka-logs
#zookeeper的链接地址(可默认不变)
zookeeper.connect=localhost:2181
4.修改主机域名
vim /etc/hostname
master
:wq
5.修改host域名映射(hosts文件)
su root
vim /etc/hosts
192.168.159.131 master

6.启动kafka
./kafka-server-start.sh ../config/server.properties
#查看kafka是否正常启动
jps

7.关闭防火墙
systemctl stop firewalld.service

8、测试kafka
1.创建TOPIC test1, 副本数1 分区数1
./kafka-topics.sh --zookeeper 127.0.0.1:2181 --topic test1 --replication-factor 1 --partitions 1 --create

2.生产消息
./kafka-console-producer.sh --broker-list 127.0.0.1:9092 --topic test1
2.消费消息
./kafka-console-consumer.sh -bootstrap-server 127.0.0.1:9092 --topic test1

9、SpringBoot 整合kafka

整合时遇到错误:
org.apache.kafka.common.errors.TimeoutException: Expiring 1 record(s) for test1-0: 30002 ms has passed since batch creation plus linger time

解决方案:(配置hosts)


五、kafka发送消息示例代码
public static void main(String[] args) {
        String mytopic = "mytest1";
        Properties props = new Properties();
        props.put("serializer.class","kafka.serializer.StringEncoder");
        props.put("metadata.broker.list","192.168.50.104:9092");
        props.put("request.required.acks","1");
        props.put("partitioner.class","kafka.producer.DefaultPartitioner");
        Producer<String,String> producer = new Producer<String,String>(new ProducerConfig(props));
        for(int index=0; index <88; index++){
            producer.send(new KeyedMessage<String,String>(mytopic,index+"", UUID.randomUUID()));
        }
}

request.required.acks:用于校验broker是否正确接收到kafka的消息.
参数值共有三个0,1,-1,为零代表不等待broker返回确认消息,无阻塞
1.只需要partition的leader保存成功即返回生产者,无需等待副本是否保存成功
-1,需要partition的leader以及follower副本均保存成功才返回消息

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值