kafka优势
- 吞吐量高、性能好
- 伸缩性好,支持在线水平扩展
- 容错性(同一份消息存储三份并持久化到硬盘上)和可靠性(消息代理服务通常一组多备)
- 与大数据生态紧密结合
Topic主题
kafka消息存储在Topic主题中,Topic类似数据库中的表,通常相同类型消息存储在同一Topic中,Topic是半结构化数据,也可以将不同类型消息存储在同一Topic中
Partition分区
Topic可以包含多个Partition分区,kafka是分布式消息系统,kafka将Topic拆分成多个Partition,不同的Partition可以存储在不同的服务器上,实现了kafka的扩展性;Partition是一个线性增长的不可变的提交日志,消息提交到Partition后便不可变更
offset偏移量
kafka为每条消息分配一个offset,offset记录每条消息的位置,kafka可以通过offset对消息进行提取,offset在每个分区中是唯一不可重复递增的,不同分区之间offset可以重复
Record消息记录
kafka中的Record消息以key-value键值对格式进行存储,如果不指定key,kafka以轮询的方式将消息写入不同的Partition中;如果指定了key,相同key的消息会被写入同一个分区中,这样就保证了具有相同key的消息根据顺序写入同一Partition中
kafka集群
kafka根据副本机制保证数据的可靠性,通过设置replication-factor参数调整kafka副本数量,设置为3即包含主分区在内一共三个副本;kafka选择一个副本作为leader(主分区),所有数据的写入与读取都是通过leader,其它两个副本称为follower,follower只负责从leader中复制数据,保持数据的一致,kafka会监控follower同步的状态,kafka会维护一个ISR的集合,ISR就是正在同步的副本集,如果某个副本落后的比较多,kafka会将其从ISR去除,直到恢复正常并重新加入
Broker消息代理
kafka集群由Broker消息代理组成,Broker负责消息的读写请求并且将数据写入到磁盘中,每个服务器上都启动一个Broker实例,一台服务器就是一个Broker;每个Broker都会存储多个不同Partition的副本。不同Partition的副本会尽量均衡地分布在所有Broker上,而同一个Partition的不同副本则会被分配到不同的Broker上
kafka环境安装
- zookeeper配置文件: zookeeper.properties
- kafka Broker配置文件: server.properties
server.properties必要配置项
- broker.id: 消息代理ID
- log.dirs: 日志目录
- zookeeper.connect: zookeeper连接
- listeners: 指定broker启动时的本机监听端口,给服务器使用
- advertised.listeners: 对外发布的访问IP和端口,注册到zookeeper中,给客户端使用
kafka消息模型
分区
- 分区是最小的并行单位
- 一个消费者可以消费多个分区
- 一个分区可以被多个消费者组里的消费者消费
- 一个分区不能同时被同一个消费者组里的多个消费者消费
发布-订阅模式(单对多)
每个消费者都属于不同的消费者组
点对点模式(单对单)
所有消费者都属于同一个消费者组
分区与消费顺序
- 同一个生产者发送到同一个分区的消息,先发送的offset比后发送的offset小
- 同一个生产者发送到不同分区的消息,消息顺序无法保证
- 消费者按照消息在分区里的存放顺序进行消费
- kafka纸包装分区内消息的顺序,不能保证分区间的消息顺序
消息传递语义
消息传递语义需要生产者和消费者共同来保证 生产者发送给Broker消息后,Broker会返回一个消息,通知生产者收到消息
最多一次——消息可能会丢失,永远不重复发送
- 生产者发送给Broker消息后,不会等待Broker的返回消息
- 消费者先提交消费位置,后读取消息
最少一次——消息不会丢失,但是可能会重复
- 生产者发送给Broker消息后,等待Broker的返回消息,如果没有收到返回消息,则重新发送
- 消费者先读取消息,后提交消费位置
精确一次——保证消息被传递到服务端且在服务端不重复
生产者API
- 异步发送: 使用send()函数,生产者创建缓冲区(不同分区在缓冲区中有不同的batch.size),消息首先发送到缓冲区,消息发送后立即返回并发送下一条(不等待消息成功发送到Broker中),后台IO线程负责将缓冲区内的消息发送到Broker
- 同步发送: 获取send()函数返回的结果result,通过调用result.get()对发送消息进行阻塞,消息发送成功后再发送下一条消息
- 批量发送: 设置batch.size参数(每批消息最大大小)、linge.ms(延迟时间),当消息满足二者任意一个则进行批量发送
- acks参数: 消息发送到服务端后,会向生产者发送回执消息
- acks=0: 生产者不会等待服务器端的任何回执消息,当消息被送入缓冲区则认为发送成功
- acks=1: 表示已经被服务端的leader存入本地,但是不保证被follower成功同步
- acks=1/all: 表示消息已经被服务端的follower同步成功
- retries参数: 当消息发送失败重试次数
- 最多一次: Acks=0或Acks=1
- 至少一次: Acks=-1或all,并且retries>0
消费者API
kafka中有一个主题_consumer_offsets用来保存消费者消费到哪个主题、哪个分区哪个消费位置,利于快速回复
- enable.auto.commit: 是否字段提交
- auto.commit.interval.ms: 每隔多久自动提交
- consumer.poll(): 拉取消息,异步,立即返回
- consumer.commitSync(): 批量提交消息offset,同步,阻塞直到offset提交成功
事务消息
- 事务成功提交后会标记为成功
- lsolation_level: 隔离级别
- read_uncommitted: 事务没有被标记成功也可以读取出来
- read_committed: 事务只有被标记成功才可以被读取出来