标签:就会 总结 -- 应用程序 开源社区 简单 idt 怎么办 java语言
客户端发送消息给kafka服务器的时候,一定是有一个内存缓冲机制的,消息会先写入一个内存缓冲中,然后直到多条消息组成了一个Batch,才会一次网络通信把Batch发送过去。
解决方法:缓冲池的机制——Batch底层的内存空间不要交给JVM去垃圾回收,而是把这块内存空间给放入一个缓冲池里。如果我现在把一个缓冲池里的内存资源都占满了,现在缓冲池里暂时没有内存块了,怎么办呢?很简单,阻塞你的写入操作,不让你继续写入消息了。把你给阻塞住,不停的等待,直到有内存块释放出来,然后再继续让你写入消息。
1、页缓存技术 + 磁盘顺序写(写入,生产)
2、零拷贝技术(读取,消费) - 假设要是kafka什么优化都不做,就是很简单的从磁盘读数据发送给下游的消费者,那么大概过程如下所示:
1.先看看要读的数据在不在os cache里,如果不在的话就从磁盘文件里读取数据后放入os cache。
2.接着从操作系统的os cache里拷贝数据到应用程序进程的缓存里,再从应用程序进程的缓存里拷贝数据到操作系统层面的Socket缓存里,最后从Socket缓存里提取数据后发送到网卡,最后发送出去给下游消费。
而且为了进行这两次拷贝,中间还发生了好几次上下文切换,一会儿是应用程序在执行,一会儿上下文切换到操作系统来执行。
所以这种方式来读取数据是比较消耗性能的。
kafka优化:读数据的时候是引入零拷贝技术
直接让操作系统的cache中的数据发送到网卡后传输给下游的消费者,中间跳过了两次拷贝数据的步骤,Socket缓存中仅仅会拷贝一个描述符过去,不会拷贝数据到Socket缓存。
通过零拷贝技术,就不需要把os cache里的数据拷贝到应用缓存,再从应用缓存拷贝到Socket缓存了,两次拷贝都省略了,所以叫做零拷贝。
对Socket缓存仅仅就是拷贝数据的描述符过去,然后数据就直接从os cache中发送到网卡上去了,这个过程大大的提升了数据消费时读取文件数据的性能。
而且大家会注意到,在从磁盘读数据的时候,会先看看os cache内存中是否有,如果有的话,其实读数据都是直接读内存的。
如果kafka集群经过良好的调优,大家会发现大量的数据都是直接写入os cache中,然后读数据的时候也是从os cache中读。
相当于是Kafka完全基于内存提供数据的写和读了,所以这个整体性能会极其的高。
说个题外话,下回有机会给大家说一下Elasticsearch的架构原理,其实ES底层也是大量基于os cache实现了海量数据的高性能检索的,跟Kafka原理类似。
总结:kafka底层的页缓存技术+磁盘顺序写的思路+零拷贝技术-->实现每秒几十万的吞吐量
问题:如果每天产生几十TB的数据,难道都写一台机器的磁盘上吗?
解决:Kafka有一个概念叫做Partition,就是把一个topic数据集合拆分为多个数据分区,你可以认为是多个数据分片,每个Partition可以在不同的机器上,储存部分数据。
问题:我们又会遇到一个问题,就是万一某台机器宕机了,这台机器上的那个partition管理的数据不就丢失了吗?
解决:我们还得做多副本冗余,每个Partition都可以搞一个副本放在别的机器上,这样某台机器宕机,只不过是Partition其中一个副本丢失。
如果某个Partition有多副本的话,Kafka会选举其中一个Parititon副本作为Leader,然后其他的Partition副本是Follower。
只有Leader Partition是对外提供读写操作的,Follower Partition就是从Leader Partition同步数据。
一旦Leader Partition宕机了,就会选举其他的Follower Partition作为新的Leader Partition对外提供读写服务,这不就实现了高可用架构了?
问题:Kafka写入数据丢失问题:
大家都知道写入数据都是往某个Partition的Leader写入的,然后那个Partition的Follower会从Leader同步数据。但是万一1条数据刚写入Leader Partition,还没来得及同步给Follower,此时Leader Partiton所在机器突然就宕机了呢?
解决: Kafka的ISR机制:
就是会自动给每个Partition维护一个ISR列表,这个列表里一定会有Leader,然后还会包含跟Leader保持同步的Follower。
也就是说,只要Leader的某个Follower一直跟他保持数据同步,那么就会存在于ISR列表里。
但是如果Follower因为自身发生一些问题,导致不能及时的从Leader同步数据过去,那么这个Follower就会被认为是“out-of-sync”,从ISR列表里踢出去。
所以大家先得明白这个ISR是什么,说白了,就是Kafka自动维护和监控哪些Follower及时的跟上了Leader的数据同步。
所以如果要让写入Kafka的数据不丢失,你需要要求几点:
1.每个Partition都至少得有1个Follower在ISR列表里,跟上了Leader的数据同步
2.每次写入数据的时候,都要求至少写入Partition Leader成功,同时还有至少一个ISR里的Follower也写入成功,才算这个写入是成功了
3.如果不满足上述两个条件,那就一直写入失败,让生产系统不停的尝试重试,直到满足上述两个条件,然后才能认为写入成功
4.按照上述思路去配置相应的参数,才能保证写入Kafka的数据不会丢失
标签:就会 总结 -- 应用程序 开源社区 简单 idt 怎么办 java语言
原文地址:https://www.cnblogs.com/little-horse/p/12230339.html