关于Kafka

Kafka 是⼀种⾼吞吐量、分布式、基于发布/订阅的消息系统,最初由 LinkedIn 公司开 发,使⽤ Scala 语⾔编写,⽬前是 Apache 的开源项⽬。broker:Kafka 服务器,负责消息 存储和转发 topic:消息类别, Kafka 按照 topic 来分类消息 partition:topic 的分区,⼀ 个 topic 可以包含多个 partition, topic 消息保存在各个 partition 上 offset:消息在⽇志 中的位置,可以理解是消息在 partition 上的偏移量,也是代表该消息的唯⼀序号 Producer:消息⽣产者 Consumer:消息消费者 Consumer Group:消费者分组,每个 Consumer 必须属于⼀个 groupZookeeper:保存着集群 broker、 topic、 partition 等 meta 数据;另外,还负责 broker 故障发现, partition leader 选举,负载均衡等功能
为什么要使⽤ kafka?为什么要使⽤消息队列?
缓冲和削峰 :上游数据时有突发流量,下游可能扛不住,或者下游没有⾜够多的机器来保 证冗余,kafka 在中间可以起到⼀个缓冲的作⽤,把消息暂存在 kafka 中,下游服务就可以 按照⾃⼰的节奏进⾏慢慢处理。
解耦和扩展性 :项⽬开始的时候,并不能确定具体需求。消息队列可以作为⼀个接⼝层, 解耦重要的业务流程。只需要遵守约定,针对数据编程即可获取扩展能⼒。冗余 :可以采 ⽤⼀对多的⽅式,⼀个⽣产者发布消息,可以被多个订阅 topic 的服务消费到,供多个毫⽆ 关联的业务使⽤。健壮性 :消息队列可以堆积请求,所以消费端业务即使短时间死掉,也 不会影响主要业务的正常进⾏。异步通信 :很多时候,⽤户不想也不需要⽴即处理消息。 消息队列提供了异步处理机制,允许⽤户把⼀个消息放⼊队列,但并不⽴即处理它。想向 队列中放⼊多少消息就放多少,然后在需要的时候再去处理它们。
数据传输的事物定义有三种:
数据传输的事务定义通常有以下三种级别:( 1)最多⼀次: 消息不会被重复发送,最多 被传输⼀次,但也有可能⼀次不传输 ( 2)最少⼀次: 消息不会被漏发送,最少被传输⼀ 次,但也有可能被重复传输. ( 3)精确的⼀次( Exactly once) : 不会漏传输也不会重复 传输,每个消息都传输被⼀次⽽且仅仅被传输⼀次,这是⼤家所期望的
Kafka 中的 ISR、AR 、ISR :
ISR:In-Sync Replicas 副本同步队列 AR:Assigned Replicas 所有副本 ISR 是由 leader 维护,follower 从 leader 同步数据有⼀些延 迟(包括延迟时间 replica.lag.time.max.ms 和延迟条数 replica.lag.max.messages 两个维度, 当前最新的版本 0.10.x 中只⽀持 replica.lag.time.max.ms 这个维度),任意⼀个超过阈值都 会把 follower 剔除出 ISR, 存⼊ OSR(Outof-Sync Replicas)列表,新加⼊的 follower 也会先 存放在 OSR 中。AR=ISR+OSR。
Kafka 消息是采⽤什么模式:Kafka 最初考虑的问题是, customer 应该从 brokes 拉取消息还是 brokers 将消息推送到 consumer,也就是 pull 还 push。在这⽅⾯, Kafka 遵循了⼀种⼤部分消息系统共同的传 统的设计:producer 将消息推送到 broker,consumer从 broker 拉取消息 ⼀些消息系 统⽐如Scribe和Apache Flume采⽤了 push模式,将消息推送到下游的consumer。这样做有好处也有坏处:由 broker 决定消息推送的速率,对于不同消费速率的 consumer 就不太好处理了。消息系统都致⼒于让 consumer 以最⼤的速率最快速的消费消息,但不幸的是, push 模式下,当 broker 推送的速率远⼤于 consumer 消费的速率时,consumer恐怕就要崩溃了。
最终 Kafka 还是选取了传统的pull模式Pull模式的另外⼀个好处是consumer可以⾃主决定是否批量的从 broker 拉取数据。Push 模式必须在不知道下游 consumer 消费能⼒和消费策略的情况下决定是⽴即推送每条消息还是缓存之后批量推送。如果为了避免 consumer 崩溃⽽采⽤较低的推送速率,将可能导致⼀次只推送较少的消息 ⽽造成浪费。Pull 模式下, consumer 就可以根据⾃⼰的消费能⼒去决定这些策略 Pull 有 个缺点是,如果 broker 没有可供消费的消息,将导致 consumer 不断在循环中轮询,直 到新消息到 t 达。为了避免这点, Kafka 有个参数可以让 consumer 阻塞知道新消息到达(当然也可以阻塞知道消息的数量达到某个特定的量这样就可以批量发)。
partition 的数据如何保存到硬盘:topic 中的多个 partition 以⽂件夹的形式保存到 broker,每个分区序号从 0 递增,且消 息有序 Partition ⽂件下有多个 segment( xxx.index, xxx.log) segment ⽂件⾥的 ⼤⼩ 和配置⽂件⼤⼩⼀致可以根据要求修改 默认为 1g 如果⼤⼩⼤于 1g 时,会滚动⼀个新的 segment 并且以上⼀个 segment 最后⼀条消息的偏移量命名
kafka 维护消费状态跟踪的⽅法:⼤部分消息系统在 broker 端的维护消息被消费的记录:⼀个消息被分发到 consumer 后 broker 就⻢上进⾏标记或者等待 customer 的通知后进⾏标记。这样也可以在消息在消费 后⽴⻢就删除以减少空间占⽤。但是这样会不会有什么问题呢?如果⼀条消息发送出去之 后就⽴即被标记为消费过的, ⼀旦 consumer 处理消息时失败了(⽐如程序崩溃)消息就 丢失了。为了解决这个问题, 很多消息系统提供了另外⼀个个功能:当消息被发送出去之 后仅仅被标记为已发送状态,当接到 consumer 已经消费成功的通知后才标记为已被消费的状态。这虽然解决了消息丢失的问题,但产⽣了新问题,⾸先如果 consumer 处理消息 成功了但是向 broker 发送响应时失败了,这条消息将被消费两次。第⼆个问题时,broker 必须维护每条消息的状态,并且每次都要先锁住消息然后更改状态然后释放锁。这样麻烦 ⼜来了,且不说要维护⼤量的状态数据,⽐如如果消息发送出去但没有收到消费成功的通 知,这条消息将⼀直处于被锁定的状态,Kafka 采⽤了不同的策略。Topic 被分成了若⼲分 区,每个分区在同⼀时间只被⼀个 consumer 消费。这意味着每个分区被消费的消息在⽇ 志中的位置仅仅是⼀个简单的整数:offset。这样就很容易标记每个分区消费状态就很容易 了,仅仅需要⼀个整数⽽已。这样消费状态的跟踪就很简单了。这带来了另外⼀个好处: consumer 可以把 offset 调成⼀个较⽼的值,去重新消费⽼的消息。这对传统的消息系统 来说看起来有些不可思议,但确实是⾮常有⽤的,谁规定了⼀条消息只能被消费⼀次呢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值