最全高可用延迟队列设计与实现,涨薪7K

结局:总结+分享

看完美团、字节、腾讯这三家的一二三面试问题,是不是感觉问的特别多,可能咱们真的又得开启面试造火箭、工作拧螺丝的模式去准备下一次的面试了。

开篇有提及我可是足足背下了Java互联网工程师面试1000题,多少还是有点用的呢,换汤不换药,不管面试官怎么问你,抓住本质即可!能读到此处的都是真爱

  • Java互联网工程师面试1000题

image.png

而且从上面三家来看,算法与数据结构是必备不可少的呀,因此我建议大家可以去刷刷这本左程云大佬著作的 《程序员代码面试指南 IT名企算法与数据结构题目最优解》,里面近200道真实出现过的经典代码面试题。

  • 程序员代码面试指南–IT名企算法与数据结构题目最优解

image.png

  • 其余像设计模式,建议可以看看下面这4份PDF(已经整理)

image.png

  • 更多的Java面试学习笔记如下,关于面试这一块,我额外细分出Java基础-中级-高级开发的面试+解析,以及调优笔记等等等。。。

image.png

以上所提及的全部Java面试学习的PDF及笔记,如若皆是你所需要的,那么都可发送给你!

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

  • at least once → 至少一次,消息肯定不会丢失,但可能重复

  • exactly once → 有且只有一次,消息不丢失不重复,且只消费一次。

exactly once 尽可能是 producer + consumer 两端都保证。当 producer 没办法保证是,那 consumer 需要在消费前做一个去重,达到消费过一次不会重复消费,这个在延迟队列内部直接保证。

最简单:使用 redis 的 setNX 达到 job id 的唯一消费

高可用

支持多实例部署。挂掉一个实例后,还有后备实例继续提供服务。

这个对外提供的 API 使用 cluster 模型,内部将多个 node 封装起来,多个 node 之间冗余存储。

为什么不使用 kafka?

考虑过类似基于 kafka/rocketmq 等消息队列作为存储的方案,最后从存储设计模型放弃了这类选择。

举个例子,假设以 Kafka 这种消息队列存储来实现延时功能,每个队列的时间都需要创建一个单独的 topic(如: Q1-1s, Q1-2s…)。这种设计在延时时间比较固定的场景下问题不太大,但如果是延时时间变化比较大会导致 topic 数目过多,会把磁盘从顺序读写会变成随机读写从导致性能衰减,同时也会带来其他类似重启或者恢复时间过长的问题。

  1. topic 过多 → 存储压力

  2. topic 存储的是现实时间,在调度时对不同时间 (topic) 的读取,顺序读 → 随机读

  3. 同理,写入的时候顺序写 → 随机写

架构设计


API 设计


producer

  1. producer.At(msg []byte, at time.Time)

  2. producer.Delay(body []byte, delay time.Duration)

  3. producer.Revoke(ids string)

consumer

  1. consumer.Consume(consume handler)

使用延时队列后,服务整体结构如下,以及队列中 job 的状态变迁:

  1. service → producer.At(msg []byte, at time.Time) → 插入延时job到 tube 中

  2. 定时触发 → job 状态更新为 ready

  3. consumer 获取到 ready job → 取出 job,开始消费;并更改状态为 reserved

  4. 执行传入 consumer 中的 handler 逻辑处理函数

生产实践


主要介绍一下在日常开发,我们使用到延时队列的哪些具体功能。

生产端

  1. 开发中生产延时任务,只需确定任务执行时间

  2. 传入 At() producer.At(msg []byte, at time.Time)

  3. 内部会自行计算时间差值,插入 tube

  4. 如果出现任务时间的修改,以及任务内容的修改

  5. 在生产时可能需要额外建立一个 logic_id → job_id 的关系表

  6. 查询到 job_id → producer.Revoke(ids string) ,对其删除,然后重新插入

消费端

首先,框架层面保证了消费行为的 exactly once ,但是上层业务逻辑消费失败或者是出现网络问题,亦或者是各种各样的问题,导致消费失败,兜底交给业务开发做。这样做的原因:

  1. 框架以及基础组件只保证 job 状态的流转正确性

  2. 框架消费端只保证消费行为的统一

  3. 延时任务在不同业务中行为不统一

  4. 强调任务的必达性,则消费失败时需要不断重试直到任务成功

  5. 强调任务的准时性,则消费失败时,对业务不敏感则可以选择丢弃

这里描述一下框架消费端是怎么保证消费行为的统一:

分为 cluster 和 node。cluster

https://github.com/tal-tech/go-queue/blob/master/dq/consumer.go#L45

  1. cluster 内部将 consume handler 做了一层再封装

  2. 对 consume body 做hash,并使用此 hash 作为 redis 去重的key

  3. 如果存在,则不做处理,丢弃

node

go-queue/consumernode.go at master · tal-tech/go-queue · GitHub

最后

为什么我不完全主张自学?
平台上的大牛基本上都有很多年的工作经验了,你有没有想过之前行业的门槛是什么样的,现在行业门槛是什么样的?以前企业对于程序员能力要求没有这么高,甚至十多年前你只要会写个“Hello World”,你都可以入门这个行业,所以以前要入门是完全可以入门的。
②现在也有一些优秀的年轻大牛,他们或许也是自学成才,但是他们一定是具备优秀的学习能力,优秀的自我管理能力(时间管理,静心坚持等方面)以及善于发现问题并总结问题。
如果说你认为你的目标十分明确,能做到第②点所说的几个点,以目前的市场来看,你才真正的适合去自学。

除此之外,对于绝大部分人来说,报班一定是最好的一种快速成长的方式。但是有个问题,现在市场上的培训机构质量参差不齐,如果你没有找准一个好的培训班,完全是浪费精力,时间以及金钱,这个需要自己去甄别选择。

我个人建议线上比线下的性价比更高,线下培训价格基本上没2W是下不来的,线上教育现在比较成熟了,此次疫情期间,学生基本上都感受过线上的学习模式。相比线下而言,线上的优势以我的了解主要是以下几个方面:
①价格:线上的价格基本上是线下的一半;
②老师:相对而言线上教育的师资力量比线下更强大也更加丰富,资源更好协调;
③时间:学习时间相对而言更自由,不用裸辞学习,适合边学边工作,降低生活压力;
④课程:从课程内容来说,确实要比线下讲的更加深入。

应该学哪些技术才能达到企业的要求?(下图总结)

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

9948274)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值