Kafka

117 阅读10分钟

zhuanlan.zhihu.com/p/446774729

1、为什么有消息系统

  1. 解耦合

  2. 异步处理 例如电商平台,秒杀活动。一般流程会分为:1: 风险控制 、2: 库存锁定 、3: 生成订单 、4: 短信通知 、5: 更新数据

  3. 通过消息系统将秒杀活动业务拆分开,将不急需处理的业务放在后面慢慢处理;流程改为:1: 风险控制 、2: 库存锁定 、3: 消息系统 、4: 生成订单 、5: 短信通知 、6: 更新数据

  4. 流量的控制 :1. 网关在接受到请求后,就把请求放入到消息队列里面 2.后端的服务从消息队列里面获取到请求,完成后续的秒杀处理流程。然后再给用户返回结果。优点:控制了流量 缺点:会让流程变慢

2、Kafka核心概念

生产者:Producer 往Kafka集群生成数据

消费者:Consumer 往Kafka里面去获取数据,处理数据、消费数据 Kafka的数据是由消费者自己去拉去Kafka里面的数据

主题:topic

分区:partition 默认一个topic有一个分区(partition),自己可设置多个分区(分区分散存储在服务器不同节点上)

3、Kafka的集群架构

Kafka集群中,一个kafka服务器就是一个broker,Topic只是逻辑上的概念,partition在磁盘上就体现为一个目录。

Consumer Group:消费组 消费数据的时候,都必须指定一个group id,指定一个组的id假定程序A和程序B指定的group id号一样,那么两个程序就属于同一个消费组。

特殊: 比如,有一个主题topicA程序A去消费了这个topicA,那么程序B就不能再去消费topicA(程序A和程序B属于一个消费组);再比如程序A已经消费了topicA里面的数据,现在还是重新再次消费topicA的数据,是不可以的,但是重新指定一个group id号以后,可以消费。不同消费组之间没有影响,消费组需自定义,消费者名称程序自动生成(独一无二)。

Controller:Kafka节点里面的一个主节点,借助zookeeper。

d972697d1d68372e83087c8fcb2288a7.png

4、Kafka磁盘顺序写保证写数据性能

kafka写数据:  顺序写,往磁盘上写数据时,就是追加数据,没有随机写的操作。 经验 : 如果一个服务器磁盘达到一定的个数,磁盘也达到一定转数,往磁盘里面顺序写(追加写)数据的速度和写内存的速度差不多 生产者生产消息,经过kafka服务先写到os cache 内存中,然后经过sync顺序写到磁盘上。

5、Kafka零拷贝机制保证读数据高性能

消费者读取数据流程:

  1. 消费者发送请求给kafka服务
  2. kafka服务去os cache缓存读取数据(缓存没有就去磁盘读取数据)
  3. 从磁盘读取了数据到os cache缓存中
  4. os cache复制数据到kafka应用程序中
  5. kafka将数据(复制)发送到socket cache中
  6. socket cache通过网卡传输给消费者

kafka linux sendfile技术 — 零拷贝

1.消费者发送请求给kafka服务 2.kafka服务去os cache缓存读取数据(缓存没有就去磁盘读取数据) 3.从磁盘读取了数据到os cache缓存中 4.os cache直接将数据发送给网卡 5.通过网卡将数据传输给消费者

6、Kafka日志分段

Kafka中一个主题,一般会设置分区;比如创建了一个 topic_a ,然后创建的时候指定了这个主题有三个分区。 其实在三台服务器上,会创建三个目录。 服务器1(kafka1)创建目录topic_a-0:。目录下面是我们文件(存储数据),kafka数据就是message,数据存储在log文件里。.log结尾的就是日志文件,在kafka中把数据文件就叫做日志文件 。 一个分区下面默认有n多个日志文件(分段存储),一个日志文件默认1G 。

image.png

9、Kafka分区、冗余副本保证高可用

在kafka里面分区为了水平扩展,提高吞吐,分区是有副本的,注: 0.8以前是没有副本机制的 。创建主题时,可以指定分区,也可以指定副本个数。副本是有角色的:

  • leader partition:
  1. 写数据、读数据操作都是从leader partition去操作的。
  2. 会维护一个ISR(in-sync- replica )列表,但是会根据一定的规则删除ISR列表里面的值 生产者发送来一个消息,消息首先要写入到leader partition中 写完了以后,还要把消息写入到ISR列表里面的其它分区,写完后才算这个消息提交
  • follower partition:从leader partition同步数据。

分区 分区.png

副本 副本.png

10、优秀架构思考-总结

Kafka — 高并发、高可用、高性能 高可用:多副本机制 高并发:网络架构设计 三层架构:多selector -> 多线程 -> 队列的设计(NIO) 高性能:写数据:

  1. 把数据先写入到OS Cache
  2. 写到磁盘上面是顺序写,性能很高

读数据:

  1. 根据稀疏索引,快速定位到要消费的数据
  2. 零拷贝机制 减少数据的拷贝 减少了应用程序与操作系统上下文切换

11、Kafka生产环境搭建

11.1 需求场景分析

电商平台,需要每天10亿请求都要发送到Kafka集群上面。二八反正,一般评估出来问题都不大。10亿请求 -> 24 过来的,一般情况下,每天的12:00 到早上8:00 这段时间其实是没有多大的数据量的。80%的请求是用的另外16小时的处理的。16个小时处理 -> 8亿的请求。16 * 0.2 = 3个小时 处理了8亿请求的80%的数据

也就是说6亿的数据是靠3个小时处理完的。我们简单的算一下高峰期时候的qps 6亿/3小时 =5.5万/s qps=5.5万

10亿请求 * 50kb = 46T 每天需要存储46T的数据

一般情况下,我们都会设置两个副本 46T * 2 = 92T Kafka里面的数据是有保留的时间周期,保留最近 3 天的数据。 92T * 3天 = 276T 我这儿说的是50kb不是说一条消息就是50kb不是(把日志合并了,多条日志合并在一起),通常情况下,一条消息就几b,也有可能就是几百字节。

11.2 物理机数量评估

1)首先分析一下是需要虚拟机还是物理机 像Kafka mysql hadoop这些集群搭建的时候,我们生产里面都是使用物理机。2)高峰期需要处理的请求总的请求每秒5.5万个,其实一两台物理机绝对是可以抗住的。一般情况下,我们评估机器的时候,是按照高峰期的4倍的去评估。如果是4倍的话,大概我们集群的能力要准备到 20万qps。这样子的集群才是比较安全的集群。大概就需要5台物理机。每台承受4万请求。

场景总结: 搞定10亿请求,高峰期5.5万的qps,276T的数据,需要5台物理机。

11.3 磁盘选择

搞定10亿请求,高峰期5.5万的qps,276T的数据,需要5台物理机。1)SSD固态硬盘,还是需要普通的机械硬盘 SSD硬盘:性能比较好,但是价格贵 SAS盘:某方面性能不是很好,但是比较便宜。SSD硬盘性能比较好,指的是它随机读写的性能比较好。适合MySQL这样集群。 但是其实他的顺序写的性能跟SAS盘差不多。kafka的理解:就是用的顺序写。所以我们就用普通的【 机械硬盘 】就可以了。

2)需要我们评估每台服务器需要多少块磁盘 5台服务器,一共需要276T ,大约每台服务器 需要存储60T的数据。我们公司里面服务器的配置用的是 11块硬盘,每个硬盘 7T。11 * 7T = 77T

77T * 5 台服务器 = 385T。

场景总结:

搞定10亿请求,需要5台物理机,11(SAS) * 7T

11.4 内存评估

搞定10亿请求,需要5台物理机,11(SAS) * 7T

我们发现kafka读写数据的流程 都是基于os cache,换句话说假设咱们的os cashe无限大那么整个kafka是不是相当于就是基于内存去操作,如果是基于内存去操作,性能肯定很好。内存是有限的。1) 尽可能多的内存资源要给 os cache 2) Kafka的代码用 核心的代码用的是scala写的,客户端的代码java写的。都是基于jvm。所以我们还要给一部分的内存给jvm。Kafka的设计,没有把很多数据结构都放在jvm里面。所以我们的这个jvm不需要太大的内存。 根据经验,给个10G就可以了 。

NameNode: jvm里面还放了元数据(几十G),JVM一定要给得很大。比如给个100G。

假设我们这个10请求的这个项目,一共会有100个topic。100 topic * 5 partition * 2 = 1000 partition 一个partition其实就是物理机上面的一个目录,这个目录下面会有很多个.log的文件。.log就是存储数据文件,默认情况下一个.log文件的大小是1G。我们如果要保证 1000个partition 的最新的.log 文件的数据 如果都在内存里面,这个时候性能就是最好。1000 * 1G = 1000G内存. 我们只需要把当前最新的这个log 保证里面的25%的最新的数据在内存里面。250M * 1000 = 0.25 G* 1000 =250G的内存。

250内存 / 5 = 50G内存 50G+10G = 60G内存

64G的内存,另外的4G,操作系统本身是不是也需要内存。其实Kafka的jvm也可以不用给到10G这么多。评估出来64G是可以的。当然如果能给到128G的内存的服务器,那就最好。

我刚刚评估的时候用的都是一个topic是5个partition,但是如果是数据量比较大的topic,可能会有10个partition。

总结: 搞定10亿请求,需要5台物理机,11(SAS) * 7T ,需要64G的内存(128G更好)

11.5 CPU压力评估

评估一下每台服务器需要多少cpu core(资源很有限)

我们评估需要多少个cpu ,依据就是看我们的服务里面有多少线程去跑。线程就是依托cpu 去运行的。如果我们的线程比较多,但是cpu core比较少,这样的话,我们的机器负载就会很高,性能不就不好。

评估一下,kafka的一台服务器 启动以后会有多少线程?

Acceptor线程 1 processor线程 3 6~9个线程 处理请求线程 8个 32个线程 定时清理的线程,拉取数据的线程,定时检查ISR列表的机制 等等。所以大概一个Kafka的服务启动起来以后,会有一百多个线程。

cpu core = 4个,一般来说,几十个线程,就肯定把cpu 打满了。cpu core = 8个,应该很轻松地能支持几十个线程。如果我们的线程是100多个,或者差不多200个,那么8 个 cpu core是搞不定的。所以我们这儿建议:CPU core = 16个。如果可以的话,能有32个cpu core 那就最好。

结论:kafka集群,最低也要给16个cpu core,如果能给到32 cpu core那就更好。2cpu * 8 =16 cpu core 4cpu * 8 = 32 cpu core

总结: 搞定10亿请求,需要5台物理机,11(SAS) * 7T ,需要64G的内存(128G更好),需要16个cpu core(32个更好)