• 大龄小学生 置顶
    2019-08-08
    老师,一图胜千言,来点图吧。

    作者回复: 你要的图来了。我在文中补充了一个流程图,便于同学们理解。

     2
     13
  • linqw
    2019-08-08
    学习完网关答疑篇,写下自己的理解和疑惑,老师有空帮忙看下哦
    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,道阻且长,持续进化。
    展开

    作者回复: 我认真的看了同学的对于秒杀的理解,技术上都没什么问题。

    从业务角度,老师有一些不同的看法。

    对于秒杀这种场景,宏观上的设计应该是倾向于利用有限的资源处理短时间内海量的请求,保证服务不宕机。有少量请求处理出错(注意是后端错误,用户不可见)或消息丢失,是可以接受的。

    毕竟秒杀拼的就是运气,某个用户秒杀请求在处理的时候丢失,和处理成功但没秒到,对于用户来说都是运气不好而已。

    基于这样的设计理念,很多保证数据可靠性的做法都可以牺牲掉,用于换取系统更大的吞吐量比较划算。

     1
     19
  • 滴流乱转小胖子
    2019-08-08
    mq界,吴彦祖老师你好,感谢分享

    作者回复: 谢谢你,蔡徐坤同学。

     1
     9
  • Abyssal
    2019-08-08
    七夕不过节,继续学习 —— 谁让我是单身狗呢
     1
     8
  • 虢國技醬
    2019-09-05
    "同一个消费组内,每个队列只能被一个消费者实例占用"
    我在想:如果队列只有两个Q1和Q2,但是G1中有三个消费者实例C1,C2和C3;那会不会有一个消费者实例一直在偷懒(没有干活的机会,😂)。
    对于这种情况会报错?还是说内部会有机制队列的占用是换着分配给消费者实例的(不是某个实例一直占用)?

    作者回复: 是的,这时候就会有一个消费者没有干活的机会。

    至于,如何分配队列与消费者的关系,不同的消息队列处理也不一样,有的消息队列是绑定队列与消费者,这样有一个消费者一直闲着,其它二个一直干活。

    也有的消息队列是分时绑定,也就是你干一会儿,我干一会儿,但任何时刻,都会有一个消费者处于闲着的状态。

    
     6
  • 摩云神雕
    2019-09-20
    请教下老师,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都支持动态扩容,增加分区数量,分区数量变更后,会重新分配消费者和分区对应关系,对生产基本没什么影响。

     1
     5
  • A:春哥大魔王
    2019-08-08
    看了几期,感觉分布式消息队列的设计方案和分布式存储系统的设计方案很类似,如果再加上事务处理,存储细节方案应该更像了

    作者回复: 同学那不是像,消息队列就是个分布式存储系统。

    
     3
  • 猿人谷
    2019-08-08
    这篇答疑解惑,虽然简短,但绝对的诚意十足。希望多出这种答疑解惑的章节,毕竟评论区里很多留言的问题非常有代表性,对代表性的问题出这种答疑解惑的章节,学到的更多,也更能体现大家的参与度。
    
     3
  • 木木木
    2019-08-20
    关于有序性还有疑惑,即使采用了一致性hash,无论扩容还是缩容队列,对分配相邻队列的用户部分还是有影响的,难道要等这些队列消费完了,阻止生产者发消息吗?感觉不具有可操作性

    作者回复: 扩容后只需要等一会儿,确保扩容之前的消息都消费完成了(不确定的话可以等久一点儿也没关系)再消费新分区的数据就可以了,生产不需要停。

    因为一致性哈希可以保证单调性:如果已经有一些内容通过哈希分派到了相应的分区中,又有新的分区加入到系统中。哈希的结果应能够保证原有已分配的内容可以被映射到原有的或者新的分区中去,而不会被映射到旧的分区集合中的其他分区

    
     2
  • 发条橙子 。
    2019-08-17
    老师,我的疑问点有些偏 。 我看老师依赖注入用的是JSR330的注释 Inject , 但实际上和spring自身的 Autowired 注释功能相同, 所以我平时都是直接用 spring 自带的注释。 请问老师使用 JSR330 提供的注释是有什么讲究莫

    作者回复: JSR是一个标准,Spring是JSR的一个实现,并做了很多的扩展。

     1
     2
  • Liam
    2019-08-14
    秒杀这个案例中,超时之后不需要补偿机制吗,对于下游服务来说很可能以及成功了

    作者回复: 这个案例中,你说的这种情况是有可能存在的。

    是否需要补偿,也无所谓对错,总体效果是一样的。秒杀的目的就是从众多秒杀用户中公平的选择n个用户,补偿或不补偿,影响的只是这n个用户是谁的问题。

    所以这是一个架构选择的问题。

    我建议是不用补偿,按失败处理,锁定的库存超时未支付后会自动释放,好处是比较简单。

    
     2
  • 微微一笑
    2019-08-09
    老师好,看了秒杀的代码,有点疑问:
    等待后端超过timeout设置的时间点,且没有秒杀结果,finally代码块中会remove掉这个请求id,并返回用户秒杀失败;若在remove之前,后端服务返回了秒杀结果并秒杀成功,在非常极致的情况下,会不会出现用户看到秒杀失败,系统却秒杀成功的情况发生呢?

    作者回复: 你可以再看一下这课的文本,我补充了一个流程图。

    对于你说的这个情况,是不会出现的。因为,后端服务返回的秒杀结果,只会存放在Map中,并不会直接返回APP。

    给APP返回结果的,只能是处理APP请求的那个线程。

     4
     2
  • sswzfly
    2019-08-09
    我是消息队列小达人了
    
     2
  • 明日
    2019-08-08
    老师,关于事务消息的ACID那个问题没有提到,能不能找机会说下你的看法?个人的看法是没有实现隔离性,一致性只能保证最终一致,而原子操作和持久化可以通过各种手段实现。

    作者回复: 严格的说,ACI都没实现,只有D实现了。

    放宽点儿限制的话,或者考虑实际效果的话,A(原子性)绝大多数情况下还是可以保证的,即“要么都成功,要么都失败”。C(一致性)通过补偿,大部分情况下也可以保证最终一致。

     1
     2
  • 业余草
    2019-08-08
    相对来说,哪一个消息队列的学习成本较高?

    作者回复: 我觉得是Kafka吧,功能足够复杂,而且老外写代码的脑回路和我们不大一样。

     1
     2
  • 海罗沃德
    2019-12-09
    说到一致性哈希算法,王争老师的算法课程里专门有一课讲一致性哈希,跟李玥老师的课互相印证,算法就落地了

    作者回复: 其实这些最基础的算法和数据结构的应用是非常广泛的,只是为了方便,被很多中间件或者底层系统给封装后,对一般的业务开发人员就不可见了。

    
     1
  • TonySweet
    2019-11-04
    刚开始学习 RocketMQ. Consumer可以register的MessageListener 有两种: MessageListenerOrderly 和 MessageListenerConcurrently.
    这和老师讲的, RocketMQ 每个queue只要一个单线程消费者矛盾吗?

    作者回复: 首先强调一下,并不是“每个队列只要一个单线程消费者”,而是“每个队列只能被一个消费者实例占用。”

    rocketMQ的MessageListenerConcurrently,和我们上面讲的内容也不矛盾,它这个并行消费是完全在客户端实现的。大致的原理就是:

    1. 客户端从服务端的某个队列读取一批消息;
    2. 分发给客户端的多个线程消费;
    3. 都消费成功后,给服务端返回消费成功确认。

    
     1
  • 切糕
    2019-11-03
    我是看了rocketMQ源码后在看了一遍,受益匪浅
    
     1
  • asdf100
    2019-08-22
    订阅模型中,消息的发送方称为发布者(Publisher),消息的接收方称为订阅者(Subscriber),服务端存放消息的容器称为主题(Topic)。发布者将消息发送到主题中,订阅者在接收消息之前需要先“订阅主题”。“订阅”在这里既是一个动作,同时还可以认为是主题在消费时的一个逻辑副本,每份订阅中,订阅者都可以接收到主题的所有消息。

    那么消息到底存储在主题里还是队列里????

    作者回复: 队列

     1
     1
  • asdf100
    2019-08-22
    消息一直在队列里不删除?

    作者回复: 消息什么时候删除取决于消息队列的配置,比如Kafka默认就是超过多长时间后就自动删除了。

    
     1
我们在线,来聊聊吧