最近一直在思考公司使用的rocketMQ的组件业务设计的问题,
因为公司在使用上比较随意, 即使出了规范, 该规范也是比较零散缺乏统一的模型, 也没有系统性的解决设计问题,
背景
1. MQ搭建的系统, 目标之一是要做到事件驱动化系统, 他的优点有很多这里不一一细说
2. RocketMQ, 有Topic, Tag, ConsumerGroup, ProducerGroup这几个概念, 其中Topic, Tag功能相同, 只是分组更细化, 所以这里为了简化问题, 将它们合二为一, ProducerGroup 在本次业务设计中用不到, 我们就当全局只有一个提供者, 所以这里的设计就只针对, tag 和 ConsumerGroup 两个, tag可以理解为对事件的定义或者命名, ConsumerGroup 可以理解为事件的消费者定义. 所以整个流程就是, 统一的发送者ProducerGroup, 发送不同的消息tag, 然后由不同的消费者ConsumerGroup处理, 一个消费者可以处理多个消息, 多个消费者也可以处理同一个消息
3. 简化问题:
事件:消息 = 1:1, 可以把事件看作是消息
Topic = Tag = 事件
ProducerGroup = 1
4. 在能解决实际问题的前提下(包含业务问题和非业务问题), 事件和消费者 数量越少越好
设计要解决的问题
1. 事件的定义维度是什么?
2. 事件有没有固定的数量? 或者这个固定的数量来源依据是什么?
3. 事件消费者定义的维度是什么?
4. 事件消费者有没有固定的数量? 或者这个固定的数量来源依据是什么?
为什么关心数量?
数量: 解决数量的问题, 1. 同等作用下, 数量越少越好, 2. 便于分类管理和便于理解
为什么关心定义的维度?
维度: 解决定义的维度问题, 1. 是为了统一模型, 统一思路, 2. 找出能解决上述问题的维度, 3. 便于理解, 便于定位
方案
事件维度:
建议以订单常用可变化状态作为维度(比如订单主状态, 订单支付状态等)
优点:
1. 极其便于理解和定位,
2. 能解决数量问题
事件数量:
数量 <= 主状态数量 * 支付状态数量
优点:
1. 数量不大于状态数量的乘积, 有上限, (如果没有指定维度, 而是凭借业务, 则很有可能因为对业务的理解不一致导致事件数量没有上限)
消费者维度:
建议以业务为作为维度, 似乎只能以业务作为维度, 消费者本身就是驱动不同业务的, 而业务是千变万化的,
消费者数量:
数量 >= 事件数量
~= 可变化状态数1 * 可变化状态数2 * 不变状态数1 * 不变状态数2 * 业务系数n
名词解释:
可变化状态: 会随着订单生命周期变化而变化的状态, 比如: 订单状态, 支付状态
可变化状态数: 指的是可变化状态的取值范围, 比如: 支付状态取值有三种, 已支付, 未支付, 无需支付, 那可变化状态数 = 3
不可变化状态: 不会随着订单生命周期变化而变化的状态, 但同时由标记订单的某种业务类型的字段, 比如: 实时单, 预约单
不可变化状态数: 不可变化状态的取值范围
业务系数n: 指的是同一个场景下, 需要处理的业务数量, 也正是因为此系数的存在, n取值 1-正无穷, 才使得消费者数量可以无穷多
其他问题
1. 事件的定义以状态变化作为维度, 那么一些业务场景会同时触发多个状态同时发生变化, 那这个时候需要发几个事件呢?
方案:
1. 还是以状态为准, 如果有两个状态发生变化, 那就发送两个事件, 消费者根据自己业务关注点的不同来自主选择监听哪个事件.
2. 多个状态的变化很多时候有依赖关系, 应该把有依赖关系的事件分开独立处理, 比如: 订单已支付和订单开始派车, 几乎是同时发生的, 可以写在同一个业务中, 但是开始派车是依赖于已支付的所以要分成两个事件让他们又先后依赖关系.
2. 有些事件是没有状态发生变化的
方案:
1. 有些事件比如创单成功, 对于数据来说就是从无到有, 所以可以把事件看作是从null变成初始值, 这样也可以定义事件的
2. 还有写业务是根据有无关联表来判断业务状态的, 而关联的表并没有状态
方案:
1. 业务定义的时候建议加上字段区分业务而不是通过有无数据进行区分
2. 如果关联表有相关状态, 可以进一步将事件细化到关联表的状态上
3. 宏观上, 数据的有无可以看做一种状态
3. 如果某个消费先定义, 如果想触发这个消费业务就要发送已经定义好的tag, 要如何实现?
方案:
1. 这种使用方式不在上述模型中, 同时在非必要的情况下, 不建议使用这种方式
2. 如果使用这种方式, 则可以添加一层消费者中转, 消费者监听指定的事件, 同时消费者所处理的业务就是发送下一个事件, 这样既能做到解耦, 又可以兼容原有模型
欢迎探讨