应大部分的小伙伴的要求,今天这篇咱们用大白话带你认识 Kafka

Kafka基础

消息系统的作用

大部分小伙伴应该都清楚,这里用机油装箱举个例子:

所以消息系统就是如上图我们所说的仓库,能在中间过程作为缓存,并且实现解耦合的作用。

引入一个场景,我们知道中国移动,中国联通,中国电信的日志处理,是交给外包去做大数据分析的,假设现在它们的日志都交给了你做的系统去做用户画像分析。

按照刚刚前面提到的消息系统的作用,我们知道了消息系统其实就是一个模拟缓存,且仅仅是起到了缓存的作用而并不是真正的缓存,数据仍然是存储在磁盘上面而不是内存。

Topic 主题

Kafka 学习了数据库里面的设计,在里面设计了 Topic(主题),这个东西类似于关系型数据库的表:

此时我需要获取中国移动的数据,那就直接监听 TopicA 即可。

Partition 分区

Kafka 还有一个概念叫 Partition(分区),分区具体在服务器上面表现起初就是一个目录。

一个主题下面有多个分区,这些分区会存储到不同的服务器上面,或者说,其实就是在不同的主机上建了不同的目录。

这些分区主要的信息就存在了 .log 文件里面。跟数据库里面的分区差不多,是为了提高性能。

至于为什么提高了性能,很简单,多个分区多个线程,多个线程并行处理肯定会比单线程好得多。

Topic 和 Partition 像是 HBase 里的 Table 和 Region 的概念,Table 只是一个逻辑上的概念,真正存储数据的是 Region。

这些 Region 会分布式地存储在各个服务器上面,对应于 Kafka,也是一样,Topic 也是逻辑概念,而 Partition 就是分布式存储单元。

这个设计是保证了海量数据处理的基础。我们可以对比一下,如果 HDFS 没有 Block 的设计,一个 100T 的文件也只能单独放在一个服务器上面,那就直接占满整个服务器了,引入 Block 后,大文件可以分散存储在不同的服务器上。

注意:

  • 分区会有单点故障问题,所以我们会为每个分区设置副本数。

  • 分区的编号是从 0 开始的。

Producer 生产者

往消息系统里面发送数据的就是生产者:

Consumer 消费者

从 Kafka 里读取数据的就是消费者:

Message 消息

Kafka 里面的我们处理的数据叫做消息。

Kafka的集群架构

创建一个 TopicA 的主题,3 个分区分别存储在不同的服务器,也就是 Broker 下面。

Topic 是一个逻辑上的概念,并不能直接在图中把 Topic 的相关单元画出:

需要注意:Kafka 在 0.8 版本以前是没有副本机制的,所以在面对服务器宕机的突发情况时会丢失数据,所以尽量避免使用这个版本之前的 Kafka。

Replica 副本

Kafka 中的 Partition 为了保证数据安全,所以每个 Partition 可以设置多个副本。

此时我们对分区 0,1,2 分别设置 3 个副本(其实设置两个副本是比较合适的):

而且其实每个副本都是有角色之分的,它们会选取一个副本作为 Leader,而其余的作为 Follower。

我们的生产者在发送数据的时候,是直接发送到 Leader Partition 里面,然后 Follower Partition 会去 Leader 那里自行同步数据,消费者消费数据的时候,也是从 Leader 那去消费数据的。

Consumer Group 消费者组

我们在消费数据时会在代码里面指定一个 group.id,这个 id 代表的是消费组的名字,而且这个 group.id 就算不设置,系统也会默认设置:

conf.setProperty("group.id","tellYourDream")

我们所熟知的一些消息系统一般来说会这样设计,就是只要有一个消费者去消费了消息系统里面的数据,那么其余所有的消费者都不能再去消费这个数据。

可是 Kafka 并不是这样,比如现在 ConsumerA 去消费了一个 TopicA 里面的数据:

consumerA:group.id = a
consumerB:group.id = aconsumerC:group.id = b
consumerD:group.id = b

再让 ConsumerB 也去消费 TopicA 的数据,它是消费不到了,但是我们在 ConsumerC 中重新指定一个另外的 group.id,ConsumerC 是可以消费到 TopicA 的数据的。

而 ConsumerD 也是消费不到的,所以在 Kafka 中,不同组可有唯一的一个消费者去消费同一主题的数据。

所以消费者组就是让多个消费者并行消费信息而存在的,而且它们不会消费到同一个消息。

如下,ConsumerA,B,C 是不会互相干扰的:

consumer group:aconsumerAconsumerBconsumerC

如图,因为前面提到过了消费者会直接和 Leader 建立联系,所以它们分别消费了三个 Leader,所以一个分区不会让消费者组里面的多个消费者去消费,但是在消费者不饱和的情况下,一个消费者是可以去消费多个分区的数据的。

Controller

熟知一个规律:在大数据分布式文件系统里面,95% 的都是主从式的架构,个别是对等式的架构,比如 ElasticSearch。

Kafka 也是主从式的架构,主节点就叫 Controller,其余的为从节点,Controller 是需要和 Zookeeper 进行配合管理整个 Kafka 集群。

Kafka 和 Zookeeper 如何配合工作

Kafka 严重依赖于 Zookeeper 集群,所有的 Broker 在启动的时候都会往 Zookeeper 进行注册,目的就是选举出一个 Controller。

这个选举过程非常简单粗暴,就是一个谁先谁当的过程,不涉及什么算法问题。

那成为 Controller 之后要做啥呢,它会监听 Zookeeper 里面的多个目录,例如有一个目录 /brokers/,其他从节点往这个目录上**注册(就是往这个目录上创建属于自己的子目录而已)**自己。

这时命名规则一般是它们的 id 编号,比如 /brokers/0,1,2。注册时各个节点必定会暴露自己的主机名,端口号等等的信息。

此时 Controller 就要去读取注册上来的从节点的数据(通过监听机制),生成集群的元数据信息,之后把这些信息都分发给其他的服务器,让其他服务器能感知到集群中其它成员的存在。

此时模拟一个场景,我们创建一个主题(其实就是在 Zookeeper 上 /topics/topicA 这样创建一个目录而已),Kafka 会把分区方案生成在这个目录中。

此时 Controller 就监听到了这一改变,它会去同步这个目录的元信息,然后同样下放给它的从节点,通过这个方法让整个集群都得知这个分区方案,此时从节点就各自创建好目录等待创建分区副本即可。这也是整个集群的管理机制。

加餐时间

Kafka 性能好在什么地方?

①顺序写

操作系统每次从磁盘读写数据的时候,需要先寻址,也就是先要找到数据在磁盘上的物理位置,然后再进行数据读写,如果是机械硬盘,寻址就需要较长的时间。

Kafka 的设计中,数据其实是存储在磁盘上面,一般来说,会把数据存储在内存上面性能才会好。

但是 Kafka 用的是顺序写,追加数据是追加到末尾,磁盘顺序写的性能极高,在磁盘个数一定,转数达到一定的情况下,基本和内存速度一致。

随机写的话是在文件的某个位置修改数据,性能会较低。

②零拷贝

先来看看非零拷贝的情况:

可以看到数据的拷贝从内存拷贝到 Kafka 服务进程那块,又拷贝到 Socket 缓存那块,整个过程耗费的时间比较高。

Kafka 利用了 Linux 的 sendFile 技术(NIO),省去了进程切换和一次数据拷贝,让性能变得更好。

日志分段存储

Kafka 规定了一个分区内的 .log 文件最大为 1G,做这个限制目的是为了方便把 .log 加载到内存去操作:

00000000000000000000.index
00000000000000000000.log
00000000000000000000.timeindex00000000000005367851.index
00000000000005367851.log
00000000000005367851.timeindex00000000000009936472.index
00000000000009936472.log
00000000000009936472.timeindex

这个 9936472 之类的数字,就是代表了这个日志段文件里包含的起始 Offset,也就说明这个分区里至少都写入了接近 1000 万条数据了。

Kafka Broker 有一个参数,log.segment.bytes,限定了每个日志段文件的大小,最大就是 1GB。

一个日志段文件满了,就自动开一个新的日志段文件来写入,避免单个文件过大,影响文件的读写性能,这个过程叫做 log rolling,正在被写入的那个日志段文件,叫做 active log segment。

如果大家有了解 HDFS 就会发现 NameNode 的 edits log 也会做出限制,所以这些框架都是会考虑到这些问题。

Kafka 的网络设计

Kafka 的网络设计和 Kafka 的调优有关,这也是为什么它能支持高并发的原因:

首先客户端发送请求全部会先发送给一个 Acceptor,Broker 里面会存在 3 个线程(默认是 3 个)。

这 3 个线程都是叫做 Processor,Acceptor 不会对客户端的请求做任何的处理,直接封装成一个个 socketChannel 发送给这些 Processor 形成一个队列。

发送的方式是轮询,就是先给第一个 Processor 发送,然后再给第二个,第三个,然后又回到第一个。

消费者线程去消费这些 socketChannel 时,会获取一个个 Request 请求,这些 Request 请求中就会伴随着数据。

线程池里面默认有 8 个线程,这些线程是用来处理 Request 的,解析请求,如果 Request 是写请求,就写到磁盘里。读的话返回结果。

Processor 会从 Response 中读取响应数据,然后再返回给客户端。这就是 Kafka 的网络三层架构。

所以如果我们需要对 Kafka 进行增强调优,增加 Processor 并增加线程池里面的处理线程,就可以达到效果。

Request 和 Response 那一块部分其实就是起到了一个缓存的效果,是考虑到 Processor 们生成请求太快,线程数不够不能及时处理的问题。

所以这就是一个加强版的 Reactor 网络线程模型。

总结

集群的搭建会再找时间去提及。这一篇简单地从角色到一些设计的方面讲述了 Kafka 的一些基础,在之后的更新中会继续逐步推进,进行更加深入浅出的讲解。

面试问Kafka,这一篇全搞定相关推荐

  1. ELK系列(十五)、Elasticsearch核心原理一篇全搞定

    目录 Lucene 介绍 核心术语 如何理解倒排索引? 检索方式 分段存储 段合并策略 Elasticsearch 核心概念 节点类型 集群状态 3C和脑裂 1.共识性(Consensus) 2.并发 ...

  2. zabbix监控哪些东西_监控系统选型,一篇全搞定

    之前,写过几篇有关线上问题排查的文章,文中附带了一些监控图,有些读者对此很感兴趣,问我监控系统选型上有没有好的建议? 图片来自 Pexels 目前我所经历的几家公司,监控系统都是自研的.其实业界有很多 ...

  3. SpringBoot 就这一篇全搞定

    一.Hello Spring Boot 1.Spring Boot 简介 简化Spring应用开发的一个框架: 整个Spring技术栈的一个大整合: J2EE开发的一站式解决方案: 2.微服务 微服务 ...

  4. 从头撸到脚,SpringBoot 就一篇全搞定!

    一.Hello Spring Boot 1.Spring Boot 简介 简化Spring应用开发的一个框架: 整个Spring技术栈的一个大整合: J2EE开发的一站式解决方案: 2.微服务 微服务 ...

  5. 一看就会!一篇全搞定!权限处理专家--Shiro保姆式教学,超详细!

    轻量级权限处理框架--Shiro 前言 Shiro三大对象 Subject SecurityManager Realm Authentication和Authorization Authenticat ...

  6. 开关电源波纹的产生、测量及抑制,一篇全搞定!

    开关电源纹波的产生 我们最终的目的是要把输出纹波降低到可以忍受的程度,达到这个目的最根本的解决方法就是要尽量避免纹波的产生,首先要清楚开关电源纹波的种类和产生原因. 上图是开关电源中最简单的拓扑结构- ...

  7. Qt5 pyqt5图片编辑器功能函数一篇全搞定:实现图片格式转换、显示、缩放、特效处理(模糊、锐化,浮雕等等)

    在本篇的基础上,你可以轻松实现一个自己的图片编辑器哦. 无论是图片格式的转换,还是各种效果的展示,基本和目前我们常用的图片编辑器功能雷同了. 至于pyqt5界面的编写,大家可以查看我的另外几篇文章,或 ...

  8. 爬虫技术——一篇全搞定!

    目录: 目录 目录: 1. 爬虫介绍 1.1 爬虫是什么 1.2 爬虫步骤 1.3 爬虫分类 1.3.1 通用爬虫 1.3.2 聚焦爬虫 ​编辑 1.4 一些常见的反爬手段 2. Urllib 2.1 ...

  9. mysql可以安多个吗_全屋插座安多高?5个数字全搞定

    原标题:全屋插座安多高?5个数字全搞定 全屋插座安多高?5个数字全搞定 都知道新房装修要多做些插座,但对于它安装的高度是多少很多人就不知道.对于插座安装的高度建议不是很多.但插座在安装时一定要把它们都 ...

最新文章

  1. 2018年4月26日笔记
  2. iOS--SDAutolayout宽度自适应
  3. 你应该知道的Excel 2007小技巧
  4. 用python阐释工作量证明(proof of work)
  5. Hyperledger Fabric基础知识
  6. 华三交换机ping大包命令_华三交换机常用命令
  7. 阿里云SLB负载均衡与使用SSL域名证书
  8. 7读不出来卡显示无服务器,win7识别不了网络如何解决_win7显示未识别网络的处理方法...
  9. OpenCV Using Python——基于SURF特征提取和金字塔LK光流法的单目视觉三维重建 (光流、场景流)...
  10. java 内存接口_java中多态机制的内存解析、抽象类、接口
  11. 新 CEO 谈论GitHub 被微软接管后的未来
  12. flask加载配置文件的三种方法
  13. 程序员工作交接文档怎么写_你认为程序员需不需要写文档?需要写哪些文档?...
  14. 腾讯加入QQ群 连接代码
  15. ios越狱开发_隐藏Root(Cydia)图标
  16. ajax authorization,ajax跨域,_ajax Authorization 鉴权失败,ajax跨域 - phpStudy
  17. Linux程序包管理命令之rpm
  18. 关于Too many re-renders. React limits the number of renders to prevent an infinite loop.的解决方案
  19. Android 抛弃原生WebView,使用腾讯X5内核、并加入广告拦截。
  20. 数据库触发器(转自http://blog.csdn.net/chinayuan/article/details/6292335/#)

热门文章

  1. JavaScript- BOM, DOM
  2. springcloud13---zuul
  3. javascript基础 (2)
  4. Visual C++ 中的重大更改
  5. iOS 修改搜索框的样式为白色
  6. Repository模式(转载)
  7. epoll 使用详解
  8. diff与patch命令
  9. VC6中根据需要显示滚动条
  10. 推荐文章:《同济大学软件学院万院长谈择业》