使用消息队列实现下面三个目标
1.保证事务一致性
2.顺序消息投递及消费
3.幂等性即 每个消息只消费一次
Kafka简介
kafka消费模式:
kafka采取pull模式,消费速度由消费者线程的消费速度决定
kafka分区:
每个主题下的kafka分区采用磁盘顺序IO写入,消费时采用磁盘顺序IO读出,
消费者在消费成功后 投递ack 分区offest会自动修改,从而保证单个分区有序,具体图示如下
kafka分区
kafka投递模式:
At most once 消息可能会丢,但绝不会重复传输
At least one 消息绝不会丢,但可能会重复传输
Exactly once 每条消息肯定会被传输一次且仅传输一次,很多时候这是用户所想要的。
默认采取At least one,消费者需要在业务层面上实现去重方案,针对一个主题,所有的消息应该有一个唯一ID标示
幂等性与事务一致的实现
幂等性
消费者代码逻辑一致性
生产者根据业务线程产生的数据,将事件进行持久化,定时调度的投递线程将标记offset 根据 mysql的自增主键序,
将消息根据其业务key值进行hash,投递到指定的kafka分区,代码里面保证messageKey一致,kafka就会投递到同一个分区中去,
保证消息在业务逻辑上是有序的。
下图的例子就是将每一个订单的更新消息都投递到一个分区中去,这样保证了业务上的有序
保证业务有序 生产者代码逻辑
顺序消费
保证顺序消费的原则就是每一个FIFO队列(这里指我们使用的kafka的分区,kafka单个分区是保证FIFO的)
每个分区在任意时刻最多只能有一个消费者线程接管它
这里在集成使用SpringCloudStream的时候,可以编写测试代码 使用ConcurrentHashMap 统计线程ID以及其消费的消息的 Kafka partion id,
顺序消费关于消费者实例宕机的问题,单个服务实例存在有可能宕机的情况,在实测中SpringCloudStream会根据配置自动将每个分区分配到不同的线程消费
正常消费的情况单个实例宕机的情况下,其余的消费者线程会自动接管宕机实例的消费分区
数据的整体流转,在代码中的具体实现
todo
代码
https://github.com/jonwinters/message_queue
参考
领域驱动设计-远程界限上下文 事件转储
网友评论