Apache Kafka 是一个分布式的流平台,有三个关键的功能:
- 能够发布(写入)和订阅(读取)事件流
- 持续可靠的存储事件流
- 在事件发生时回顾性的处理事件流
事件流: 数据源随着时间变化产生的一系列的动作或者时间被捕获后,形成事件流
服务解耦
微服务场景,服务以来耦合严重场景
流量削峰
潮汐性较大的场景
实时处理
行为分析、日志采集、异常报警
异步、广播、排队
直播课堂、商城等
服务解耦
用户下单购买商品,购买流程,需要先查看库存是否有货,如果有则快递派送,可以利用消息队列进行服务解耦,下的订单发送进消息队列可以使下单这个事件闭环,可以提升下单这个事件的用户体验,配送服务的消费者去订单的队列里消费这个订单的时候,再去进行配送处理即可
流量削峰
用户行为埋点日志上报,用户在网页上触发的行为非常频繁,100W用户同时进行点击,会形成100W qps的log流,后端存储需要应对100w qps的流量冲击,没有用户点击的时候,流量会降低,这样可以引入消息队列,前端上报服务不会因为写库而阻塞,写库的时候可以分批有序写入。消息队列的存在提升了整个系统架构的
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NXJDchPo-1673344693322)(/Users/zsh/Library/Application Support/typora-user-images/image-20230110175322527.png)]
- 如图所示,为一套三个broker的集群
- zookeeper作为分布式一致性服务,kafka通过其进行元数据管理
- topic1有三个分区,每个分区有3个副本,其中broker0/1/2上各有一个分区副本的leader
- topic2 有三个分区,每个分区有3个副本,其中broker0/1/2上各有一个分区副本的leader
- producer-0 向topic1中生产消息,有consumer-group-0 的三个消费者消费,三个消费者消费的数据不重复
- producer-1 向topic2中生产消息,有consumer-group-1 的一个消费者消费
生产者在生产数据的过程 中,是随机将消息写入到一个topic的每一个partition中,每一个partition都存在一个有序的记录序列,如果有新增日志,会按顺序添加至末尾,分配一个ID号,叫偏移量[offset],这个ID在整个partition中具有唯一性。
磁盘顺序读写
写数据是通过不断追加的方式到本地磁盘末尾的,比磁盘随机读写方式性能提升很高
页缓存(os cache)
写数据的时候直接写入 os cache,有操作系统异步的把数据刷入磁盘里,很大的提升写性能
零拷贝(zero-copy)
直接读取内核缓存区的数据发送到网络。没有在用户空间发送拷贝操作,节省了开销,提升了读性能
分区并发
每个topic划分多个partition,每个p中数据有序,同一个consumer group 中不同的consumer 拉取不同p中的数据,增加partition提升增加数据拉取并发能力
稀疏索引
分区中的数据会分段存储在 segment中,默认每4kb新增一个索引,通过二分查找确定数据在文件中的位置,在通过磁盘顺序读找到信息
批量&压缩
Producer 和 consumer 通过 batch 的方式读写数据,且支持lz4、snappy、gzip等多种压缩算法,节省大量的网络和磁盘开销
kafka的topic 由多个partition组成,每个partition中的数据有序且不同,而每个partition是分散在多个broker上的,这样单个topic承载数据的能力,可以通过扩partition的方式来进行扩展,而当集群资源达到上限是,又可以通过扩展broker的方式来扩展集群资源,这样实现了kafka的可扩展性
CAP理论:一个分布式系统最多只能满足**一致性(Consistency)、可用性(Avaliability)、分区容错性(Partition tolerance)**这三项中的两项
一致性
生产者将数据写入kafka topic的不同分区里,每个分区有多个副本,其中读写操作都是由leader来承担,满足了数据一致性
可用性
在kafka的副本机制,每个分区会允许存在多个副本,follower 副本对象leader副本同步数据,当主副本挂掉时重新选举备份副本成为leader提供读写,满足了可用性
分区容错性
由于follower副本异步同步数据,所以kafka不保证分区容错性,但是ISR机制可以尽可能减小分区容错的问题
配置项 | 配置意义 |
---|---|
broker.id | broker的唯一标识符,如果不配置则自动生成,一定要保证集群中必须唯一 |
port | broker server 端口 |
log.dir | 日志数据存放的目录,默认/tmp/kafka-logs |
zookeeper.connect | Zookeeper 主机地址,如果zookeeper是集群则以逗号隔开,如 172.6.14.61:2181,172.6.14.62:2182,172.6.14.63:2181 |
listeners | 监听列表,broker对外提供服务时绑定的ip和端口。多个已逗号隔开,如果监听器名称不是一个安全的协议,listener.security.protocol.map也必须设置 |
advertised.listeners | 给客户端用的发布至zookeeper的监听,broler会上送此地址到zookeeper,zookeeper会将此地址提供给消费者,消费者根据此地址获取消息。如果和上面的listeners不同则以此为准 |
delete.topic.enable | 是否可以删除topic,如果关闭此配置则通过管理工具删除topic则不生效。默认false |
log.retention.hours log.retention.minutes log.retention.ms |
日志删除之前保留的时间,支持不同时间单位 |
num.network.threads | broker用来处理网络请求的线程数,默认3 |
message.max.bytes | kafka可以接受的消息最大尺寸,默认1MB,生产环境一般10MB |
num.partition | 创建topic的默认分区数目 |
auto.create.topics.enable | 是否自动创建topic,默认true |
创建topic
bin/kafka-topic.sh --create --zookeeper x.x.x.x:2181 --replication-factor 1 --partition 1 --topic xxx
查看topic列表
bin/kafka-topic.sh --zookeeper x.x.x.x:2181 --list
查看指定topic信息
bin/kafka-topic.sh --zookeeper x.x.x.x:2181 --describe --topic xxx
控制台向topic生产数据
bin/kafka-console-producer.sh --broker-list x.x.x.x:9092 --topic xxx
控制台消费topic数据
bin/kafka-console-consumer.sh --broker-list x.x.x.x:9092 --topic
删除指定topic
bin/kafka-topic.sh --delete --zookeeper x.x.x.x:2181 --topic xxx
特性 | 可靠性 | 性能 | 实时性 | 顺序性 | 分布式事务 | 消息查询 | 消息回溯 |
---|---|---|---|---|---|---|---|
kafak | 不保证 | 较高 | 较高 | 不保证 | 不支持 | 不支持 | 支持 |
RocketMQ | 保证 | 高 | 较高 | 保证 | 支持 | 支持 | 支持 |
总结
kafka更擅长处理流量较大,吞吐需要较高的场景,由于异步刷新,所以消息是无法保证强可靠性的,对于一些偏业务交互的能力支持也偏弱,比较适合大数据处理,性能优先的场景
RocketMQ 是支持同步刷盘、同步复制,可靠性较高,适当牺牲性能,比较适合业务侧应用的数据处理,对于数据可靠性有保障,支持分布式事务,可以适合业务优先的场景
kafka不适合作为数据库来进行使用
kafka虽然提供了ACID的保证,也可以长期存储数据,但是对于检索能力的支持比较差,无法提供有好的数据访问机制
kafka不适合处理大型数据
基于kafka 的IO特性,kafka不是为大型消息而设计的,10k的消息大小为最佳
kafka无法独立提供一套实时系统,更多的事作为消息中间件,和其他框架搭配使用
kafka 自身设计没有提供丰富的面向业务的函数库,对于消息的处理还是需要以来合适的消费者的选型和处理逻辑的准确性,所以更多的是作为中间件搭配使用
强时序性消息流需要谨慎选择kafka
kafka 是单分区保持强顺序性,但是分区数超过1时,消费的顺序是无法保证的,所以需要在顺序性和扩展性上做选择,需要选择合适的场景使用