kafka基础

Posted little-horse

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了kafka基础相关的知识,希望对你有一定的参考价值。

公司选取Kafka作为一种消息中间件产品。考虑的问题会是:

  • 选用什么消息中间件?
  • 为什么要用这个?
  • 好处与坏处?

一、选用什么消息中间件,举例说明几种中间件产品的优势和缺点(选型分析):

  1. ActiveMQ是老牌的消息中间件,但是问题在于没法确认ActiveMQ可以支撑互联网公司的高并发、高负载以及高吞吐的复杂场景,在国内互联网公司落地较少。而且使用较多的是一些传统企业,用ActiveMQ做异步调用和系统解耦。
  2. RabbitMQ,他的好处在于可以支撑高并发、高吞吐、性能很高,同时有非常完善便捷的后台管理界面可以使用。还支持集群化、高可用部署架构、消息高可靠支持,功能较为完善。而且经过调研,国内各大互联网公司落地大规模RabbitMQ集群支撑自身业务的case较多,国内各种中小型互联网公司使用RabbitMQ的实践也比较多。RabbitMQ的开源社区很活跃,较高频率的迭代版本,来修复发现的bug以及进行各种优化。但是RabbitMQ也有一点缺陷,就是他自身是基于erlang语言开发的,所以导致较为难以分析里面的源码,也较难进行深层次的源码定制和改造,毕竟需要较为扎实的erlang语言功底才可以。
  3. RocketMQ,是阿里开源的,经过阿里的生产环境的超高并发、高吞吐的考验,性能卓越,同时还支持分布式事务等特殊场景。而且RocketMQ是基于Java语言开发的,适合深入阅读源码,有需要可以站在源码层面解决线上生产问题,包括源码的二次开发和改造。
  4. Kafka提供的消息中间件的功能明显较少一些,相对上述几款MQ中间件要少很多。优势在于专为超高吞吐量的实时日志采集、实时数据同步、实时数据计算等场景来设计。在大数据领域中配合实时计算技术(比如Spark)使用的较多。但是在传统的MQ中间件使用场景中较少采用。

二、为什么在你们系统架构中要引入消息中间件?

  • 复杂系统解耦
  • 复杂链路的异步调用
  • 瞬时高峰的流量削峰

三、哥们,那你说说系统架构引入消息中间件有什么缺点

  • 系统可用性降低——MQ可用性
  • 系统稳定性降低
  • 分布式一致性问题

四、哥们,消息中间件在你们项目里是如何落地的?或者问Kafka的结构原理和核心源码?

五、Kafka如何通过精妙的架构设计优化JVM GC问题

客户端发送消息给kafka服务器的时候,一定是有一个内存缓冲机制的,消息会先写入一个内存缓冲中,然后直到多条消息组成了一个Batch,才会一次网络通信把Batch发送过去。

  • 优点:这样每次网络请求都可以发送很多数据过去,避免了一条消息一次网络请求。从而提升了吞吐量,即单位时间内发送的数据量。
  • 缺点:一个Batch中的数据,会取出来然后封装在底层的网络包里,通过网络发送出去到达Kafka服务器。你要知道,这些Batch里的数据此时可还在客户端的JVM的内存里啊!那么此时从代码实现层面,一定会尝试避免任何变量去引用这些Batch对应的数据,然后尝试触发JVM自动回收掉这些内存垃圾。这样不断的让JVM回收垃圾,就可以不断的清理掉已经发送成功的Batch了,然后就可以不断的腾出来新的内存空间让后面新的数据来使用。——最大的问题,就是JVM GC问题

解决方法:缓冲池的机制——Batch底层的内存空间不要交给JVM去垃圾回收,而是把这块内存空间给放入一个缓冲池里。如果我现在把一个缓冲池里的内存资源都占满了,现在缓冲池里暂时没有内存块了,怎么办呢?很简单,阻塞你的写入操作,不让你继续写入消息了。把你给阻塞住,不停的等待,直到有内存块释放出来,然后再继续让你写入消息。

六、Kafka到底是如何做到这么高的吞吐量和性能的呢?

1、页缓存技术 + 磁盘顺序写(写入,生产)

  • Kafka是基于操作系统的页缓存来实现文件写入的,操作系统本身有一层缓存,叫做page cache,是在内存里的缓存,我们也可以称之为os cache,意思就是操作系统自己管理的缓存。在写入磁盘文件的时候,可以直接写入这个os cache里,也就是仅仅写入内存中,接下来由操作系统自己决定什么时候把os cache里的数据真的刷入磁盘文件中。
  • 以磁盘顺序写的方式来写的。也就是说,仅仅将数据追加到文件的末尾,不是在文件的随机位置来修改数据。普通的机械磁盘如果你要是随机写的话,确实性能极差,也就是随便找到文件的某个位置来写数据。但是如果你是追加文件末尾按照顺序的方式来写数据的话,那么这种磁盘顺序写的性能基本上可以跟写内存的性能本身也是差不多的。
技术图片

2、零拷贝技术(读取,消费) - 假设要是kafka什么优化都不做,就是很简单的从磁盘读数据发送给下游的消费者,那么大概过程如下所示:

1.先看看要读的数据在不在os cache里,如果不在的话就从磁盘文件里读取数据后放入os cache。

2.接着从操作系统的os cache里拷贝数据到应用程序进程的缓存里,再从应用程序进程的缓存里拷贝数据到操作系统层面的Socket缓存里,最后从Socket缓存里提取数据后发送到网卡,最后发送出去给下游消费。

技术图片
有两次没必要的拷贝吧 一次是从操作系统的cache里拷贝到应用进程的缓存里,接着又从应用程序缓存里拷贝回操作系统的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底层的页缓存技术+磁盘顺序写的思路+零拷贝技术-->实现每秒几十万的吞吐量

七、写入Kafka的数据该如何保证其不丢失?

问题:如果每天产生几十TB的数据,难道都写一台机器的磁盘上吗?

解决:Kafka有一个概念叫做Partition,就是把一个topic数据集合拆分为多个数据分区,你可以认为是多个数据分片,每个Partition可以在不同的机器上,储存部分数据。

技术图片
Kafka分布式存储架构

 

问题:我们又会遇到一个问题,就是万一某台机器宕机了,这台机器上的那个partition管理的数据不就丢失了吗?

解决:我们还得做多副本冗余,每个Partition都可以搞一个副本放在别的机器上,这样某台机器宕机,只不过是Partition其中一个副本丢失。

如果某个Partition有多副本的话,Kafka会选举其中一个Parititon副本作为Leader,然后其他的Partition副本是Follower。

只有Leader Partition是对外提供读写操作的,Follower Partition就是从Leader Partition同步数据。

一旦Leader Partition宕机了,就会选举其他的Follower Partition作为新的Leader Partition对外提供读写服务,这不就实现了高可用架构了?

技术图片
Kafka高可用架构

 

问题: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的数据不会丢失

技术图片
kafka的数据不丢失:ISR机制



以上是关于kafka基础的主要内容,如果未能解决你的问题,请参考以下文章

1.5万字长文:从 C# 入门 Kafka(Kafka .NET 基础)

Kafka入门实战教程基础概念与术语

kafka基础命令

Kafka--kafka基础知识

Kafka-安装与基础操作

Kafka框架基础