08 | 答疑解惑(一) : 网关如何接收服务端的秒杀结果?
该思维导图由 AI 生成,仅供参考
1. 网关如何接收服务端的秒杀结果?
- 深入了解
- 翻译
- 解释
- 总结
本文深入介绍了消息队列处理、并行消费等技术内容,对于想要了解消息队列处理和并行消费的读者具有一定的参考价值。作者详细解释了网关如何接收服务端的秒杀结果,并通过Java代码展示了处理方案。此外,文章还详解了RocketMQ和Kafka的消息模型,以及如何实现单个队列的并行消费。在保证消息的严格顺序方面,作者提出了一些实现方法,强调了在学习消息队列的过程中要保持一定的高度,掌握消息队列宏观层面上的实现原理和最佳实践。在“基础篇”结束后,作者表示在“进阶篇”中将把学习重点从“如何使用”转为“如何实现”,并鼓励读者坚持学习,多思考,多练习,成为真正的高手。整体而言,本文内容丰富,涵盖了消息队列处理和并行消费等技术内容,适合对消息队列技术感兴趣的读者阅读学习。
《消息队列高手课》,新⼈⾸单¥59
全部留言(97)
- 最新
- 精选
- 大龄小学生置顶老师,一图胜千言,来点图吧。
作者回复: 你要的图来了。我在文中补充了一个流程图,便于同学们理解。
2019-08-08342 - linqw学习完网关答疑篇,写下自己的理解和疑惑,老师有空帮忙看下哦 1、秒杀的理解: APP--发送秒杀请求--》网关(也是RPC服务端,和配置中心保持长连接,比如nacos,将其路由和配置信息定时的发送给配置中心,配置中心对其进行管理,定时的清除宕机的网关路由信息,如超过一定时间没有接收到网关的心跳包)--》将其APP请求做一定的封装,增加网关id和网关实例中唯一的请求id发送给消息队列,为了保证消息不丢失,网关对其发送消息出现的异常进行处理,如超时异常,直接返回秒杀失败,网关发送消息的这个过程中可能涉及到分布式事务,使用消息队列的分布式事务进行处理,然后网关需要等待一段时间,等待秒杀服务端使用RPC调用网关实例的接收秒杀结果,为此创建一个新对象,将其请求id做为key,新对象做为value放入CurrentMap中,调用新对象的超时wait方法进行等待秒杀结果--发送封装的APP请求,包含网关id和请求id--》消息队列接收APP请求消息,为了保证消息不丢失,开启Sync_Flush参数将消息保存到磁盘,并且为了防止一台机器磁盘出问题,集群需要2台机器都有消息才确认请求--从消息队列中拉取消息--》秒杀服务端,为了低延迟执行风控、预占库存,拿到消息中网关id,从本地路由中查询网关id的实例信息,如果获取不到调用网关实例时,需先从配置中心获取到网关的路由信息,秒杀服务端也需和配置中心保持长连接,定时的从配置中心拉取网关的路由信息,保存到本地,使用RPC调用网关实例的接收秒杀结果的方法,为了保证消息不丢失,先执行消费逻辑,再响应消息队列,如果根据网关id获取不到网关实例,或者确认消息队列超时或出现异常,秒杀服务端回滚事务,此过程也涉及到分布式事务,为了防止消费重复消息,接口的幂等性,将请求id和网关id做为唯一键。也为了防止消息积压,消息队列中的主题队列和消费组中的消费者一一对应,保证消息被快速消费。 2、秒杀异步,APP发送请求给网关,网关接收请求后将请求做一定的封装(包括请求id,网关id,账户id),然后发送到消息队列中,响应APP请求,无需等待后需的流程,然后秒杀成功以否直接返回,后续流程处理完使用短信的形式告知用户是否秒杀成功,不知道这样做法是否可行。 3、最近在撸rocketmq的源码,搞了namesrv、logging、logappend模块,想成为commiter,立个flag,等后续JMQ出来,撸其源码,也想成为commiter,道阻且长,持续进化。
作者回复: 我认真的看了同学的对于秒杀的理解,技术上都没什么问题。 从业务角度,老师有一些不同的看法。 对于秒杀这种场景,宏观上的设计应该是倾向于利用有限的资源处理短时间内海量的请求,保证服务不宕机。有少量请求处理出错(注意是后端错误,用户不可见)或消息丢失,是可以接受的。 毕竟秒杀拼的就是运气,某个用户秒杀请求在处理的时候丢失,和处理成功但没秒到,对于用户来说都是运气不好而已。 基于这样的设计理念,很多保证数据可靠性的做法都可以牺牲掉,用于换取系统更大的吞吐量比较划算。
2019-08-08268 - 滴流乱转小胖儿mq界,吴彦祖老师你好,感谢分享
作者回复: 谢谢你,蔡徐坤同学。
2019-08-08838 - 摩云神雕请教下老师,topic的partition数 是根据什么确定的? 我理解partition的设置 是为了一个消费组中多个消费者并行消费的, 那么partition数根据什么设定呢? 根据消费者数 和 broker机器的性能吗 假设我现在的kafka有 3个broker节点, 创建了一个topic, partition值设为5, 然后我的一个消费组中有5个消费者, 正好一个消费者 消费一个partition, 后续, 这个消费组 我又想加2个消费者, 呢partition数 也调成7 是吧? 但是, 我这个topic 可能被好几个消费组消费的, 你消费组A扩展了消费者数, 想扩展partition数, 但是 我消费组B没这个需求啊, 怎么办? 这个topic是消费组A、B、C、D大家共同订阅的, 就因为 你A组加了几个消费者, 我就去改这个topic的partition数吗? 这里没太想通; 另外,在生产环境中 改了partition数,会造成什么影响?
作者回复: 多个消费组的时候,确实有你说的问题,partition数量需要兼顾所有消费者。一般的做法都是照顾消费最慢的那个消费组,按照它的速度和消费者数量来确定partition数量。 大部分MQ都支持动态扩容,增加分区数量,分区数量变更后,会重新分配消费者和分区对应关系,对生产基本没什么影响。
2019-09-20630 - 虢國技醬"同一个消费组内,每个队列只能被一个消费者实例占用" 我在想:如果队列只有两个Q1和Q2,但是G1中有三个消费者实例C1,C2和C3;那会不会有一个消费者实例一直在偷懒(没有干活的机会,😂)。 对于这种情况会报错?还是说内部会有机制队列的占用是换着分配给消费者实例的(不是某个实例一直占用)?
作者回复: 是的,这时候就会有一个消费者没有干活的机会。 至于,如何分配队列与消费者的关系,不同的消息队列处理也不一样,有的消息队列是绑定队列与消费者,这样有一个消费者一直闲着,其它二个一直干活。 也有的消息队列是分时绑定,也就是你干一会儿,我干一会儿,但任何时刻,都会有一个消费者处于闲着的状态。
2019-09-05225 - 木木木关于有序性还有疑惑,即使采用了一致性hash,无论扩容还是缩容队列,对分配相邻队列的用户部分还是有影响的,难道要等这些队列消费完了,阻止生产者发消息吗?感觉不具有可操作性
作者回复: 扩容后只需要等一会儿,确保扩容之前的消息都消费完成了(不确定的话可以等久一点儿也没关系)再消费新分区的数据就可以了,生产不需要停。 因为一致性哈希可以保证单调性:如果已经有一些内容通过哈希分派到了相应的分区中,又有新的分区加入到系统中。哈希的结果应能够保证原有已分配的内容可以被映射到原有的或者新的分区中去,而不会被映射到旧的分区集合中的其他分区
2019-08-2020 - 大魔王汪汪看了几期,感觉分布式消息队列的设计方案和分布式存储系统的设计方案很类似,如果再加上事务处理,存储细节方案应该更像了
作者回复: 同学那不是像,消息队列就是个分布式存储系统。
2019-08-08213 - Liam秒杀这个案例中,超时之后不需要补偿机制吗,对于下游服务来说很可能以及成功了
作者回复: 这个案例中,你说的这种情况是有可能存在的。 是否需要补偿,也无所谓对错,总体效果是一样的。秒杀的目的就是从众多秒杀用户中公平的选择n个用户,补偿或不补偿,影响的只是这n个用户是谁的问题。 所以这是一个架构选择的问题。 我建议是不用补偿,按失败处理,锁定的库存超时未支付后会自动释放,好处是比较简单。
2019-08-14211 - 大白先生老师,在秒杀场景中,后端服务通过调用onResult方法来放入秒杀结果,有没有可能有一种情况,就是秒杀成功了,但是获取mutex是空,这样的活,会不会前段接收了秒杀失败的提示,但是库存扣减成功了
作者回复: 会有这种情况。但无需特殊处理。 一般秒杀成功后,还有后续的支付流程。 有些用户秒杀成功也不会支付。你说的这种情况与“秒杀成功不支付”一并处理就行了。一般都是有一个支付超时,超过这个时限还没支付,就取消这个秒杀资格,自动释放库存。
2019-08-09211 - 托尼斯威特刚开始学习 RocketMQ. Consumer可以register的MessageListener 有两种: MessageListenerOrderly 和 MessageListenerConcurrently. 这和老师讲的, RocketMQ 每个queue只要一个单线程消费者矛盾吗?
作者回复: 首先强调一下,并不是“每个队列只要一个单线程消费者”,而是“每个队列只能被一个消费者实例占用。” rocketMQ的MessageListenerConcurrently,和我们上面讲的内容也不矛盾,它这个并行消费是完全在客户端实现的。大致的原理就是: 1. 客户端从服务端的某个队列读取一批消息; 2. 分发给客户端的多个线程消费; 3. 都消费成功后,给服务端返回消费成功确认。
2019-11-04510