这是我参与「第三届青训营 -后端场」笔记创作活动的的第12篇笔记
GO-学习笔记
消息队列
- Message Queue,保存消息的容器,本质上是个队列,需要支持高吞吐,高并发,高可用
kafka
- 日志信息、Metrics(运行情况)数据、用户行为
- 使用
- 创建集群
- 新增topic,逻辑队列
- 生产者
- 消费者
- zookeeper 负责存储集群元信息,分区分配信息
基本概念
- topic,逻辑队列,每个逻辑队列中有多个partition,存放真正的消息
- offset,消息在partition内的相对位置,作为唯一ID
- replica,每个partition有多个副本,保证容灾
- leader 负责写入
- follower,不断同步leader
- ISR,In Sync Replicas,如果副本和leader差距过大,将不会同步;在ISR中,leader发生宕机,在ISR中选出新leader
- broker,集群的一个节点
生产端
- 通过Batch,批量发送消息,减少IO次数,加强发送能力
- 通过压缩,减少消息大小
- 顺序写入,提高写入效率,减少寻道时间
接收端
- 内部通过二分查找目标消息文件
对于时间索引,增加时间戳作为二级索引
- 通过零拷贝,传输数据,通过DMA拷贝,从磁盘拷贝出来,再通过SG-DMA直接拷贝到网卡,发送给消费者进程
- partition的分配
- 手动分配,手动为consumer配置处理哪几个partition,不能自动容灾
- 通过coordinator,自动分配,进行rebalance;coordinator也是集群里的某个节点;在consumers中选择一个leader确定分配方案,通过coordinator将分配方案告诉其他consumer
缺点
- 每一个broker都有topic的分区,需要保持同步
- 重启机器后,需要同步数据,影响topic可用性
- 负载不均衡,某个partition过多,迁移消耗大量IO资源
- 没有自己的缓存,完全依赖PageCache
BMQ
- 兼容Kafka,存算分离,云原生消息队列
- proxy/broker,无状态,秒级重启节点
- HDFS,分布式文件式的写入,每次写入都随机选择部分节点(dataNode)进行写入
- 状态机,保证任意分片同一时刻只能在一个broker上存活
- revoer,选择一个节点进行写入,进行节点恢复和数据同步
- failover,DataNode宕机,选择一个新的节点
- 写入流程
- 可以修改返回策略
- build index建立索引
- checkpoint,告诉系统数据已经完全写入到某个offset
- 读取流程
- wait等待机制,proxy没有数据的时候,间隔一段时间再请求
高级特性
- 泳道消息,对每一个topic都有附带topic,配置都一样,并隔离资源;消费者只消费对应的泳道消息
- BOE Bytedance Offline Environment,完全独立的线下机房环境
- PPE Product Preview Environment,产品预览环境
- Databus
- 降低开发难度,简化消息队列客户端复杂度
- 解耦业务和Topic
- Mirror
- 跨地区的业务部署
- 通过mirror异步写入其他region的BMQ
- Index,直接在BMQ中将数据结构化,通过消息的Index查询日志信息
- Parquet,列式存储格式,列挨着存储,提高查询列的效率
RocketMQ
- 跟Kafka的对比
- 架构
- NameServer,作为路由,指出MessageQueue在哪个副本上
- 存储模型,密集索引,每个消息都有一个索引
高级特性
- 事务场景,异步处理多个业务,通过事务保证业务之间的关联
订单发起业务中,库存/订单/通知商家,是在一个业务中的
- 延迟发送,提前发送给消息好,并设置可以被消费的时间,定时会被消费处理
先发送给ScheduleTopic,ScheduleMessage通过轮询,到达时间点后回写给CommitLog,正常提交进行消费
- 消费重试和死信队列
- 消费失败,进行重试,没有达到重试次数,延期投递,发送给RetryTopic,再进行消费
- 达到重试次数,发送到死信队列,进行记录
定时任务
- Linux,CronJob命令
- Java,Timer/ScheduledExecutorService复用任务线程
- GO,Ticker
- 触发
- 定时发生
- 延时发生
- 周期发生
分布式定时任务
- 支持海量数据
- 是一个平台,把分散的、可靠性差的定时任务纳入统一的平台,并实现集群管理调度和分布式部署的一种定时任务的管理方式
- 单机任务,一台机器执行
- 广播任务,所有机器执行同一个任务
- Map任务,一个任务分为多个子任务,一个机器负责一部分的计算
- MapReduce热舞,对所有子任务进行汇总计算
- 现有框架
- Xxl-job 美团
- SchedulerX 阿里
- TCT 腾讯
实现原理
- 要解决触发、调度、执行
- 触发器,Trigger,解析任务,生成出发事件
- 调度器,Scheduler,分配任务,管理任务生命周期
- 执行器,Executor,获取执行任务单元,执行任务逻辑
- 控制台,Admin,提供任务管理和干预
- 数据流
- 细节架构
控制台
- Job,任务,任务元数据
- 基础信息
- 调度时机
- 执行行为
- 执行方式
- JobInstance,任务实例,一个任务,可以有多个任务实例
- JobId,绑定任务
- 触发时间
- 状态/结果
- 过程信息,通过消息队列进行调度,可以通过消息ID进行追回
- JobResult,任务实例的运行结果
一个任务实例,可以有多种结果,出错需要重试
- JobHistory,任务历史
存储历史任务
触发器
- 需要解析触发规则,在规定的时间点触发任务
- 支持大量任务
- 支持秒级的调度
- 周期任务需要多次执行
- 保证秒级扫描的高性能,避免资源浪费
- 定时扫描+延时消息
- 从db获取将要执行的任务
- 通过消息队列发送延时消息
- 时间轮,Quartz
- 环形队列,底层采用数组存储,每个元素可以存放一个定时任务列表,根据时间取对应的列表
- 链表/最小堆/时间轮
- 多级时间轮,根据时分秒三种时间轮,分配到不同的列表
- 高可用
- 不同业务,需要进行资源隔离
- 部署,需要多机房集群化部署
- 数据库行锁,保证任务只会被触发一次;多台机器频繁竞争锁,性能较差
- 分布式锁,抢占分布式锁
调度器
- 资源来源/资源调度/任务执行
- 业务系统提供机器资源
- 任务执行逻辑与业务系统共用资源,利用率高
- 定时任务脚本影响在线服务,不能由定时任务平台控制扩缩容
- 定时任务平台提供机器资源
- 任务执行逻辑与业务系统提供的在线服务隔离,避免互相影响;支持扩缩容
- 消耗更多机器资源,需要额外为定时任务平台申请接口权限,不能直接继承业务系统的权限
- 节点选择
- 随机节点执行,定时对账
- 广播执行,广播到所有节点上执行,批量运维
- 分片执行,任务拆分
- 任务编排,任务之间有同步执行关系
使用无向图进行任务编排
- 故障转移,一致性Hash,策略分发任务,如果失败,选择另外的机器执行
- 高可用
- 靠消息队列的重试机制保障任务一定会被调用
执行器
- 基于注册中心,可以让调度器调度
- 心跳机制,定时状态上报
业务应用
- 电商/互动/游戏
- 发货超过十天未收货,自动确认收货
- 分布式定时任务的延时任务
- 消息队列的延时消息
- 集卡
- 分布式定时任务的MapReduce任务
- 大数据离线处理引擎Hive
- 大数据实时处理引擎Flink
- 方案对比