最近在测试kafka的读写性能,所以借这个机会了解了kafka的一些设计原理,既然作为分布式系统,我们还是按照分布式的套路进行分析。

Kafka的逻辑数据模型:

生产者发送数据给服务端时,构造的是ProducerRecord<Integer, String>(String topic, Integer key,String value)对象并发送,从这个构造函数可以看到,kafka的表面逻辑数据模型是key-value。当然api再发送前还会在这个基础上加入若干校验信息,不过这个对用户而言是透明的。

Kafka的分发策略:

跟很多分布式多备份系统类似,kafka的基本网络结构如下:

一个节点(Broker)中存有不同partition的备份,一个parittion存在多份备份保存在不同节点上并且选举出一个作为leader跟客户端交互,一个topic拥有多个parittion。

默认的kafka分发算法是hash(key)%numPartitions,简单来就是哈希再取模。当然这个算法可以自定义,只要重写相关接口。如上图在一个四台主机上创建了一个有两个备份,四个分区partion的话题topic,但生产者需要发送某个key-value对象到消息队列里面时,创建连接时通过访问zookeeper,获取到一份leader partion列表(Broker1. Partition-0, Broker2. Partition1, Broker3. Partition-2, Broker4.Partition-3),再根据分发算法计算出这个对象应该要发送到哪个leader partion中。

Kafka的物理存储模型和查找数据的设计:

Kafka的物理存储模型比较简单,在kafka的物理持久化的存储中有分Segment的概念,每个Segment有两种类型的文件:索引文件***.index和日志文件(数据文件)***.log。两者的命名规则都是以这个Segment的第一条的消息逻辑偏移量作为文件名。索引是稀疏索引,目的在于减少索引文件的数据量,其文件的内容是key-value结构,key是消息的偏移量offeset(就是一个自增的序列号),value是对应的log文件的实际物理磁盘偏移量。

值得一提的是,跟其他正常分布式不一样,kafka并不支持根据给定的key查找该key对应的value值的能力,某种意义而言,逻辑数据模型中的key只是用来实现分发计算用的,所以使用kafka查找数据只能以指定消息的偏移量的放松实现。

整个查找过程:当要查找offset=888及后续的消息时,kafka先到该节点上找到对应的Segment。通过该Segment的index文件上用二分查找的方法找到最接近offset=888的纪录,比如886,然后找到886对应的物理磁盘偏移量999,这样就从log的磁盘偏移量找起,连续遍历了两个消息后就能找到888这个消息的数据(log文件中保留了每条消息的逻辑偏移量,长度和数据)。

Kafka的持久化策略设计:

Kafka的持久化设计是非常有特色的,和其他分布式系统不同,它没有自己维护一套缓存机制,而是直接使用了操作系统的文件系统(操作系统的文件系统自带pagecache)。这样的好处是减少了一次内存拷贝的消耗。其他分布式系统比如cassandra,自己在服务端维护了一份数据缓冲内存块datacache,当需要持久化时再调用操作系统的文件系统写入到文件中,这样就多了一次datacache到pagecache的拷贝消耗。这样的话,kafka的持久化管理关键是管理文件系统的pagecache的刷盘。

由于kafka采用了这种特别的持久化策略,所以在kafka中并没有其他分布式系统的重做日志。所以kafka在出现故障后的数据恢复策略有自己的一套:首先,kafka会通过配置文件配置pagecache定时或者定量刷盘的频率以保证即使出现故障也能把丢失的数据降低到最少。其次,pageche本身是操作系统管理维护的,跟kafka自身的服务进程没有关系,如果是kafka本身挂了的话,重启后还是能访问到pageche中的数据的。最后如果很不幸是kafka所在的一个节点的主机挂掉的话,那么重启主机和kafka后也可以从其他备份节点重新同步丢失的数据。

Kafka高性能的和持久化策略关系非常密切,这部分内容,也是整个kafka设计的精髓所在:

传统的观念认为磁盘的读写是非常低效的,所以一般系统都会自己管理一块内存datacache充当磁盘的缓存,只有需要的时候才去和磁盘交互。但是实际上,磁盘的低效的原因不在于磁盘io,而在于磁头的随机寻址。如果数据是顺序读写的话(也就是一次磁头寻址,连续io),其实速度是非常快的((Raid-5,7200rpm):顺序 I/O: 600MB/s)。而在传统的设计中虽然加入了内存作为缓存,但是为了保证数据的安全性还是得提供一份重做日志(每次的修改操作都要记录在重做日志redo.log中,以保证内存丢失后能根据重做日志进行恢复),并且当datacache里面的数据达到一定容量时刷新到磁盘的data文件中。但是kafka并没有使用这套常规设计,并没有自己维护一套datacache而是另辟蹊径,直接使用操作系统中的文件系统,并利用文件系统原有的pagecache作为数据缓存。减少了datacache到pagecache的拷贝消耗。并且顺序地进行磁盘io,这样大大提高了kafka写数据时持久化的效率。对于kafka的读数据这块,kafka也使用了Sendfile技术来提高读的效率,传统的读方案是读取磁盘的数据到pagecache中,然后从pagecache拷贝一份到用户进程的datacache中,datacache再拷贝到内核的socket缓存区中,最后从socket缓存区拷贝数据到网卡中发送。而Sendfile技术跳过了用户进程的datacache这一环节,直接读取磁盘的数据到pagecache中,然后从pagecache拷贝一份到socket缓存区中,最后从socket缓存区拷贝数据到网卡中发送。整个过程减少了两次拷贝消耗。

Kafka的节点间的数据一致性策略设计:

对于任何多节点多备份的分布式系统而言,数据的一致性问题都是绕不开的难点,一般的选择是要么优先考虑效率,这样可能就造成数据不一致甚至是数据丢失,要么选择保障数据一致性和数据安全性牺牲效率。在kafka的身上也存在这样的矛盾。

Kafka是一种分partion,多节点多备份的分布式系统,每个partion都可以存在多份备份,每个备份在不同的节点上。多个备份中会根据zookpeer的注册信息通过算法选举出其中一份作为leader,这个leader负责和客户端的读写访问进行交互。其他备份不参与跟客户端的交互。而是去跟leader partion交互同步数据。这样一来就可能出现主备之间数据不一致的情况。Kafka在客户端提供了一个配置选项props.put("acks", "all");--其中all表示生产者等待确认所有的备份数据都写入pagecache后再返回。可以设置为0(不等待任何确认),1(leader确认)或者其他小于备份数的数字。其他备份节点会异步去同步leader partion的数据,保持一致,当然如果在同步的过程中,leader partion出现数据丢失,那么这部分数据将永远丢失。

Kafka的备份和负载均衡:

Kafka的备份很明显,上文已经说过是通过讨论一致性问题已经交待清楚,至于Kafka的负载均衡,个人发现是严重依赖于zookeeper上的注册信息,通过一套算法来选取leader partion来实现kafka多节点的负载均衡。Zookeeper中保存了kafka几乎一切的重要信息,比如topic,每个topic下面的多个partion信息,主机节点信息(包括ip和端口),每个节点下的多个partion信息,每个partion的主备份信息,消费客户端的group_id分组信息,每个消费者信息等。通过这一堆信息进行算法计算最后得出负载均衡的方案,主要体现是选出让kafka效率性能达到最好的每个partion的leader。并且在zookeeper中注册监视器,一旦发现上述信息有变动则更新负载均衡方案。

Kafka消息队列原理总结相关推荐

  1. 基于 Kafka 和 ZooKeeper 的分布式消息队列原理

    转载:https://gitbook.cn/books/5bc446269a9adf54c7ccb8bc/index.html 消息队列中间件是分布式系统中重要的组件,主要解决应用耦合,异步消息,流量 ...

  2. 再谈基于 Kafka 和 ZooKeeper 的分布式消息队列原理

    关于分布式消息队列,我在几个月前写过一篇文章:<深入浅出理解基于 Kafka 和 ZooKeeper 的分布式消息队列 >.最近,由于写作课程<分布式中间件实践之路>的契机,我 ...

  3. Kafka(消息队列原理,kafka定义,Kafka架构原理,kafka架构的工作流程)秒懂的kafka

    目录 什么是Kafka? 消息队列原理: 为什么要用Kafka? kafka的架构 kafka工作流程详解: 什么是Kafka? kafka是一个分布式消息队列 这个定义意味深长,记住容易,理解不易. ...

  4. 使用kafka消息队列中间件实现跨进程,跨服务器的高并发消息通讯

    作者 | 陈屹       责编 | 欧阳姝黎 近来工作上接收到一项任务,实现c++后台服务器程序,要求它能承载千万级别的DAU读写请求.目前实现千万级高并发海量数据请求的服务器设计在"套路 ...

  5. kafka 消息队列

    kafka 消息队列 kafka 架构原理 大数据时代来临,如果你还不知道Kafka那就真的out了!据统计,有三分之一的世界财富500强企业正在使用Kafka,包括所有TOP10旅游公司,7家TOP ...

  6. SpringBoot集成Kafka消息队列

    1.说明 Spring可以方便的集成使用 Kafka消息队列 , 只需要引入依赖包spring-kafka, 注意版本兼容问题, 本文详细介绍SpringBoot集成Kafka的方法, 以及生产者和消 ...

  7. kafka消息队列的概念理解

    kafka在大数据.分布式架构中都很流行.kafka可以进行流式计算,也可以做为日志系统,还可以用于消息队列. kafka作为消息队列的优点: 分布式的系统 高吞吐量.即使存储了许多TB的消息,它也保 ...

  8. 19 kafka消息队列

    文章目录 19 kafka消息队列 一.kafka介绍 1.消息队列基本介绍 2.常用的消息队列介绍 3.消息队列的应用场景 4.消息队列的两种模式 5.kafka的基本介绍 6.kafka的架构介绍 ...

  9. Java+Kafka消息队列

    本文主要针对,Java端对Kafka消息队列的生产和消费.Kafka的安装部署,请看查看相关文章. 笔者最近所用的是Spring mvc,监听文件路径,然后将读取到的文件内容发送到消息队列中.由另外系 ...

  10. kafka消息队列应用总结

    kafka官网: Apache Kafka 公司使用阿里云提供的kafka消息队列服务,分别为测试环境与生产环境,部署了多个集群. 使用场景:应用对外提供API接口调用,同时支持kafka增量消息推送 ...

最新文章

  1. 如何成为一名优秀CTO
  2. java反射原理三种,Java反射的原理,作用
  3. Redis与Memcache的对比
  4. 多项式拟合缺点_曲线拟合方法的选择
  5. C++学习之路 | PTA乙级—— 1078 字符串压缩与解压 (20 分)(精简)
  6. 浅谈OpenGL、OpenGL ES
  7. es基于completion suggest实现搜索提示
  8. 北大计算机科学与技术怎么样,国内高校计算机科学与技术学科排名,浙大表现亮眼,北大荣登榜首...
  9. IOS第12天(3,UIViewController的生命周期)
  10. 程序员如何面对自己三十岁后的下坡路?
  11. python 日期减一天_怎么用Python在指定日期上减去7天?
  12. httpd-2.2部署Discuz!论坛系统、wordpress博客系统和phpMyAdmin程序
  13. [禅悟人生]不自律的品性如堕落的瓷瓶
  14. 【元胞自动机】基于matlab元胞自动机收费站交通问题【含Matlab源码 357期】
  15. Android 11.0 12.0修改搜狗为默认输入法,并且授予运行权限
  16. 2022年Github学生包白嫖!
  17. 产品经理如何开好需求评审会
  18. springboot使用Cassandra组合查询数据
  19. IDEA+SpringBoot+Vue
  20. PW4203降压型1-3节锂电池充电芯片

热门文章

  1. 零基础学Java,最开始应该学什么?
  2. H5 页面在 APP 里如何支持缩放,并隐藏手机自带的放大缩小图标。
  3. 根据车辆型号自动生成车辆编号
  4. java 字符串练习(罗马数字的转换)
  5. html 字怎么居中怎么写,html文字居中代码怎么写
  6. 单片机实验中用到的元器件(Multisim14)
  7. TSP问题详解(旅行商问题)
  8. shiro+springMVC文档
  9. 【MOOC测试】数学模型
  10. vs2015安装+下载详细教程