当我们说到Kafka的时候, 总是会想起奥地利作家Kafka和他的小说变形记.同名开源消息中间件(apache kafka其实是一个"distributed streaming data processing plateform")的名字来源于他(我随口一说, 不一定是真的) .
咳, 这是有着深刻的历史原因的.
话说当年Kafka的老爹是个暴力狂, 动不动就是一顿胖揍.有一天我们的作家kafka终于忍无可忍了, 于是给他拿起了刀,思前想后,给他的爹...写了一封长长的信, 写完之后让他的妈转交给其暴力狂老爹.但是他的妈在偷偷的看了这封信之后,觉得不好,顺手将这封信丢在了垃圾桶. 于是其老爹暴力依旧.
于是我们的消息系统也存在这这样的几个问题:
- 冗长: 本来可以当面沟通的, 愣是要写一封信.
- 存在消息丢失的可能: 信丢了.
以上只是一个故事, 如有雷同, 就是真的。
为什么会有消息系统?
说正经事儿.
在我还很小的时候, 2014年, 26岁. 当时在网上买了一个联想的手机(后来发现用起来很差), 快递员给我送货, 在楼下等我, 但是我在上课. 于是他等了我大概30分钟, 才把东西教到我的手中.上课中的我也"知有鸿鹄将至, 思援弓缴而射之", 根本没心上课.
现在有了蜂巢,菜鸟驿站,他不用等了, 我也不会再火急火燎的去取快递.
蜂巢菜鸟驿站,就是一个消息系统.
感受一下消息系统的作用:
没有kakfa:
有了kafka
没有kafka:
有了kafka:
第二张图引起了本人极度的舒适(以上图片均来自网络).
kafka能干啥
上面我们都说kafka是一个消息系统, 但是其官网对自己的定位是:
logo: a distributed streaming plateform, 分布式流处理平台.所以,这里总结一下, Kafka主要由三个作用:
- message system(high through put, 强大的吞吐量).
- streaming processing.
- DB connection and data transmitting.
在这篇笔记中, 我们会依次对以上内容进行讲解.
概念的明确
其实仔细想一想, Kafka其实就像是一个数据库(RDBMS), 往数据库里面写输入, 从数据库里面读取数据.借助我们对于关系型数据库的认识来理解Kafka,你会发现很好理解.
- Broker
- broker就是安装的一个Kafka软件。一般情况下,我们只在一台机器上安装一个软件(微信分身是个特例), 所以, 一只安装在Linux上面, 可以正常运行的Kafka软件, 我们就称之为一个Broker。
- 亦可以称为一个Kafka实例。
- Topic
- 相当于一个RDBMS中的一个DB. 不同点在于RDBMS中,可以存放不同类型(schema)的表。但是Kafka中的topic(特殊的DM)只能存放一个Table。
- SIZE, 太小,太大都不好。当一个DB中的一个表存放的东西过多的时候我们就需要对其进行切分。 Kafka中也有这样一种操作:切分后的小表称之为patition。
- Partition.
- 一个topic由多个partition组成.我有一个数据库PeopleNames,这个数据库就是Topic。这个数据库里面存储着许多的表,分别为叫PeopleName_Part1,PeopleName_Part2,PeopleName_Part3..., 只是, 这些表的Schema都是完全一样的。
- Kafka中存储的数据类型都是:<K V> 类型,同时这个数据会被序列化, 也就不存在RDBMS中schema不同这么一说。
- Replicas:
- 我的这些partition需不需要做个备份?丢了怎么办?毕竟分布我用的这些机器都是commodity level的。Distributed system fail occasionally for sure. 我们会对每个partition进行备份,这些备份称之为Replicas. 起容灾的作用, 这个在分布式系统中是比较常见.
- partition 和replicas在分布式系统中其实都是常用的手段。
- offset: 对应表中的自增主键, 记录了kafka partition 中消息的编号, 从1开始逐渐递增.
- serialization.
- 消息在网络传输的过程中, 必须先序列化, 再传输. 所以Kafka中传输的消息其实就是一个序列化后的字符串.
- message:这里的message也就是要发送的数据.对应RDBMS中的一条记录.但是这里需要记住的几点.
- message没有Schema的概念, kafka不管你发送的数据是什么内容.
- message必须是byte数组. 这也很好理解, 因为需要我网络传输.
- ”人没有办法两次踏进同一条河流“。我的Linux目录下放了一个文件,有一个人给我删了, 然后又做了一个一模一样的给我放回来了, 那么这个文件发生了变化么?我可以检查一下这个文件的时间戳.所以一个message,我们一般也会给它加一个timestamp.
- topic, partition, timestamps, key, value
集群环境配置
这个我就不说了, 相信大家都能够配置好, 哈哈.
消息发送流程的思考
有一个Kafka集群,这个集群首先应该能够存储消息. 其次能够接受消息, 再次能够发送消息.
一个丰巢柜,首先他能够存储物品,其次, 提供一种方法能让我把东西放进去,再次, 还能提供一种方法取出东西.
Kafka对应提供了Producer API, 使用者通过这组API将消息传入Kafka, Broker用来存储消息, Consumer API 供使用者从里面获取消息.
拿到一条消息: "hello, young lady",
- Kafka中所有的消息都是key-value的形式.同时,这条消息是一个字符串, 因为要网络传输, 自然我们要对其进行序列化.
- 序列化之后就可以发送到Broker, 这时候我们要确定发送到哪个Broker?哪个Topic? 哪个partition? 就好比我们往数据库中写入数据的时候必须确定数据库信息, 数据库名称表名称.
- 发送有没有成功?
- 发送成功后就可以被别人(consumer)消费(读取)了, 怎么读取? 你要读哪一个Kafka中的哪一个Topic的哪一个Partition的数据?
- 读取数据. 还要反序列化.
配置文件:
bootstrap
producer API:
public
消息在传输过程中存在的问题:
Throughput and Reliability
往Kafka中发送消息的时候, 如何保证消息不丢失(网络传输常见),如何增大消息的传输速率(大数据处理常见需求)。一般情况下, 以上两个需求是矛盾的,又要马儿跑, 又要马儿不吃草是不可能的。
为了解决以上问题,Kafka对应有如下方案:
- Send and forget: you do not check if a message is successfully send, you just send it,no confirmation.
- Synchronous: you send a message, you send the next one after geting confirmation.
- Asynchronous: better throughput, you don't wait there for the result, you just keep sending the message and check latter when the result comes back or not.
Kafka partitionner
Partitioner
- when a message is serialized, it will next decided to be sent to which partition(the topic has already been designated) to be send, so which partition to send?
- you can specify one in your code.
- provide a key, the default partitioner will send hashcode(key)/partition_num == partition
- do not provide key, the default partitioner will randomly generate a partition to send you message
- you write your own partitioner.
class
Serialization(custom Serializer)
the essence of serialization is to convert the data into byte[], and put them into Stream Object and store into the hard disc.
Byte
Kafak消息的并发读取:
Consumer Group:
- Coordinator** Kafka broker is elected as a coordinator(arrangement of partitions to consumers for consumption)
- manage a list of group members
- initiates a rebalance activity(when such rebalance is happening, all reading of data are blocked).
- Leader**:(the first consumer participated into the group is the leader;
- Executes the rebalance activity.
- sends new partition assignments to the Coordinator.
- Kafka offset
- Current Offset
- Committed Offset(when the consumer finishe processing the message, it will sent the offset number of the message to broker so that when the consumer is closed, the Coordinator will know when to continue to send the message to the next consumer.), Kafka has an auto commit method which will automaticly send the commit offset at certain intervals.
some times when you sent the commit off set at certain intervals , it will be problematic. for instance. the consumer finish processing message 0 to 7 and failed, the mechanism is set such that you commit offset only 10, 20, 30 ..., and therefore, the broker keeps on committed offset 0, when the partition is assigned to another consumer, this consumer will start from offset 0;
To resolve such a problem, need to manually commit the offset, before the rebalancing which consists of two steps:
- Detect the rebalancing process and commit, these can be finished with the APIs provided by Kafka.
其他
- 与zookeeper相关联, zookeeper上面保存元数据信息:broker的状态信息, consumer的消费信息;
- producer[--consumer--kafka(broker, 进程;)存储:ack
- topic--partition--replication(leader follower)
- 发布订阅(topic), 点对点;
- 解耦, 冗余, 扩展性;
- 一个消费组中, 在 某一个时刻,只能有一个消费者消费;
- server: 配置zookeeper.connect, brokerId需要配置; kafka-logs(日志信息目录的配置;) ;设置副本数量;
- producer: 消息往哪里发:bootstrap.servers=xiangbo27:9092(卡夫卡进程占用端口)
- consumer: zookeeper.connect;
- 常用命令
XML start a kafka broker: bin/kafka-server-start.sh config/server.properties bin/kafka-topics.sh --zookeeper xiangbo27:2181 --list
check the properties of a topic:bin/kafka-topics.sh --zookeeper xiangbo29:2181 --describe --topic xiangbo ```
```bash bin/kafka-console-producer.sh --broker-list xiangbo100:9092 --topic xiangbo
bin/kafka-console-consumer.sh --bootstrap-server xiangbo100:9092 --topic recommender ```