1、为什么有消息系统
1、解耦合
2、异步处理
例如电商平台,秒杀活动。
一般流程会分为:
- 风险控制
- 库存锁定
- 生成订单
- 短信通知
- 更新数据
通过消息系统将秒杀活动业务拆分开,将不急需处理的业务放在后面慢慢处理;
流程改为:
- 风险控制
- 库存锁定
- 消息系统
- 生成订单
- 短信通知
- 更新数据
3、流量的控制
3.1 网关在接受到请求后,就把请求放入到消息队列里面
3.2 后端的服务从消息队列里面获取到请求,完成后续的秒杀处理流程。然后再给用户返回结果。
- 优点:控制了流量
- 缺点:会让流程变慢
推荐一个开源免费的 Spring Boot 实战项目:
GitHub - javastacks/spring-boot-best-practice: Spring Boot 最佳实践,包括自动配置、核心原理、源码分析、国际化支持、调试、日志集成、热部署等。
2、Kafka核心概念
- 生产者:Producer 往Kafka集群生成数据
- 消费者:Consumer 往Kafka里面去获取数据,处理数据、消费数据
Kafka的数据是由消费者自己去拉去Kafka里面的数据
- 主题:topic
- 分区:partition
默认一个topic有一个分区(partition),自己可设置多个分区(分区分散存储在服务器不同节点上)
解决了一个海量数据如何存储的问题
例如:有2T的数据,一台服务器有1T,一个topic可以分多个区,分别存储在多台服务器上,解决海量数据存储问题
3、Kafka的集群架构
Kafka集群中,一个kafka服务器就是一个broker,Topic只是逻辑上的概念,partition在磁盘上就体现为一个目录。
Consumer Group:消费组,消费数据的时候,都必须指定一个group id,指定一个组的id
假定程序A和程序B指定的group id号一样,那么两个程序就属于同一个消费组
特殊:
- 比如,有一个主题topicA, 程序A去消费了这个topicA,那么程序B就不能再去消费topicA(程序A和程序B属于一个消费组)
- 再比如程序A已经消费了topicA里面的数据,现在还是重新再次消费topicA的数据,是不可以的,但是重新指定一个group id号以后,可以消费。
不同消费组之间没有影响。消费组需自定义,消费者名称程序自动生成(独一无二)。
Controller:Kafka节点里面的一个主节点。借助zookeeper
4、Kafka磁盘顺序写保证写数据性能
kafka写数据:
顺序写,往磁盘上写数据时,就是追加数据,没有随机写的操作。
经验:
如果一个服务器磁盘达到一定的个数,磁盘也达到一定转数,往磁盘里面顺序写(追加写)数据的速度和写内存的速度差不多。
生产者生产消息,经过kafka服务先写到os cache 内存中,然后经过sync顺序写到磁盘上
5、Kafka零拷贝机制保证读数据高性能
消费者读取数据流程:
- 消费者发送请求给kafka服务
- kafka服务去os cache缓存读取数据(缓存没有就去磁盘读取数据)
- 从磁盘读取了数据到os cache缓存中
- os cache复制数据到kafka应用程序中
- kafka将数据(复制)发送到socket cache中
- socket cache通过网卡传输给消费者
kafka linux sendfile技术 — 零拷贝
- 消费者发送请求给kafka服务
- kafka服务去os cache缓存读取数据(缓存没有就去磁盘读取数据)
- 从磁盘读取了数据到os cache缓存中
- os cache直接将数据发送给网卡
- 通过网卡将数据传输给消费者
6、Kafka日志分段保存
Kafka中一个主题,一般会设置分区;比如创建了一个topic_a,然后创建的时候指定了这个主题有三个分区。
其实在三台服务器上,会创建三个目录。
服务器1(kafka1):
- 创建目录topic_a-0:
- 目录下面是我们文件(存储数据),kafka数据就是message,数据存储在log文件里
- .log结尾的就是日志文件,在kafka中把数据文件就叫做日志文件。
一个分区下面默认有n多个日志文件(分段存储),一个日志文件默认1G
服务器2(kafka2):
- 创建目录topic_a-1:
服务器3(kafka3):
- 创建目录topic_a-2:
7、Kafka二分查找定位数据
Kafka里面每一条消息,都有自己的offset(相对偏移量),存在物理磁盘上面,在position
Position:物理位置(磁盘上面那个地方)
也就是说一条消息就有两个位置:
- offset:相对偏移量(相对位置)
- position:磁盘物理位置
稀疏索引:
- Kafka中采用了稀疏索引的方式读取索引,kafka每当写入了4k大小的日志(.log),就往index里写入一个记录索引。
其中会采用二分查找
8、高并发网络设计(先了解NIO)
网络设计部分是kafka中设计最好的一个部分,这也是保证Kafka高并发、高性能的原因
对kafka进行调优,就得对kafka原理比较了解,尤其是网络设计部分
Reactor网络设计模式1:
Reactor网络设计模式2:
Reactor网络设计模式3:
Kafka超高并发网络设计:
9、Kafka冗余副本保证高可用
在kafka里面分区是有副本的,注:0.8以前是没有副本机制的。创建主题时,可以指定分区,也可以指定副本个数。副本是有角色的:
leader partition:
- 写数据、读数据操作都是从leader partition去操作的。
- 会维护一个ISR(in-sync- replica )列表,但是会根据一定的规则删除ISR列表里面的值
生产者发送来一个消息,消息首先要写入到leader partition中
写完了以后,还要把消息写入到ISR列表里面的其它分区,写完后才算这个消息提交
follower partition:从leader partition同步数据。
10、优秀架构思考-总结
Kafka — 高并发、高可用、高性能
- 高可用:多副本机制