kafka系列——日志篇

6 篇文章 0 订阅
6 篇文章 0 订阅

kafka的日志格式

ps:该图引用下面kafka日志版本的演变的博客

  • crc32:消息校验码                                                                                                                                
  • magic:消息版本号,0=v0,1=v1,2=v2,目前是2                                                                                                                              
  • attributes:占用2字节,低3位指压缩格式,0=none,1=gzip,2=snappy,3=lz4;第4位指时间戳,第5位值是否为事务消息,第6位指是否为control消息,用于支持事务,0=否,1=是,其余保留                                                                                                                                
  • key length:息的key的长度,若为-1,则表示没有设置key,即key=null                                                                                                        
  • key:可选,如果没有key则无此字段                                                                                                                                
  • value length:实际消息体的长度,若为-1,则表示消息为空(墓碑消息)                                                                                                     
  • value:消息体,可以为空,即墓碑消息                                                                                                                                
  • 中图length:消息总长度                                                                                                                              
  •  timestamp delta:时间戳增量,这里保存与RecordBatch的起始时间戳的差值                                                                                
  •  offset delta:位移增量,保存与RecordBatch起始位移的差值                                                       
  • headers:用来支持应用级别的扩展,而无需像v0和v1版本一样将一些应用级别的属性值嵌入在消息体里面                                  
  • first offset:表示当前RecordBatch的起始位移                                                                                                                              
  • 左图length:计算partition leader epoch到headers之间的长度                                         
  • partition leader epoch:用来确保数据可靠性                                         
  • last offset delta:RecordBatch中最后一个Record的offset与第一个Record的offset的差值,主要被broker用来确认RecordBatch中Records的组装正确性                                       
  •  first timestamp:RecordBatch中第一条Record的时间戳                                         
  • max timestamp:RecordBatch中最大的时间戳,一般情况下是指最后一个Record的时间戳,  和last offset delta的作用一样,用来确保消息组装的正确性                                          
  • producer id:用来支持幂等性                                         
  • producer epoch:和producer id一样,用来支持幂等性                                       
  •  first sequence:和producer id与producer epoch一样,用来支持幂等性                                         
  • records count:RecordBatch中Record的个数

日志查找

1.查找offset=350的消息,先二分查找确定消息在哪个segment中                           

2.到对应segment的.index文件中找到小于350的最大偏移量,即 345,其对应的物理位置是328                                             

3.根据物理位置328,直接定位到.log文件的328文件位置                           

4.顺序读取每条消息的偏移量,但不读取消息内容                           

5.找到offset=350的消息,得到物理位置为448                           

6.开始真正读取offset=350的消息内容并返回 

日志压缩(log campaction)

在默认的删除规则之外提供的另一种数据清除策略,对于有相同key的的不同value值,只保留最后一个版本 kafka中

用于保存消费者消费位移的主题”__consumer_offsets”使用的就是log compaction策略

每个日志目录下,有名为”cleaner-offset-checkpoint”的文件,根据该文件可以将日志文件分成2部分

clean部分:偏移量是断续的,经过压缩的部分

dirty部分:偏移量是连续的,未清理过的部分

activeSegment部分:活跃的热点数据,不参与log campaction,默认情况下firstUncleanableOffset等于activeSegment的baseOffset

log campaction使用时应注意每个消息的key值不为null,这种方式当客户端进行消费时总能赶上dirty部分的情况,它就能读取到日志的所有消息,反之,就不可能读到全部的消息

如何确选择合适的log文件进行清理:

选择污浊率最高的,可通过配置log.cleaner.min.cleanable.ratio参数(默认0.5)

dirtyRatio = dirtyBytes / (cleanBytes + dirtyBytes)

如何对log文件中消息的key进行筛选:

1.创建一个名为”SkimpyOffsetMap”的哈希表来构建key与offset的映射表

2.遍历第一遍log文件,把每个key的hashCode和最后出现的offset都保存在SkimpyOffsetMap中

3.遍历第二遍log文件,检查每个消息是否符合保留条件,如果符合就保留下来,否则就会被清理掉

保留条件:假设一条消息的offset为O1,这条消息的key在SkimpyOffsetMap中所对应的offset为O2,如果O1>=O2即为满足保留条件

hash冲突处理:采用线性探测法来处理哈希冲突

缺点:遇到两个不同的key但哈希值相同的情况,那么其中一个key所对应的消息就会丢失

日志压缩步骤举例:

1.第一次日志压缩,清理点为0,日志头部的范围从0到活动分段的基准偏移量13

2.第一次压缩后,清理点更新为13,第二次日志压缩时,日志头部范围从13到活动日志分段的基准偏移量20,日志尾部范围从0到清理点的位置13

3.第二次压缩后,清理点更新为20,第三次日志压缩时,日志头部范围从20到活动日志分段的基准偏移量28,日志尾部范围从2到清理点的位置20

日志压缩合并:

1.第一次日志压缩,清理点等于0,没有尾部日志,日志头部从6:00带7:40,所有日志分段文件都是1GB,不考虑删除的消息

2.第一次日志压缩后,清理点改为日志头部末尾即7:40,每个新日志分段的大小都小于1GB

3.第二次日志压缩时,清理点为7:40,日志头部从8:00到8:10,日志尾部从6:00到7:40,压缩操作会将多个小文件分成1组,每一组不超过1GB

kafka日志版本的演变

https://www.cnblogs.com/qwangxiao/p/9043491.html

kafka生产者幂等的实现思路

1.为每个producer设置唯一的PID

2.引入了序列号字段sequence number,标识某个producer发送的每批消息,sequence number是从0开始严格单调递增的

3.broker端会为每个PID(即每个producer)保存该producer发送过来的消息batch的某些元信息(如PID信息、消息batch的起始seq number及结束seq number等)

4.每当该PID发送新的消息batch时,Kafka broker就会对比这些信息,如果发生冲突(比如起始seq number和结束seq number与当前缓存的相同),那么broker就会拒绝这次写入请求;倘若没有冲突,那么broker端就会更新这部分缓存然后再开始写入消息

总结:为每个producer设置唯一的PID并引入seq number以及broker端seq number缓存更新机制来去重

这部分完~

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值