领域驱动设计 2
1.幂等设计
1.1.定义
无论进行多少次相同的操作,结果都保持一致的设计。
1.2.写操作的幂等性
1.2.1.Insert
指定唯一标识写,是具有幂等性的。
不指定唯一标识写,不具备幂等性。
1.2.2.Update
如果更新操作依赖于与历史状态,则不是幂等的,反之则幂等。
例:
//无论执行多少次 count的值都为1
Update test_table set count = 1 where id = 1;
//count的最终值,取决于执行次数,所以是非幂等的
Update test_table set count = count+1 where id = 1;
1.2.3.Delete
删除操作天然幂等,因为删除之后数据就没了,再删一次,数据仍旧没了。
1.3.幂等性设计
1.3.1.唯一索引
通过给每一个操作一个requestId,并将其记录到操作记录表中,保证操作只会执行一次。如:某个操作的requestId为1,当其执行完了,则将其插入操作记录表中。当再次执行该操作时,其requestId在操作记录表中已经存在,则不应再执行该操作。流程如下:

1.3.2.有限状态机
有限状态机(简称状态机),表示有限个状态以及在这些状态之间的转移和动作等行为的模型。

2.领域事件
领域事件是聚合内已经发生的事实,代表聚合内已经发生了业务操作或状态变化。领域事件通常由聚合根产生,且因该是值对象或贫血对象。
领域事件可解耦领域对象之间的耦合度,通过发布事件通知其他对象自身发生了某个事件,代替直接调用。可实现夸聚合的数据一致性。
3.领域事件发布
例子:
public class ApplicationSevice{@AutoWiredDoMainService dms;@AutoWiredDoMainEventPublisher publisher;public void handleSomeThing(SomeCommand command){//领域服务完成某项业务,并返回领域事件List<DomainEvent> eventList = dms.doSomeThing(command);//推送领域事件publisher.publish(eventList);}
}
在上述例子中,领域服务执行完事务后,如果推送领域时间这一步执行失败,会导致完整的业务流程没有执行成功。
为了解决这个问题,可以将领域事件持久化并可靠地发布事件。
3.1.领域事件持久化
例:
public class DomainRepository{@ResourceEventRepository eventRepository;@ResourceDataRepository dataRepository;@Transactionalpublic void save(Entity entity){//获取领域事件List<DomainEvent> events = entity.getEvents();//将领域事件转换为持久化存储事件List<Event> eventList = events.stream().map(s->{......}).collect(Collectors.toList());//持久化领域事件eventRepository.saveAll(eventList);//将实体转换为是数据库对应的数据模型DataModel d = toDataModel(entity);//持久化数据模型dataRepository.save(DataModel);}
}
3.2.可靠发布领域事件
3.2.1.直接发布并补偿机制

1)领域服务在实现具体的业务时,应持久化保存领域事件,并将领域事件的状态设置为未完成发布。
2)当应用层调用领域服务完成业务逻辑处理之后,将领域服务返回的事件直接发布。
3)事件发布成功后,将数据库中事件状态更新为发布成功。
4)定时任务定时扫描最近一段时间范围内的状态为未发布成功的领域事件,并将这些事件进行发布,发布成功之后,修改其状态为发布成功。
3.2.2.事物日志拖尾
频繁地轮训数据库可能会对数据库造成压力。此时可以考虑采用事务日志拖尾的方案。事务日志拖尾,指监听数据库的事务日志,以获取增量的新数据,可通过CDC中间件来实现。常见的CDC中间件包括Debezium、Canal、Flink CDC等。

1)领域服务执行完业务逻辑之后,持久化存储领域事件。
2)CDC中间件通过监听事务日志,读取到增量的新数据。CDC中间件从数据中解析出事件,发布到消息队列中。
4.领域事件订阅
领域事件订阅需要考虑幂等性设计。事件的发布和订阅可通过消息中间件kafka实现。
5.CQRS的概念
CQRS(Command Query Responsibility Segregation)命令查询职责分离架构模式。通过不同的模型实现Command(数据修改)与Query(数据查询)分离。
6.为什么要引入CQRS?
聚合根事是务一致性的边界。开发者在处理业务时为了保证业务的准确性,需要完整的加载整个聚合根。而Query操作不一定需要完整的聚合根,可能只需要聚合根的一部分状态,且不会对状态进行修改,此时将完整的聚合根加载到内存中,可能因为读取的数据过多影响性能。所以需要将Query操作与Command操作分离开来。
在领域驱动设计的架构中,可以直接在应用层调用基础设施层服务进行查询并返回查询条件,而不用调用领域模型进行查询。
7.CQRS实现方式
7.1.方法级
一个方法要么执行Command,要么执行Query,不应在Command方法中返回View对象。
7.2.相同数据源CQRS

Command操作处于DDD应用中,Query操作处于三层贫血应用中。
7.3.异构数据源CQRS
数据的Command操作和Query操作可能使用不同的数据源。此时Command的应用仍采用DDD模型,Query操作可采用三层贫血模型。但两个数据源之间应存在同步机制,保证数据的一致性。可通过事件发布+补偿机制或者事务日志拖尾的形式实现。
相关文章:
领域驱动设计 2
1.幂等设计 1.1.定义 无论进行多少次相同的操作,结果都保持一致的设计。 1.2.写操作的幂等性 1.2.1.Insert 指定唯一标识写,是具有幂等性的。 不指定唯一标识写,不具备幂等性。 1.2.2.Update 如果更新操作依赖于与历史状态,…...
十年后LabVIEW编程知识是否会过时?
在考虑LabVIEW编程知识在未来十年内的有效性时,我们可以从几个角度进行分析: 1. 技术发展与软件更新 随着技术的快速发展,许多编程工具和平台不断更新和改进,LabVIEW也不例外。十年后,可能会有新的编程语言或平台…...
ARM交叉编译Boost库
Boost下载:点击跳转 编译过程: 生成project-config.jam ./bootstrap.sh --with-librariesfilesystem,thread --with-toolsetgcc 2. 修改project-config.jam(位于第12行附近) if ! gcc in [ feature.values <toolset> ] …...
uniapp:钉钉小程序需要录音权限及调用录音
{// ... 其他配置项"mp-dingtalk": {"permission": {"scope.userLocation" : {"desc" : "系统希望获得您的定位用于确认您周围的设施数据"},"scope.bluetooth" : {"desc" : "你的蓝牙权限将用于小…...
Swin Transformer模型详解(附pytorch实现)
写在前面 Swin Transformer(Shifted Window Transformer)是一种新颖的视觉Transformer模型,在2021年由微软亚洲研究院提出。这一模型提出了一种基于局部窗口的自注意力机制,显著改善了Vision Transformer(ViT…...
gitee 使用教程
前言 Gitee 是一个中国的开源代码托管平台,类似于 GitHub,旨在为开发者提供一个高效、稳定、安全的代码管理和协作开发环境。Gitee 支持 Git 协议,可以托管 Git 仓库,进行版本控制、代码协作、项目管理等操作。 1. Gitee 的主要…...
基于YOLOv8的水下目标检测系统
基于YOLOv8的水下目标检测系统 (价格90) 使用的是DUO水下目标检测数据集 训练集 6671张 验证集 1111张 测试集 1111张 包含 [holothurian, echinus, scallop, starfish] [海参, 海胆, 扇贝, 海星] 4个类 通过PYQT构建UI界面,包含图片检测,视…...
浅析PCIe链路均衡技术原理与演进
在现代计算机硬件体系的持续演进中,PCIe技术始终扮演着核心角色,其作为连接 CPU 与各类周边设备的关键高速通信链路,不断推动着计算机性能边界的拓展。而 PCIe Link Equalization均衡技术,作为保障数据在高速传输过程中准确性与稳…...
js代理模式
允许在不改变原始对象的情况下,通过代理对象来访问原始对象。代理对象可以在访问原始对象之前或之后,添加一些额外的逻辑或功能。 科学上网过程 一般情况下,在访问国外的网站,会显示无法访问 因为在dns解析过程,这些ip被禁止解析,所以显示无法访问 引…...
C++虚函数(八股总结)
什么是虚函数 虚函数是在父类中定义的一种特殊类型的函数,允许子类重写该函数以适应其自身需求。虚函数的调用取决于对象的实际类型,而不是指针或引用类型。通过将函数声明为虚函数,可以使继承层次结构中的每个子类都能够使用其自己的实现&a…...
vue的路由守卫逻辑处理不当导致部署在nginx上无法捕捉后端异步响应消息等问题
近期对前端的路由卫士有了更多的认识。 何为路由守卫?这可能是一种约定俗成的名称。就是VUE中的自定义函数,用来处理路由跳转。 import { createRouter, createWebHashHistory } from "vue-router";const router createRouter({history: cr…...
[备忘.OFD]OFD是什么、OFD与PDF格式文件的互转换
OFD(Open Fixed-layout Document)是一种由工业和信息化部软件司牵头中国电子技术标准化研究院制定的版式文档国家标准,属于中国的一种自主格式。OFD旨在打破政府部门和党委机关电子公文格式不统一的问题,以方便电子文档的存…...
Pycharm连接远程解释器
这里写目录标题 0 前言1 给项目添加解释器2 通过SSH连接3 找到远程服务器的torch环境所对应的python路径,并设置同步映射(1)配置服务器的系统环境(2)配置服务器的conda环境 4 进入到程序入口(main.py&#…...
嵌入式系统 tensorflow
🎬 秋野酱:《个人主页》 🔥 个人专栏:《Java专栏》《Python专栏》 ⛺️心若有所向往,何惧道阻且长 文章目录 探索嵌入式系统中的 TensorFlow:机遇与挑战一、TensorFlow 适配嵌入式的优势二、面临的硬件瓶颈三、软件优化策略四、实…...
深度学习知识点:LSTM
文章目录 1.应用现状2.发展历史3.基本结构4.LSTM和RNN的差异 1.应用现状 长短期记忆神经网络(LSTM)是一种特殊的循环神经网络(RNN)。原始的RNN在训练中,随着训练时间的加长以及网络层数的增多,很容易出现梯度爆炸或者梯度消失的问…...
11.C语言内存管理与常用内存操作函数解析
目录 1.简介2.void 指针3.malloc4.free5.calloc6.realloc7.restrict 说明符8.memcpy9.memmove()10.memcmp 1.简介 本篇原文为:C语言内存管理与常用内存操作函数解析。 更多C进阶、rust、python、逆向等等教程,可点击此链接查看:酷程网 C 语…...
Python 中的错误处理与调试技巧
💖 欢迎来到我的博客! 非常高兴能在这里与您相遇。在这里,您不仅能获得有趣的技术分享,还能感受到轻松愉快的氛围。无论您是编程新手,还是资深开发者,都能在这里找到属于您的知识宝藏,学习和成长…...
门禁系统与消防报警的几种联动方式
1、规范中要求的出入口系统与消防联动 1.1《建筑设计防火规范》GB 50016-2018 1.2《民用建筑电气设计规范》JGJ 16-2008 14.4出入口控制系统 3 设置在平安疏散口的出入口限制装置,应与火灾自动报警系统联动;在紧急状况下应自动释放出入口限制系统&…...
云原生安全风险分析
一、什么是云原生安全 云原生安全包含两层含义: 面向云原生环境的安全具有云原生特征的安全 0x1:面向云原生环境的安全 面向云原生环境的安全的目标是防护云原生环境中基础设施、编排系统和微服务等系统的安全。 这类安全机制不一定具备云原生的特性…...
解决cursor50次使用限制问题并恢复账号次数
视频内容: 在这个视频教程中,我们将演示如何解决科sir软件50次使用限制的问题,具体步骤包括删除和注销账号、重新登录并刷新次数。教程详细展示了如何使用官网操作将账号的剩余次数恢复到250次,并进行软件功能测试。通过简单的操…...
业务系统对接大模型的基础方案:架构设计与关键步骤
业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...
【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...
树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...
sqlserver 根据指定字符 解析拼接字符串
DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...
SpringCloudGateway 自定义局部过滤器
场景: 将所有请求转化为同一路径请求(方便穿网配置)在请求头内标识原来路径,然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...
LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf
FTP 客服管理系统 实现kefu123登录,不允许匿名访问,kefu只能访问/data/kefu目录,不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...
MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...
基于鸿蒙(HarmonyOS5)的打车小程序
1. 开发环境准备 安装DevEco Studio (鸿蒙官方IDE)配置HarmonyOS SDK申请开发者账号和必要的API密钥 2. 项目结构设计 ├── entry │ ├── src │ │ ├── main │ │ │ ├── ets │ │ │ │ ├── pages │ │ │ │ │ ├── H…...
