1. kafka介绍
kafka是一个分布式liushi流式处理平台,什么是流式处理平台呢,它有以下几个特点:
a. 类似消息系统,提供事件流的发布和订阅
b. 存储事件流数据的节点具有故障容错的特点,Kafka 会把消息持久化到磁盘,有效避免了消息丢失的⻛险
c. 能够对实时的事件流进行流式地处理和分析,提供了⼀个完整的流式处理类库
2. kafak如何实现这三个特点呢:
5. 流处理系统:Kafka流处理(KafkaStreams )为开发者提供了完整的流处理API ,比如流的聚合、连接、各种转换操作,处理乱序或迟来的数据、重新处理输入数据窗口和状态操作等
3. Producer、Consumer、Broker、Topic、Partition
4. Replica kafak多副本
5. Kafka 如何保证消息不丢失
生产者在发送消息后,kafka提供了两种方式获取发送结果的api,一种是同步 sendResult.getRecordMetadata() ,
另一种是异步方法 ListenableFuture<SendResult<String, Object> future = kafkaTemplate.send(topic, obj); future.addCallback(..) ;
另外可以设置发送失败的重试次数,retries 设置完成之后,当出现⽹络问题之后能够⾃动重试消息发送,避免消息丢失,并且设置重试时间间隔,保证短时间内不会快速的进行多次重试失败,导致最终发送
失败。
哪种情况会丢失呢?
消息在被追加到分区时,会分配一个特定的偏移量offset,偏移量表示消费者消费到的分区的位置,kafka内部通过偏移量保证了消息的顺序。
a. 而如果设置了消费后自动提交offset,那么当消费者刚拿到消息时,这时应用服务出现故障,消息并没有被真的消费掉,但offset自动提交了,这就会造成消息丢失。
解决方案:手动提交offset,但这种方式会导致消费完成后尚未提交offset时,系统故障,当重新启动时,消息被二次消费。
b. 我们已经直到kafka通过多副本保证消息的安全性,正是这种多副本的方式,有可能会导致消息丢失,原因是:消息在发送到leader副本后,follower副本尚未同步完成,leader所在的broker出现故障挂
掉了,这时follower副本重新选举一个leader对外提供服务,但是leader刚收到的消息没有被同步到这个副本,就造成了消息丢失。
解决方案:设置 acks = all ,此处默认为1,即发送到leader时就成功,设置成all,意味着所有的副本同步完成才算成功。
设置 replication.factor >= 3 ,保证每个分区至少有三个副本,虽然造成数据冗余,但数据更加安全。
设置 min.insync.replicas > 1,代表消息至少被写入两个副本才算成功。默认值为1。
6. 如何保证消息不重复消费
解决方案:业务幂等性,重复消费其实造成的结果是,业务被重复处理,所以消息不重复消费不是kafka来保证的,这是需要结合相关业务,考虑架构设计或者业务设计来控制的。
例如:消费消息时存储消息唯一ID, 下次消费时校验ID,此处需结合实际情况,进行可靠设计,一般推荐redis存储,速度快
7. kafka为什么快呢?
a. kafka使用顺序读写机制
kafka的数据保存在磁盘上,但又保持了和内存处理一样的读取写入速度,原因是:因为硬盘的每次读写都会寻址,写入;寻址是一次机械操作,随机(I/O )读写非常耗时 ,但顺序 I/O 速度很快,没有
耗时的寻址动作,所以kafka选择了顺序读写(I/O )。这是kafka分区消息采用文件尾加的原因。
b. 基于MMFiles(mmap)内存映射文件的存储
但是顺序写入,磁盘操作速度也远远小于内存操作,所以这里采用了操作系统的分页存储技术,利用内存来提高I/O效率;
mmap即内存映射文件,在64位操作系统中表示了20G的数据文件,工作原理是利用操作系统的page实现文件到物理内存的直接映射,对物理内存的操作会同步到硬盘上(操作系统自己选择时机);
通过mmap,读写硬盘就像读写内存(虚拟内存)一样速度很快;
写到mmap的数据并没有被真的写到硬盘中,操作系统会在接收到flush命令时将数据写入到硬盘中,Kafka提供了一个参数 producer.type 来控制是不是flush,所以就有了异步刷盘和同步刷盘;
Kafka写入到mmap之后就立即flush然后再返回叫 同步 (sync);写入mmap之后立即返回不调用flush叫 异步 (async)。
c. kafka在读取时做了优化,基于sendfile实现Zero Copy
传统read/write方式进行网络文件传输的方式 : 硬盘—>内核buf—>用户buf—>socket相关缓冲区—>协议引擎 , 在这个过程当中,文件数据实际上是经过了四次copy
kafka 2.1版本内核引进的sendfile已经减少了内核缓冲区到user缓冲区,再由user缓冲区到socket相关缓冲区的文件copy。