1、Offset如何标记数据
每个分区的offset都是从1开始标记的
每个分区将数据切分成segment(段),每个段由log和index两份文件组成
假设一个Topic的数据,有三个分区,存了4500条数据:
ruozedata-0 1开始标记…
ruozedata-1 1开始标记…
ruozedata-2 1开始标记…
命名规则:
第一组0开头,存了1000条:
00000000000000000000.index
00000000000000000000.log
第二组,由上一组的最后一条消息的offset来命名,存了2500条:
00000000000000001000.index
00000000000000001000.log
第三组,由第二组的最后一条消息的offset来命名,存了1000条:
00000000000000003500.index
00000000000000003500.log
绝对offset:是关于分区的全局id,比如ruozedata-0分区(3个log文件 全局的id)
相对offset::存储在index文件里,对应其log文件的消息的id,格式是:相对offset-id,对应log的pos位置
index存储:是稀疏存储的, log文件里的每条信息不会都有一个index的,而是挑选的部分index。
举例,假设mysql一张表维护的offset信息:
对于上面提到的概念,结合这个表,就一目了然。
mysql表
globalid sid message
1 1
2 2
3 3
4 4
...
1000 1000
------------------
1001 1
1002 2
1003 3
...
1010 10
...
3500 2500
-----------------
3501 1
3502 2
3503 3
...
4500 1000
2、Offset如何寻址
还是根据上面的例子
假设:寻找offset为1016的消息是什么?
这里的1016是全局的offset,用二分查找法。
第一步,先找到<=1016的最大的segment文件
00000000000000000000.index # [0-1000)
00000000000000000000.log
#那么此时知道是落在这个区间,在第二个segment里面,他里面包含的是[1000-3500)的数据条数信息
00000000000000001000.index
00000000000000001000.log
00000000000000003500.index #[3500,4500]
00000000000000003500.log
第二步,1016-1000=16 为index的相对offset,去index找 <=16的最大的相对offset
假设index里面存储的是这样的信息,因为是稀疏存储,不会存所有的index记录。
那么找到的就是: 10,98这一行的信息
第三步,去对应的log文件找到98位置,按顺序往下读到第16条消息即可,我们要的是第16条的信息,而index只维护了第10条所在位置的信息,所以最优位置只能从第10所在的位置开始读。
#读log文件,98位置,按顺序读到第16条
00000000000000001000.log
3、消费模式
at most once :最多消费一次 0/1 可能丢数据,但是不重复
at least once:至少消费一次 >=1 不丢数据 但是会重复(实际工作中常用)
exactly once::精准消费一次 1 不丢 也不重复
4、参数调优
配置文件,主要是这三个
[hadoop@vm01 config]$ ll
-rw-r--r--. 1 hadoop hadoop 1221 Nov 9 2018 consumer.properties
-rw-r--r--. 1 hadoop hadoop 1925 Nov 9 2018 producer.properties
-rw-r--r--. 1 hadoop hadoop 6963 Aug 9 09:54 server.properties
#producer
#这意味着领导者将等待完整的同步副本来确认记录。leader是用来读写,另外俩副本用来同步
#这保证了只要至少有一个同步副本仍然存在,记录就不会丢失。这是最有力的保证
acks=all
#生产者可用于缓冲等待发送到服务器的记录的总内存字节数。
#如果记录发送的速度比发送到服务器的速度快,那么生产者将阻塞max.block。之后,它将抛出异常。
buffer.memory
#生成器生成的所有数据的压缩类型。默认值是none(即没有压缩)
compression.type = snappy
#重试次数
retries=100
#客户机在阻塞之前在单个连接上发送的未确认请求的最大数量。
#注意,如果该设置被设置为大于1且发送失败,则由于重试(即,如果启用重试功能)。
max.in.flight.requests.per.connection=1
#当多个记录被发送到同一个分区时,生产者将尝试将这些记录一起批处理成更少的请求。
#这有助于提高客户机和服务器的性能。此配置以字节为单位控制默认批处理大小。
batch.size
#此设置将限制生产者在单个请求中发送的记录批次的数量,以避免发送巨大的请求。
#这也有效地限制了最大记录批大小。注意,服务器对记录批大小有自己的上限,这可能与此不同。
max.request.size
#客户机等待请求响应的最大时间量
request.timeout.ms
timeout.ms
#Broker/server
advertised.host.name ?????
#Kafka允许的最大记录批大小
message.max.bytes
#服务器用于处理请求的线程数,可能包括磁盘I/O
num.io.threads
#服务器用于从网络接收请求并向网络发送响应的线程数
num.network.threads
#客户端等待与zookeeper建立连接的最长时间
zookeeper.connection.timeout.ms
#zookeeper会话超时
zookeeper.session.timeout
#consumer: new
#服务器应该为获取请求返回的最大数据量。
fetch.message.max.bytes
#如果为真,使用者的偏移量将在后台定期提交。
auto.commit.enable : false
#当Kafka中没有初始偏移量,或者当前偏移量在服务器上不存在时(例如,因为数据已被删除),该怎么办?
#earliest: 自动重置偏移到最早的偏移
#latest:自动将偏移量重置为最新偏移量
#none: 如果没有为使用者的组找到以前的偏移量,则向使用者抛出异常
#anything else:向使用者抛出异常。
auto.offset.reset
"auto.offset.reset" -> "latest",
"enable.auto.commit" -> (false: java.lang.Boolean)
#如果enable.auto.commit设置为true,则使用者偏移量自动提交到Kafka的频率(以毫秒为单位)。
auto.commit.interval.ms