线上真实排队系统重构案例分享

网站建设3年前发布
64 0 0

1、现状:,* 目前线上乘客排队性能瓶颈很明显,主要采用Redis  List存储结构。随着队列中订单量增大,查询、插入、判断订单是否在队列中等操作RT指数级增长。,* 目前乘客排队架构,无法满足业务扩展需求,为支撑之后业务快速迭代,乘客排队重构迫在眉睫。,2、调研事项,* 使用Mysql存储排队信息可行性分析(线下环境压测) ,* 对外接口和影响范围梳理(目前对外提供的20个左右接口分析),,表格如下:,1、对外接口不变,从底层存储改造,兼容目前线上显示场景,乘客排名显示和出队解耦。,排名显示保留普通队列、渠道队列、优先队列(包含绝对优先), 按入队时间排序,出队排序因子入队时根据固定规则计算, 采用更加灵活的策略算法计算出队优先级, 出队时只需根据排序因子排序,从而间接决定出队顺序,,2、数据存储排名采用Redis有序集合,队列信息新增mysql存储,分128张表。,3、解决目前性能瓶颈问题,支持后续业务快速迭代,以及后续需求扩展。,重构前存储架构: redis: list数据结构  ,  key:蜂巢中心点 + 车型 + 队列类型,重构后存储架构:,排名队列: redis有序集合, key: 蜂巢中心点 + 车型 + 队列类型(为了兼容老的),队列信息表:  queue_info_xxx,   mysql存储, 按蜂巢中心点 hash分表,订单号 + 车型 建联合唯一索引,部分接口新—老对比,重构前瓶颈分析: 每次请求都会将队列中元素全部取出循环遍历(当排队订单量增大时,RT呈指数级增长,卖个关子,原因大家可以想想为啥?),重构后存储架构优势: 将原来的O(n)时间复杂度,变为O(1)复杂度。,关于队列大小统计问题:,排名未限流队列:   直接通过ZCARD获取 (O(1)  时间复杂度),排名限流队列: 通过计数器获取总长度 (O(1)), 降级通过ZCARD获取,2)关于新增运力撮合——查询列表【橙色部分】可能存在瓶颈问题——后期优化方向有2种 可以排名前N抽离出缓冲集合 队列截断 —— 大小超过N转为其它表存储,queue_info_[001 ~ 128] : 排队信息表 按蜂巢中线点 hash % 128 规则分表,数据按天归档,queue_manager : 排 名队列管理表 主要控制是否限流状态,和蜂巢队列信息,queue_log_[001~128] : 订单入队&出队记录表,按蜂巢中线点  hash % 128 规则分表,后期再考虑归档。,详细表结构 —— 省略,针对排队场景,时间越小,越在前。可以使用时间差逆序计算,公式如下: ~(-1L << 39L) & (~(毫秒级时间差)),其它规则此处省略.,排名显示:   普通队列、渠道队列、优先队列,订单出队:  通过权重系数不同配置,最后计算出不同排序,按城市灰度,先选小流量城市。,关闭城市灰度开关,已存在队列中数据会影响,需要迁移工具刷新数据,数据归档:   乘客排队信息按天归档,兜底策略:  长时间(可配置)排队状态未变更(可能出现异常),强制退出,乘客排队Grafana监控: 监控指标:  城市、蜂巢、车型、普通队列数、渠道队列数、优先队列数 报警: 队列数超过阈值钉钉报警,方案调研的接口(20个接口)增加改造方案、责任人,进度项,注意: 接口自测 和 CR是在开发阶段完成的,监控报警不影响测试的开发,可以在测试阶段开发。,略,略,重构需要考虑到细节很多,需要考虑到每一个可能出现瓶颈的地方,以及后续优化,扩展问题。,所有改动项,必须责任到个人(避免遗漏),另外提测之前必须全部自测通过(单元测试)。

© 版权声明

相关文章