- 👏作者简介:大家好,我是爱吃芝士的土豆倪,24届校招生Java选手,很高兴认识大家
- 📕系列专栏:Spring源码、JUC源码、Kafka原理
- 🔥如果感觉博主的文章还不错的话,请👍三连支持👍一下博主哦
- 🍂博主正在努力完成2023计划中:源码溯源,一探究竟
- 📝联系方式:nhs19990716,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬👀
文章目录
- 基本概念
- 什么是kafka?
- kafka的特点
- kafka 系统的架构
基本概念
什么是kafka?
Kafka 最初是由 LinkedIn 即领英公司基于 Scala 和 Java 语言开发的分布式消息发布-订阅系统,现
已捐献给 Apache 软件基金会。其具有高吞吐、低延迟的特性,许多大数据实时流式处理系统比如
Storm、Spark、Flink 等都能很好地与之集成。
kafka简单的说就是一个消息系统,类似的有rabbitmq等,但是kafka不能严格的称之为消息队列,只能说是消息中间件。
下面简述消息队列,是一个数据的存储 和 中转系统吧。
队列的特点,先进先出。
在javaee中,消息队列的场景非常的多。
比如秒杀,或者站内消息等,都是借助消息队列来实现的。类似的消息队列有很多,如ActiveMQ、RabbitMQ、RocketMQ。各有特点,但是总体上来说,功能和应用都是一样的。
第一个是数据的先进先出,第二个就是数据的严格有序(不是按照大小严格有序,是按照数据写入的时间)
实时流式计算:
有一个数据源,实时源源不断的产生数据,然后我们要用一个计算系统去源源不断的处理这个数据,但是如果要让计算系统去对接数据源会产生一点问题。
1.这两个系统必然形成一个耦合
比如计算系统去调用这个数据源的方法,去拿到这个数据,这是一种方案,去源源不断的去拿,这就是一种耦合,那么就会出现一个问题,将来计算系统要升级,那么计算系统 和 数据源的对接可能就失效了,或者数据源要升级也一样。
2.速度不匹配
数据源产生数据的速度是由数据源里面的属性特性去决定的,加入数据源产生的是用户的行为日志,那么行为日志显然就跟此时此刻公司的业务系统上面在线的用户数量以及用户的活跃程度有关。
app用户不是固定的,那么就会导致用户行为日志是会不断地变化的。也就是产生数据的速度 和 规模,是不可预期的。但是数据计算处理的速度是恒定的,确切的是速度上限是有限的,因为计算的资源有限,配备的计算系统的硬件的配置、节点的数量都是一个固定的,所以导致处理数据的上限是恒定的。而一旦数据源在某一个瞬间产生数据的速度超越了处理数据的上限,那么这两个之间就一定会出问题,因为这两个是耦合在一起的,一个慢了或者快了都会对双方造成影响,那么速度不匹配就会造成数据丢失、app用户发送日志阻塞等等,这样就完全不能适应我们生产上的需求了。
那么应该怎么做呢?比如说在这中间加入一个缓存。缓存还可以容纳一定容量的数据。
那么也就是数据源先存入缓存系统中,然后数据计算从缓存系统中取出去计算。
如果数据源产生数据的速度,比计算速度慢,那么产生过来的数据会及时的第一时间的被消费过去,那么在缓存中是没有数据的积压的,只是当作一个简单的中转。也就是将两个系统(数据源、数据计算)解耦。
可是一旦,数据源在某段时间产生速度的速率超过了计算的速率,那么也不至于像前面一样产生不可阻挡的问题,数据源依然可以正常的消费数据,数据计算依然的可以正常的去计算。只不过速度不一致,会在缓存系统中存在积压。但是只要累计的量不超过缓存系统总的存储量,那么这个系统还是能正常的工作。
缓存系统的要求:
- 吞吐量要大
- 读写要快
- 轻量级(轻量级 和 吞吐量、读写速度成反比,不需要做额外的操作)
能够一想到的就是redis,但是redis的存储量小,而且很难控制数据的读写顺序,不能保证读写顺序的一致性。
实时计算中,基本计算模式是,数据源持续不断生成数据,计算系统持续不断处理数据(也就代表着数据源写入数据的顺序,要与计算系统读取数据的顺序保持一致)
(其它消息队列的缺点,对比kafka — 吞吐量)
kafka 为什么不直接叫做一个消息队列呢?
因为kafka是一个分布式的,必然会导致数据读写顺序的一个不完美。
数据写在kafka不是写在单机上,而是写在很多机器上,那么消费者去读的时候,无法保证读的顺序和写入的顺序是严格一致的。无法百分百确保数据读写的先后顺序是严格一致的。但是可以保证分区内的数据读写一致。
在有些计算中,要保证全局的一致性是必须的选项,但是很多时候并不需要你的读写顺序完全一致。
如果真的要保证全局的一致的话,那么kafka有满足不了你的要求了。
主要要分数据类型,绝大多数任务都是统计,所以对数据的顺序一致性没那么关注。
换句话说,当需要绝对顺序一致性的情况,不需要考虑kafka。
如果非要保证绝对顺序一致性,那就将分布式的系统,退化成一个单机系统。把数据的分区数设置为1。
而一旦这样退化,还不如用RabbitMQ、RocketMQ呢(术业有专攻)
总的来讲,Kafka 通常具有 3 重角色:
**存储系统: **通常消息队列会把消息持久化到磁盘,防止消息丢失,保证消息可靠性。Kafka 的消息持久化机制和多副本机制使其能够作为通用数据存储系统来使用。
消息系统: Kafka 和传统的消息队列比如 RabbitMQ、RocketMQ、ActiveMQ 类似,支持流量削锋、服务解耦、异步通信等核心功能。
流处理平台: Kafka 不仅能够与大多数流式计算框架完美整合,并且自身也提供了一个完整的流式处理库,即 Kafka Streaming。Kafka Streaming 提供了类似 Flink 中的窗口、聚合、变换、连接等功能。
一句话概括:Kafka 是一个分布式的基于发布/订阅模式的消息中间件,在业界主要应用于大数据实时流式计算领域,起缓冲和削峰填谷的作用。
kafka的特点
**高吞吐量、低延迟: **kafka 每秒可以处理几十万条消息,它的延迟最低只有几毫秒,每个 topic 可以分多个 partition, 由多个 consumer group 对 partition
可扩展性: kafka 集群支持热扩展(系统部署上去了,将来发现数据源产生的速度已经超越了你之前部署的kafka所能容纳的最大的缓存量,这个时候还不想把整个系统停掉,那就在线扩容。)
大数据系统可以进行热扩容,加机器就好了。
但是像mysql,是不能动态的进行热扩容的,比如之前只有一台MySQL,发现不够,需要先停掉,修改配置,还需要进行分库分表,此时服务器1 和 服务器2互相不知道。需要上层的应用代码自己去搞定要查的数据在哪一个服务器,自己去路由选择查那个服务器。一旦这么写死了,将来又要扩容了,那么就会比较麻烦一点。
所以mysql本身是不能够去扩容的,一切都要人工去操作。人工分库分表放在不同的服务器上。很难去实现动态扩容。
而大数据设计出来就是分布式的
比如HBase里面,加机器后,将配置文件同步好,从节点会自动通知master,然后master会去做负载均衡,然后自己去做region的迁移,而且发生的变化对于上层的应用来说是完全无感的。数据在那个机器上不需要人工去做任何的调整,内部都会自动去协调。
持久性、可靠性: 消息被持久化到本地磁盘,并且支持数据备份防止数据丢失
容错性: 允许集群中有节点失败 (本质上就是会生成很多的task,如果task失败,允许重试)(若副本数量为 n,则允许 n-1 个节点失败)
高并发: 支持数千个客户端同时读写
kafka 系统的架构
首先kafka是用来存数据的,现实世界有数据分类,所以存储系统也应该有数据分类管理功能,如mysql的表、kafka有topic。如一个topic的数据全部交给一台Server存储和管理,则读写吞吐量有限,所以,一个 topic 的数据应该可以分成多个部分(partition)分别交给多台 server 存储和管理。如一台 server 宕机,这台 server 负责的 partition 将不可用,所以,一个 partition应该有多个副本(可以支撑高的数据吞吐量和数据的高可靠性。
比如说有一堆的生产者 和 消费者去读取topic,如果你的topic都在一台机器上,那么显然吞吐量不够,所以分割了很多的partition,放在不同的机器上,这样大量的生产者 和 消费者就可以去选择读取那个 partition,当你们读的是不同的partition的时候,相当于并行度就提高了。)
但是一个 partition 有多个副本,则副本间的数据一致性难以保证,因此要有一个 leader 统领读写,一个 leader 万一挂掉,则该 partition 又不可用,因此还要有 leader 的动态选举机制。
集群有哪些 topic,topic 有哪几个分区,server 在线情况,等等元信息和状态信息需要在集群内部及客户端之间共享,则引入了 zookeeper。
客户端在读取数据时,往往需要知道自己所读取到的位置,因而要引入消息偏移量维护机制。