这是我参与「第五届青训营 」伴学笔记创作活动的第 7 天
消息队列
保存消息的容器 本质上是一个队列 需要支持 高吞吐、高并发、高可用
异步RPC通信
Kafka
Kafka 中的消息以 topic 题为单位进行归类,生产者负责将消息发送到特定的 topic (发送到 Kafka 集群中的每一条消息都要指定一个主题),而消费者负责订阅主题并进行消费
创建Kafka集群 -> 新增topic -> 编写生产者逻辑 -> 编写消费者逻辑
- Topic:逻辑队列(每一个不同的业务场景,对这个业务来说,所有数据存于Topic中);内部partition分区,不同分区的消息可以并发处理
- Cluster:Broker的物理集群,每个集群中可以建立多个不同的Topic
- Producer:生产者,负责将业务消息发送到Topic中
- Consumer:消费者,负责消费Topic中的消息
- ConsumerGroup:消费者组,不同组的Consumer消费进度互不干涉
Offset:消息在partition中的相对位置(也是ID)
Replica:每个partition具有多个副本 Leader负责对外
Producer发送消息时,可以采用 批量发送&数据压缩
副本最终以日志的形式写到磁盘上
消息有过期机制
日志将切分成有序的日志段
Broker采用顺序写(末位添加),减少磁头运动寻道时间,提高写入效率
Consumer通过发送 FetchRequest 请求消息数据,Broker会将指定Offset处的消息,按照时间窗口和消息大小窗口发送给Consumer
Broker拿到FetchRequest后如何处理、响应?
ConsumerGroup中partition的分配问题(组内Consumer分别拉取哪些partition)
手动设置分配存在容灾问题,且扩缩容时麻烦(会带来数据中断)
自动分配 需要ConsumerRebalance
BMQ
存算分离 底层增加分布式存储系统
RocketMQ
面向低延时场景、业务峰值(秒杀)场景
较Kafka多一个 Tag字段 可以丰富消费的场景
存在ProducerGroup 以支持事务消息
NameServer提供路由
通过最终一致性保证事务
事务消息(类似两阶段提交)
RPC框架
远程函数调用
RPC需要解决的问题(与本地调用的区别):
- 函数映射(本地时函数指针,但RPC是对于两个不同进程,不共享地址空间)
- 数据转换成字节流(参数传递)
- 网络传输(如何保证高效稳定)
IDL文件:约定的规范 通过一种中立的方式描述接口,使得不同平台上运行的对象和用不同语言编写的程序可以互相通信
生成代码:通过编译器工具把IDL文件转换成对应语言的静态库
编解码:内存表示与字节序列的相互转化
通信协议:规范数据在网络传输中的内容和格式,通常还包含额外的元数据
网络传输:通常基于成熟的网络库,TCP/UDP
TLV编码:
- Tag:标签(类型)
- Length:长度
- Value:值(也可以是一个TLV结构)
协议层
一个特殊字符作为每个协议单元结束的提示
变长协议 由不定长部分与定长部分组成 定长部分需要描述不定长部分的长度
协议构造:
- LENGTH:数据包大小,不包含自身
- HEADER MAGIC:标识版本信息,协议解析时快速校验
- SEQUENCE NUMBER:表示数据包的seqID,可用于多路复用,在单个连接内递增
- HEADER SIZE:头长度
- PROTOCOL ID:编解码方式
- TRANSFORM ID:压缩方式
- INFO ID:传递一些定制的meta信息
- PAYLOAD:消息体
稳定性保障(衡量指标:请求成功率):
- 熔断:保护调用方,防止被调用的服务出现问题影响整个链路
- 限流:保护被调用方,防止大流量把服务压垮
- 超时控制:避免资源浪费在不可用节点上