关于ddd:一条拍卖系统优化一-建立拍品Lot模型实践CQRS

42次阅读

共计 1972 个字符,预计需要花费 5 分钟才能阅读完成。

分享一下组内小伙伴张聪、庆红在年初对拍卖领域建模的总结

一、背景:原拍卖零碎设计 (基于数据模型)
原拍卖零碎的构建了 SkuBidRedisInfo(数据对象)用来记录拍品在竞拍中的热点信息,并且将这个实体放入 Redis 中。

在拍品的生命周期中间接应用 SkuBidRedisInfo 进行逻辑判断,尽管通过 SkuBidRedisInfo(拍品)和 AuctionSkuDTO(拍品)结构了 InnerSkuLotInfo(仅作为一个 Value object)对象,然而 InnerSkuLotInfo 并不能残缺的形容一个拍品残缺的生命周期比方 竞拍前、竞拍中、竞拍完结、生成订单中等状态。

二、重构拍卖设计及改良过程

  1. 裁减数据对象 LotRedisInfo 信息,简化结构过程:

通过 LotRedisInfo 存储拍品在竞拍中的信息,竞拍期间仅依赖 LotRedisInfo 即可构建拍品实体。一方面通过双写 AuctionSkuDTO 以及 LotRedisInfo,放弃竞拍中的数据一致性;另一方面简化了原有拍品实体构建的过程,失去更好的性能晋升;

  1. 构建拍品畛域实体 Lot,定义了拍品的不同生命周期、以及各个生命周期的行为:

这里咱们的初始做法是将 Lot 的构建分为两种状况:1、竞拍中的拍品 Lot,利用 LotRedisInfo 进行结构,2、非竞拍中的拍品,从 DB 中取出数据结构 Lot,放入 Local&Redis 缓存;

拍品生命周期内的行为

3. 围绕实体进行数据变更:

当拍品信息产生变更时,比方开拍、出价、截拍、成交等行为产生,咱们通过变更 Lot,在基于 Lot 实体转化失去须要长久化的 AuctionSkuDTO 或 LotRedisInfo,进行长久化;

长久化的过程如下:

变更 Lot 自身的信息

这里长久化 Lot 信息的时候,咱们会依据 Lot 的预期截止工夫和 Lot 对应 InnerActivityInfo 的预期截止工夫比拟判断是否须要延期流动截止工夫,这里对 InnerActivityInfo 的信息进行批改并且长久化刷新缓存(潜在问题 1)

长久化 Lot 信息 , Lot 导出相应的 AuctionSkuDTO(长久到 DB)、流动未完结 LotRedisInfo(长久到 Redis)

  1. 新模型存在的问题

这里 Lot 畛域实体的构建曾经可能详细描述一个拍品的残缺生命周期及各个行为,然而存在两个问题:

问题 1:InnerActivityInfo 的批改不平安:

咱们在构建 Lot 的时候,依赖了流动信息的实体 InnerActivityInfo, 然而 InnerActivityInfo 在 Lot 的整个生命周期外面并不是固定不变的,咱们通过一个 InnerActivityInfo A 构建了一个 Lot A,这个时候如果有其余 Lot 信息变更,导致 InnerActivityInfo 产生了变更,那么 Lot A 中应用了 InnerActivityInfo A 的局部信息就可能是脏数据了;

问题 2:因为引入了 Lot 在零碎中存在了存储正本(缓存),对于 Lot 的读写存在了不统一:

利用实例 A 获取拍品 Lot 的本地缓存 Lot A,而后对 Lot A 进行批改,比方批改拍品程序,长久化,这个场景在单实例下没有问题,然而多实例下,如果在 A 操作之前,如果利用实例 B 上也想对同一个拍品 Lot 进行批改,读取本地缓存 Lot B 批改了起拍价,长久化,那么利用实例 A 上读出来的数据就是脏数据,那么通过一系列操作,A 只是想批改一个拍品程序,然而却把 B 批改起拍价的数据给笼罩了, 问题的要害就是咱们不能基于缓存进行信息变更,再长久化到数据库;

解决方案:

问题 1 —- 解决方案:对象隔离

在 Lot 中咱们不要强依赖 InnerActivityInfo 实体,而是每次应用时,传入一个最新的 InnerActivityInfo(最佳做法是传递一个只读正本),这样就保障了在 Lot 的生命周期中,每次应用到 InnerActivityInfo 的相干信息都是最新的(这个是不是 InnerActivityInfo 的一致性问题由 InnerActivityInfo 保障,通过其畛域服务进行对应的批改);

问题 2 —– 解决方案:CQRS,将拍品分为两种实体 ReadonlyLot(只读实体)、ReadWriteLot(可读写实体)

ReadonlyLot 不蕴含对本身信息变更的能力,这样防止了误用。咱们的内存 cache 和缓存都是建设在 ReadonlyLot 上的可能会读取到过期数据,但写场景是不容许过期数据的读取(写建设在读上,读过期,会产生写笼罩问题),通过实体层面的隔离咱们杜绝了这种过期读的产生。当咱们须要批改 Lot 的信息时,即便咱们获取了 ReadonlyLot,也无奈对其进行信息变更,从根本上杜绝了这种不平安公布的产生。

ReadonlyLot&ReadWriteLot

ReadonlyLot、ReadWriteLot 的构建

正文完
 0