分布式事务、CAP定理、事件总线,在当前微服务、分布式、集群大行其道的架构前提下,是不可逃避的几个关键字,在此不会过多阐述相关的理论知识。Shashlik.EventBus
就是一个基于.NET6的开源事件总线解决方案,同时也是分布式事务最终一致性、延迟事件解决方案。Shashlik.EventBus
采用的是异步确保的思路(本地消息表),将消息数据与业务数据在同一事务中进行提交或回滚,以此来保证消息数据的可靠性。其设计目标是高性能、简单、易用、易扩展,为抛弃历史包袱,仅支持NET6,采用最宽松的 MIT 开源协议。
https://github.com/dotnet-shashlik/shashlik.eventbus
各位爷高兴了给个star呗。
如图所示,消息数据需要和业务数据在同一的事务中进行提交或者回滚,最后Shashlik.EventBus会检查消息数据是否已提交,如果已提交才会执行真正的消息发送。所以要求事务的隔离级别最低为读已提交(RC)。
关于消息幂等
Shashlik.EventBus不能保证业务消息的幂等性,为了保证消息的可靠传输,EventBus以及消息中间件对消息QOS处理等级必须为at least once (至少到达一次),一般消息中间件都需要开启消息持久化避免消息丢失。简而言之就是一个事件处理类可能处理多次同一个事件,事件消息的幂等性应该由业务方进行处理。比如用户订单付款完成为一个事件,付款完成后需要修改订单状态为待发货,也就是在付款完成事件处理类中可能收到多次这个订单的付款完成事件,那么业务的幂等性处理就可以使用锁,判断订单状态,如果订单状态已经为待发货,则直接返回并忽略本次事件响应。
延迟事件
Shashlik.EventBus支持基于本地的延迟事件机制,考虑到不是所有的消息中间件都支持延迟功能,且为了最大程度保证消息的可靠性,最后采用了System.Timers.Timer来执行延迟功能。
延迟事件同样适用于分布式事务最终一致性,但如果延迟事件处理类处理异常由重试器介入处理后,那么最终的延迟执行时间和期望的延迟时间就会产生较大的差异,是否忽略这里的时间差需要由具体的业务来决定。比如订单30分钟未付款需要关闭订单,30分钟后关闭订单出现了异常,最后由重试器到了40分钟后才关闭,也不影响订单,那么认为这个时间差可以容忍。又比如双11啦,发布一个延迟事件,晚上12点叫醒我起来买买买,只有1分钟时间,过了就买不到了,那么这种情况可以在事件处理类中,自行根据当前时间、事件发送时间、延迟执行时间等要素,自行决定业务如何处理。
延迟事件和普通事件在事件定义和事件处理类声明和处理时没有任何区别,仅仅是在发布事件时需要指定延迟时间。
上代码
需求:一个新用户注册以后有