今天项目中用到了kafka做用户行为的数据埋点,重新熟悉了一下kafka
1. 消息中间件对比
- kafka: 追求高吞吐量,适合产生大量数据的互联网服务的数据收集业务
- RocketMQ: 可靠性要求很高的金融互联网领域,稳定性高,经历了多次阿里双11考验
- RabbitMQ: 数据响应达到微秒级,性能较好,社区活跃度高,数据量没有那么大,优先选择功能比较完备的RabbitMQ
2. kafka是一个高性能跨语言分布式发布/订阅消息队列系统
2.1.1 kafka基本结构
- producer:发布消息的对象称之为主题生产者(Kafka topic producer)
- topic:Kafka将消息分门别类,每一类的消息称之为一个主题(Topic)
- consumer:订阅消息并处理发布的消息的对象称之为主题消费者(consumers)
- broker:已发布的消息保存在一组服务器中,称之为Kafka集群。集群中的每一个服务器都是一个代理(Broker)。 消费者可以订阅一个或多个主题(topic),并从Broker拉数据,从而消费这些已发布的消息。
2.1.2 kafka高可用设计
集群
- Kafka 的服务器端由被称为 Broker 的服务进程构成,即一个 Kafka 集群由多个 Broker 组成
- 这样如果集群中某一台机器宕机,其他机器上的 Broker 也依然能够对外提供服务。这其实就是 Kafka 提供高可用的手段之一
备份机制
- Kafka 中消息的备份又叫做 副本(Replica)
- Kafka 定义了两类副本:
- 领导者副本(Leader Replica)
- 追随者副本(Follower Replica)(分为isr和普通)
- ISR的follower是同步保存领导者数据
- 普通的follower是异步
- leader失效后选举原则
- 第一:选举时优先从ISR中选为这个列表中follower的数据是与leader同步的
- 第二:如果ISR列表中的follower都不行了,就只能从其他follower中选取
- 极端情况,就是所有副本都失效了,这时有两种方案
- 第一:等待ISR中的一个活过来,选为Leader,数据可靠,但活过来的时间不确定
- 第二:选择第一个活过来的Replication,不一定是ISR中的,选为leader,以最快速度恢复可用性,但数据不一定完整
3. 生产者
3.1 发送消息类型
- 同步发送,获取offset偏移量,容易阻塞
- 异步发送指定回调函数。返回offset偏移量
3.2 ack消息确认机制
- ack配置 消息确认机制prop.put(ProducerConfig.ACKS_CONFIG,"all");
- acks=0 : 生产者在成功写入消息之前不会等待任何来自服务器的响应,消息有丢失的风险,但是速度最快
- acks=1: 只要集群首领节点收到消息,生产者就会收到一个来自服务器的成功响应
- acks=all: 只有当所有参与赋值的节点全部收到消息时,生产者才会收到一个来自服务器的成功响应
3.3 retries重试机制
- 重试次数prop.put(ProducerConfig.RETRIES_CONFIG,10);
- 生产者从服务器收到的错误有可能是临时性错误,在这种情况下,retries参数的值决定了生产者可以重发消息的次数,如果达到这个次数,生产者会放弃重试返回错误,默认情况下,生产者会在每次重试之间等待100ms
3.4 消息压缩
- 默认情况下, 消息发送时不会被压缩。 prop.put(ProducerConfig.COMPRESSION_TYPE_CONFIG,"lz4");
- 压缩算法
- snappy:占用较少的 CPU, 却能提供较好的性能和相当可观的压缩比, 如果看重性能和网络带宽,建议采用
- lz4:占用较少的 CPU, 压缩和解压缩速度较快,压缩比也很客观
- gzip:占用较多的 CPU,但会提供更高的压缩比,网络带宽有限,可以使用这种算法
4. 消费者
4.1 消费组
- 消费者组(Consumer Group) :指的就是由一个或多个消费者组成的群体
- 一个发布在Topic上消息被分发给此消费者组中的一个消费者
- 所有的消费者都在一个组中,那么这就变成了queue模型
- 所有的消费者都在不同的组中,那么就完全变成了发布-订阅模型
4.2 消息有序性
topic分区中消息只能由消费者组中的唯一一个消费者处理,所以消息肯定是按照先后顺序进行处理的。但是它也仅仅是保证Topic的一个分区顺序处理,不能保证跨分区的消息先后处理顺序。 所以,如果你想要顺序的处理Topic的所有消息,那就只提供一个分区。
4.3 提交偏移量
- 如果有消费者发生崩溃,或者有新的消费者加入消费者群组的时候,会触发 Kafka 的再均衡。这使得 Kafka 完成再均衡之后,每个消费者可能被会分到新分区中。为了能够继续之前的工作,消费者就需要读取每一个分区的最后一次提交的偏移量,然后从偏移量指定的地方继续处理。
- 如果提交的偏移量小于客户端处理的最后一个消息的偏移量,那么处于两个偏移量之间的消息就会被重复处理。
- 如果提交的偏移量大于客户端处理的最后一个消息的偏移量,那么处于两个偏移量之间的消息将会丢失。
- 自动提交
- 当 enable.auto.commit 属性被设为 true,那么每过 5s,消费者会自动把从 poll()方法接收到的最大偏移量提交上去。
- 容易出现提交的偏移量小于客户端处理的最后一个消息的偏移量这种情况的问题
- 手动提交
- 大部分开发者通过控制偏移量提交时间来消除丢失消息的可能性,并在发生再均衡时减少重复消息的数量。
- 一般采用同步和异步混合提交
- 能解决异步提交失败不会进行重试的缺点