采用事件溯源重构支付功能

本文介绍了采用事件溯源重构支付功能的原因、步骤和效果。通过识别支付流程中的领域事件,如支付验证、支付成功等,实现支付逻辑的优化,解决原支付功能的并发控制和历史记录问题。重构后,代码耦合降低,并发控制通过乐观锁实现,提高了系统的健壮性和可维护性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

事件溯源是什么

        事件溯源是以时间顺序记录所发生的领域事件,之后可通过所记录的领域事件得到相应对象当前状态的一种设计理念。这种设计理念从根本上颠覆了以更新方式维护对象状态的传统方式,其优点是保存了聚合(如果还没听说过这个概念,可以先了解下DDD)的操作历史,从而为审计和数据分析提供支持;对于事件只进行插入,也就无需锁和事务,因此性能更好。缺点是数据量会更大;需要重放所有相关事件来得到当前状态;有违大多数开发人员的习惯思维方式。

为什么用事件溯源

        在为新类型单据开发支付功能的过程中发现了原支付功能中诸多不合理设计和缺陷,比如表结构(不参与查询的属性定义为表中的列,也就是可以保存为json的数据以结构化方式保存),代码不能应对并发。

        原支付功能由payment表负责保存单据的支付状态,每次支付操作的请求数据和回调数据都保存在与payment表结构完全一样的payment_history表中,两个表的唯一的区别是payment_history表的单据编号字段保存的是单据编号 + 支付次数,像这样:0001-1,0001-2。当执行任何与支付有关的操作(支付,拒绝,退款)或接收到支付接口的回调后须同时更新payment和paymeny_history两个表。

        支付功能对于任何系统的重要性都不言而喻,因此当初的设计者才会将有关支付的所有操作都记录在paymeny_history这个相当于支付日志的支付历史表中。事件溯源就是为类似这种需要完整保存历史轨迹的需求而量身打造的,但其实这并不是事件溯源的目的,而只是该设计理念所附带的好处。这就是为什么选择以事件溯源来重构支付功能的唯一原因。

如何以事件溯源进行重构

        事件溯源的核心是事件,没有事件何以溯源。所以,首先要做的就是从支付流程中识别并提取出所有领域事件。根据本系统支付业务的特点,提取出如下事件:支付数据验证通过,支付数据验证未通过,支付成功,支付失败,退款,拒绝支付。事件对象中属性的定义取决于系统的特点,并没有通用的标准,不过至少要包含事件名和时间两个核心属性。以下是本系统支付领域事件的定义。

    public static class StartPay extends Event {
        public StartPay(Long billId) {
            super(billId, StartPay.class, "开始支付");
        }
    }

    public static class Verified extends Event {
        public Verified(Long billId, String data) {
            super(billId, Verified.class, data);
        }
    }

    public static class VerificationFailed extends Event {
        public Ver
### Kafka在事件溯源中的应用与实现方案 #### 什么是事件溯源事件溯源是一种软件开发模式,其中系统的状态不是直接存储的,而是通过一系列不可变的历史事件来重建。每次发生更改时,都会记录一个新的事件而不是覆盖现有数据[^4]。 #### Kafka作为事件日志的作用 Kafka可以作为一个分布式、高吞吐量的事件日志系统,在事件溯源中扮演核心角色。它提供了持久化、分区和复制的功能,使得它可以可靠地存储大量的历史事件。由于Kafka的主题(Topic)本质上是一个有序的日志文件集合,因此非常适合用来保存事件序列[^3]。 #### 使用Kafka Streams进行流处理 为了支持复杂的业务逻辑或者实时计算需求,可以通过Kafka Streams API对流入的数据执行各种操作,比如过滤、聚合等。这允许开发者基于原始事件创建派生视图或将多个来源的信息结合起来形成更丰富的上下文信息[^1]。 #### 测试考虑 当实施涉及Kafka的应用程序时,确保有适当的质量保证措施非常重要。为此目的,可以采用专门针对此技术栈定制化的单元/集成测试框架——例如由Confluent提供的`kafka-streams-test-utils`库以及Docker-based解决方案如TestContainers For Kafka来进行模拟环境下的验证工作[^2]。 #### 最佳实践建议 - **选择合适的主题结构**: 设计合理的关键字键值映射关系以便于后续查询优化;同时也要注意控制单个分区大小以免影响性能表现。 - **保障消息顺序性**: 如果某些特定情况下要求严格的消息传递语义,则需特别关注如何配置Producer端参数以满足一致性约束条件。 - **监控健康状况**: 定期检查集群资源利用率情况并设置告警阈值防止潜在瓶颈问题扩大化传播至整个生态系统当中去。 ```java // 示例代码展示如何使用KafkaStreams构建简单的单词统计应用程序 Properties props = new Properties(); props.put(StreamsConfig.APPLICATION_ID_CONFIG, "wordcount-application"); props.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092"); final Serde<String> stringSerde = Serdes.String(); StreamsBuilder builder = new StreamsBuilder(); builder.stream("TextLinesTopic", Consumed.with(stringSerde, stringSerde)) .flatMapValues(value -> Arrays.asList(value.toLowerCase().split("\\W+"))) .groupBy((key, word) -> word) .count() .toStream() .to("WordsWithCountsTopic", Produced.with(Serdes.String(), Serdes.Long())); Topology topology = builder.build(); KafkaStreams streams = new KafkaStreams(topology, props); streams.start(); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值