kafka全面理解

SegmentFault

共 2423字,需浏览 5分钟

 · 2020-08-25

来源:SegmentFault思否社区
作者:byte




什么是消息队列,它的好处是什么?

解藕


将消息写入消息队列,需要消息的系统自己从消息队列中订阅,从而上游系统不需要做任何修改


例如有上游系统a,它有3个下游系统b,c,d,为了使b,c,d能拿到a的数据,a需要在代码中去调用这3个系统。如果有一天,b不再使用a的数据了或b的接口发生了变化,a还需要修改代码。而使用消息队列,就只管往队列里发送数据,需要的下游自己去队列里取数据即可。


异步


不用同步等待下游将数据处理完,将消息发到消息队列中即可返回,不阻碍主流程。


例如上游系统a是主业务,b,c,d是非主要业务,没有必要同步等待3个下游都返回主业务才继续。使用消息队列可以实现异步,提高吞吐量。


削峰


上游数据有突发流量,下游可能扛不住,kafka在中间可以起到一个缓冲的作用,把消息暂存在kafka中,下游服务就可以按照自己的节奏慢慢处理。





kafka概念


broker


broker是kafka实例。


replication


每一个partition有多副本,当主节点发生故障时,会选择一个副本作为主节点。kafka是主写主读的。


topic


topic是消息的分类,一个topic可以供任意多个消费组消费。


partition


topic的分区,每个topic的数据可以被分成多个partition,可以不在一个机器上,由此来实现kafka的伸缩性。各个partition的数据是不重复的,相同partition的数据是按照发送顺序有序的。任何partition只有一个leader,只有leader是对外提供服务的。leader接收到数据后,follower会不停给他发送请求尝试去拉取最新的数据,拉取到自己本地后,写入磁盘中。每个partition都有多个副本,相同partition的各个副本分布在不同的broker上。


consumer group/consumer


一个consumer group是一个topic的订阅者,一个topic可以被多个consumer group订阅,各个consumer group是相互独立的。一个consumer group内部可以有多个consumer,多个consumer不会消费相同的partition的消息。最多有效的consumer数与partition数相同,如果consumer数多于partition数,那么多出来的consumer不会消费到任何消息。


rebalance


消费组内某个消费者挂掉后,其他消费者自动重新分配订阅topic的partition的过程。rebalance是消费者端实现高可用的重要手段。





kafka的特性


  • 高吞吐、低延迟:kakfa 最大的特点就是收发消息非常快,kafka 每秒可以处理几十万条消息,它的最低延迟只有几毫秒。
  • 高伸缩性:每个主题(topic) 包含多个分区(partition),主题中的分区可以分布在不同的主机(broker)中。
  • 持久性、可靠性:Kafka 能够允许数据的持久化存储,消息被持久化到磁盘,并支持数据备份防止数据丢失,Kafka 底层的数据存储是基于 Zookeeper 存储的,Zookeeper 我们知道它的数据能够持久存储。
  • 容错性:允许集群中的节点失败,某个节点宕机,Kafka 集群能够正常工作
  • 高并发:支持数千个客户端同时读写





kafka为何快


页缓存+顺序写入


kafka 写数据的时候,非常关键的一点,它是以磁盘顺序写的方式来写的。仅仅将数据追加到文件的末尾,不是在文件的随机位置来修改数据。


写入磁盘文件的时候,可以直接写入这个 OS Cache 里,也就是仅仅写入内存中,接下来由操作系统自己决定什么时候把 OS Cache 里的数据真的刷入磁盘文件中。


零拷贝


如果Kafka从磁盘中读取数据发送给下游的消费者,大概过程是:


  1. 先看看要读的数据在不在os cache中,如果不在的话就从磁盘文件里读取数据后放入os cache
  2. 从操作系统的os cache 里拷贝数据到应用程序进程的缓存里
  3. 从应用程序进程的缓存里拷贝数据到操作系统层面的Socket缓存里
  4. 从Soket缓存里提取数据后发送到网卡,最后发送出去给下游消费者


整个过程有两次没必要的拷贝


  1. 从操作系统的cache里拷贝到应用进程的缓存里
  2. 从应用程序缓存里拷贝回操作系统的Socket缓存里。


为了进行这两次拷贝,中间还发生了好几次上下文切换,一会儿是应用程序在执行,一会儿上下文切换到操作系统来执行。


所以这种方式来读取数据是比较消耗性能的


零拷贝


  1. 让操作系统的cache中的数据发送到网卡
  2. 网卡传出给下游的消费者


中间跳过了两次拷贝数据的步骤,Socket缓存中仅仅会拷贝一个描述符过去,不会拷贝数据到Socket缓存


另外:


从磁盘读数据的时候,会先看看os cache内存中是否有,如果有的话,其实读数据都是直接读内存的。


如果kafka集群经过良好的调优,大家会发现大量的数据都是直接写入os cache中,然后读数据的时候也是从os cache中读。


相当于是Kafka完全基于内存提供数据的写和读了,所以这个整体性能会极其的高


消息压缩


批量发送


参考文章:

https://juejin.im/post/6844903817348136968#heading-8

https://juejin.im/post/6844903495670169607

https://zhuanlan.zhihu.com/p/96957920





点击左下角阅读原文,到 SegmentFault 思否社区 和文章作者展开更多互动和交流。

- END -

浏览 18
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报