后端基础| 青训营笔记

99 阅读6分钟

这是我参与「第五届青训营」伴学笔记创作活动的第 11 天

消息队列
案例一:系统崩溃
一个购买系统:①搜索直播间,②搜索行为记录,③点击商品,④点击行为记录 ②③④都需要及记录在记录存储中,如果此时记录存储程序所在的机房被删库跑路了,会发生什么事故?
解决方案:解耦
可以将②③④存储在消息队列中,然后再由存储服务把它拉出来进行消费。

案例二:服务能力有限
多个人发起订单,然后系统只能同时处理10订单请求,面对庞大的请求量,处理订单的服务该怎么办
解决方案:削峰
放在消息队列中,然后每次只获取10个请求进行处理

案例三:链路耗时长尾
用户:发起订单5ms,库存记录-1 100ms,订单记录+1 100ms,通知商家30s,对于这个流程应该怎么优化来挽回这个暴躁的用户?
解决方案:异步

image.png 发起订单之后,然后就是通知下单成功,然后再去进行处理

案例四:日志如何处理
Log——消息队列——LogStash——ES——Kibana
日志专门处理的组件,然后写到搜索引擎里面,然后进行展示
消息队列:指保存消息的一个容器,本质是个队列。但这个队列呢,需要高吞吐,高并发,并且高可用。
消息队列发展历程 image.png

常见的消息队列 image.png kafka:目前最常见的
使用场景:离线的消息处理,日志信息,Metrics数据,程序在运行状态中对程序的状态进行采集,比如说QBS,用户行为(搜索、点赞、评论、收藏)
如何使用:创建kafka集群,新增Topic,设置分区数量,引入kafka的SDK,编写生产者逻辑,然后编写消费者逻辑

image.png Topic: 逻辑队列,不同 Topic 可以建立不同的 Topic
Cluster: 物理集群,每个集群中可以建立多个不同的
TopicProducer: 生产者,负责将业务消息发送到 Topic 中
Consumer: 消费者,负责消费 Topic 中的消息ConsumerGroup: 消费者组,不同组 Consumer 消费进度互不干涉
Offset:消息在partition中的相对位置信息,可以理解为唯一ID,在partition内部严格递增
每个分片有多个Replica,Leader Replica将会从ISR中选出

image.png Leader就是对外进行写入或读取,Follower就是不断拉拉取,然后尽量保持一致。如果差距过大就踢出去(通过时间的差距来判断),选择副本通信成为Leader,保证高可用。
数据复制

image.png

Kafka架构

image.png 高吞吐:
Producer—生产—Broker—消费—Consumer
如果发送一条消息,等到其成功后再发一条会有什么问题?
就是延迟会大一些,而且量级也不够。
Producer—批量发送
将多条Message放在Batch中,进行发送。批量发送可以减少IO次数,从而加强发送能力。
如果消息量很大,网络带宽不够,怎么解决?
Producer—压缩
通过压缩,减少消息大小,目前支持Snappy,Gzip,LZ4,ZSTD压缩算法,推荐使用ZSTD
Broker—数据的存储

image.png


每条LogSegment用第一条信息的Offset作为具体的命名
Broker—磁盘结构
移动磁头找到对应磁道,磁盘转动,找到对应扇区,最后写入。寻道成本比较高,因此循序写可以减少寻道所带来的时间成本。 顺序写的方式进行写入,以提高写入效率,就是在末位添加
Broker—如何找到消息
Consumer通过发送FetchRequest请求数据消息,Broker会将指定Offset处的消息,按照时间窗口和消息大小窗口发送给Consumer,怎么寻找数据?
通过二分找到小于目标Offset的最大文件

image.png Broker时间戳索引文件:
二分找到小于目标时间戳最大的索引位置,再通过寻找Offset的方式找到最终数据

image.png

image.png
降低了三次的内存拷贝
Consumer—消息的接收端
手动分配

image.png
容灾问题,调换的时候会出现中断
自动分配

image.png 选举一个Coordinator,然后要是删除一个或者增加的时候,Coordinator会进行相应的分配

image.png
Producer: 批量发送、数据压缩
Broker: 顺序写,消息索引,零拷贝
Consumer: Rebalance
问题:
1.数据复制问题: ①重启操作

image.png 负载均衡问题,因为这个回切,不能进行并发重启


替换、扩容、缩容

image.png
只要由节点的变动就会产生,时间运维成本,相对较高
存在的问题
①. 运维成本高
②.对于负载不均衡的场景,解决方案复杂
③.没有自己的缓存,完全依赖 Page Cache4.
④Controller 和 Coordinator和Broker 在同一进程中,大量 10会造成其性能下降
BMQ:字节(Pulsar:腾讯,跟他类似)
兼容Kafka协议,存算分离,云原生消息队列

image.png

image.png HDFS写文件流程
Client—写入—随机选择一定数量的DataNode进行写入—读取—Client

image.png
BMG就是随机选取进行分配节点
Broker-Partition状态机 image.png
保证对于任意分片在同一时只能在一个Broker上存活
Broker—写文件流程
Messages——数据校验——Buffer(ACK=0)——Writer Thread(Write Data——Flush——Build Index——Checkpoint——Roll new segment file)——Storage(ACK=-1)
Broker—写文件Failover
Client—写入—DataNode,如果DataNode节点挂了或者是其他原因导致我们写文件失败,要重新选择一个节点,创建一个新的segment进行写入
Proxy image.png Wait设置:数据大小的窗口,时间窗口
多机房部署

image.png

BMQ—高级特性 image.png 开发流程:开发——BOE——PPE——Prod
BOE:是一套完全独立的线下机房环境
PPE:即产品预览环境

image.png
多个人同时测试,需要等待上一个人测试完成(串行的)
如果是搭配多个环境的话,每多一个测试人员,都需要重新搭建一个相同配置的Topic,造成人力和资源的浪费

image.png 对于PPE的消费者来说,资源没有生产环境多,所以无法承受生产环境的流量。

image.png 解决主干道流量隔离问题以及泳道资源重复创建问题。

image.png

Databus:
MySQL——Databus Server——Databus Agent(Application)——BMQ
1.简化消息队列客户端复杂度
2.解耦业务与Topic
3.缓解集群压力,提高吞吐

image.png

image.png Index:
Producer——BMQ——Consumer
Query By: 1.Offset 2.Timestamp
如果希望通过写入的 Logld、Userld 或者其他的业务字段进行消息的查询,应该怎么做?

image.png
直接在BMQ中将数据结构化,配置索引DDL,异步构建索引后,通过Index Query服务读出数据
Parquet
Apache Parquet是Hadoop生态圈中一种新型列式存储格式,它可以兼容 Hadoop 生态圈中大多数计算框架(Hadoop、Spark等),被多种查询引擎支持(Hive、Impala、Drill等)。

image.png 直接在 BMQ 中将数据结构化,通过 Parquet Engine,可以使用不同的方式构建 Parquet格式文件

image.png

RocketMQ:(阿里自研)
使用场景(低延时):针对电商业务线,其业务涉及广泛,如注册、订单、库存、物流等;同时,也会涉及许多业务巅峰值时刻,如秒杀活动、周年庆、定期特惠等

image.png

image.png

架构 image.png

存储模型 image.png

高级特性:
①最终一致性

image.png

②事务消息 image.png (两阶段提交) ③延迟发送
提前编辑菜单(前一天编辑好)——消息队列+定时发送(第二天到点发送)——接受菜单

延迟消息 image.png 处理失败
Producer——RocketMQ——Consumer——处理失败
消费重试和死信队列

image.png

image.png