Kafka具备的4大特性
- 吞吐量/延时(高性能)
- 大量使用操作系统页缓存,内存操作速度快且命中率高
- kafka不直接参与物理I/O操作,而是交由操作系统来完成
- 采用追加写入方式,摒弃了缓慢地磁盘随机读、写操作
- 使用sendfile的零拷贝几乎是加强网络间的数据传输效率
- 消息持久化(高可靠)
- 消息持久化的好处
- 解耦消息发送与消息消费
- 实现灵活的消息处理:指定offset消费
- kafka在实现持久化时会立即写入文件系统的持久化日志中,之后kafka服务器才会返回结果给客户端通知它们消息被成功写入,这样既实时保存数据,又减少了kafka程序对于内存的消耗,从而节省内存给页缓存使用,进一步提升性能
- 消息持久化的好处
- 负载均衡和故障转移(高可用性)
- 负载均衡:通过分区领导者选举机制来实现的,可以在集群的所有机器上以均等的机会分散各个partition的leader,从而整体实现了负载均衡
- 故障转移:使用会话机制,在kafka的broker启动后会以会话的形式注册到zookeeper服务器上(临时节点)。一旦该broker运转出现问题,此时kafka集群会选举出另外一台服务器来完全代替这台服务器继续提供服务
- 伸缩性(高可扩展性)
- kafka服务器的状态由zookeeper管理,扩展集群只需一步,启动新的kafka服务器即可
kafka的基本概念与术语
- 消息由很多字段组成,其中很多字段都是用于管理消息的元数据字段。kafka消息格式经历过3次变迁,分别有v0,v1,v2版本。目前大多数使用的是v1版本。
- 消息主要由消息头部、key和value组成
- 消息头部:包括消息的CRC码、消息版本号、属性、时间戳、key长度、value长度
- 消息key:对消息做partition时使用,决定消息被保存在topic下的哪个partition
- 消息体value:保存实际的消息数据
- 时间戳timestamp:消息发送的时间戳,用于流式处理及其他依赖时间的处理语义,如不指定取当前时间
- 消息的属性字段:kafka为该字段分配了一个字节,使用低3位保存消息的压缩类型。当前支持“0(无压缩)、1(GZIP)、2(Snappy)和3(LZ4)和4(zstd)
- kafka使用紧凑的二进制数组保存消息字段,比直接存Java对象更节省内存(类似的设计还有redis的数据结构)
- 消息头部:包括消息的CRC码、消息版本号、属性、时间戳、key长度、value长度
- topic和partition
- topic只是个逻辑概念,代表了一类消息,为了提高系统的吞吐量,每个topic有多个partition,而partition是有序消息队列,每个partition有自己专属的partition编号,从0开始,新写入的消息被追加在partition的尾部,每条消息都已唯一的序列号(偏移量offset)
- topic只是个逻辑概念,代表了一类消息,为了提高系统的吞吐量,每个topic有多个partition,而partition是有序消息队列,每个partition有自己专属的partition编号,从0开始,新写入的消息被追加在partition的尾部,每条消息都已唯一的序列号(偏移量offset)
- offset
- 消息在partition端的偏移量:最新一条消息的位移
- 消费者偏移量:表示当前topic对应的partition的消费的进度,小于等于partition中最新一条消息的偏移量
- 通过<topic,partition,offset>三元组,能找到唯一对应的那条消息
- replica:用来备份partition,实现高可靠,唯一的作用是防止数据丢失
- leader副本:对外响应客户端发来的消息写入和消息消费请求
- follower副本:不能提供给服务给客户端,被动向leader副本获取数据
kafka的参数
-
broker端参数,目录在config/server.properties文件
- broker.id 用来表示集群中的每个broker,默认-1.如果不指定,kafka会自动生成一个唯一值,这个数值需保证唯一
- log.dirs kafka 持久化消息的目录,可以设置多个目录,逗号分隔
- zookeeper.connect zookeeper的连接地址。如果zookeeper管理着多个kafka集群,zk01:2181,zk02:2181,zk03:2181/kafka_cluster1
- listeners broker监听器列表,格式[协议]://host:port,[[协议]]
- advertised.listeners 用于发布给client的监听器,提供给外网用户访问
- unclean.leader.election.enable 当ISR变空,是否允许存活的非ISR参与选举,默认为false;如果为true打开可以让kafka继续提供服务,但会造成消息丢失
- log.retention.{hours|minutes|ms} 控制消息数据的留存时间,同时设置时取值优先级ms>minutes>hours,默认留存时间是7天
- log.retention.bytes 控制消息日志在空间维度的留存策略,默认值-1表示永远不会根据消息日志文件大小来删除日志
- min.insync.replicas 指定broker端必须成功响应生产者消息发送的最少副本数,与producer端的acks参数配合使用。acks=all 或者-1 表示,也只有在ack=-1或者all时有意义。需要根据高可用和数据一致性的实际需求配置
- message.max.bytes控制broker能够接受的最大消息大小,默认977KB,不到1MB,需要根据实际情况进行配置
-
- retention.ms 每个topic可以设置自己的日志留存时间以覆盖全局默认值
- max.message.bytes 每个topic消息最大字节数,覆盖broker参数,
- retention.bytes topic级别的日志留存大小,覆盖全局参数log.retention.bytes
-
- acks 用于控制producer生产消息的持久性
- acks=0 完全不关心消息是否发送成功,适用允许消息丢失的场景
- ack=1(默认) producer发送消息后leader broker仅将消息写入本地日志,便发送响应结果给producer,无需等待ISR中其他副本写入该消息、
- ack=all或-1,发送消息时,leader broker不仅将消息写入本地日志,同时还会等待ISR中所有其他副本都成功写入他们自己的本地日志,才发送响应结果给producer
- linger.ms控制消息发送延时行为,默认0,无需关心batch是否填满
- batch.size默认16KB,控制发送消息时一批的大小。太大,容易给内存带来压力;太小,吞吐量会降低
- buffer.memory指定producer端用于缓存消息的缓冲区大小,单位字节,默认33554432,32MB
- compression.type设置producer段是否压缩消息,默认值是none,注意如果与broker设置的compression.type不一样,broker端在写入消息时也会使用对应的cpu资源对消息解压缩-重压缩。所以一般是(producer压缩,broker保持,consumer解压缩)
- max.request.size控制producer发送请求的大小,由于请求有一些头部数据结构,因此包含一条消息的请求的大小比消息本身大。
- retries控制消息发送失败进行重试的次数,默认0.消息重试会造成消息乱序&消息重复发送。
- acks 用于控制producer生产消息的持久性