DDD与微服务的千丝万缕
- 一、软件设计发展过程
- 二、什么是DDD?
- 2.1 战略设计
- 2.2 战术设计
- 2.3 名词扫盲
- 1. 领域和子域
- 2. 核心域、通用域和支撑域
- 3. 通用语言
- 4. 限界上下文
- 5. 实体和值对象
- 6. 聚合和聚合根
- 2.4 事件风暴
- 2.5 领域事件
- 三、DDD与微服务
- 3.1 DDD与微服务的关系
- 3.2 基于DDD进行微服务设计
- 3.3 基于DDD重构中台业务模型
- 1. 自顶向下
- 2. 自底向上
- 四、总结
一、软件设计发展过程
软件架构模式大体上经历了从单机架构 -> 集中式架构 -> 分布式微服务三个阶段的架构演进。
在单机和集中式架构模式下,软件无法快速响应需求和业务的迅速变化,直到微服务架构时代的来临。微服务架构解决了单机和集中式架构的很多问题,比如扩展性、弹性伸缩性、小规模团队的敏捷开发等。
但是,带来好处的同时,微服务实践过程中也产生了不少争议性的问题:“微服务到底应该怎么拆分和设计才算合理,拆多小才叫微服务”,而微服务的边界历来也是最容易产生争议的地方。
二、什么是DDD?
2004年埃里克·埃文斯发表了《领域驱动设计》这本书,DDD(Domain Driven Design)由此诞生。
DDD核心思想是通过领域驱动设计方法定义领域模型,从而确定业务和应用边界,保证业务模式和系统架构模式的一致性。
DDD不是架构,而是一种架构设计方法论,它通过边界划分将复杂的业务领域简单化,从而设计出清晰的领域和应用边界,进而可以非常容易地实现架构演进。
DDD主要包括战略设计和战术设计两大部分。
- 战略设计主要从业务视角出发,建立业务领域模型,划分领域边界,建立通用语言的限界上下文,而限界上下文可以作为微服务划分的主要参考边界。
- 战术设计主要从技术视角出发,侧重于领域模型的技术实现,完成软件开发的落地,包括聚合、聚合根、实体、值对象、领域服务、应用服务和资源库等代码逻辑的设计和实现。
2.1 战略设计
DDD 战略设计主要从业务视角出发,建立业务领域模型,领域模型可以用于指导微服务的设计和拆分。事件风暴是建立领域模型的主要方法,它是一个从发散到收敛的过程。
什么是事件风暴?
事件风暴是一种协作的过程,通常采用用例分析、业务场景分析和用户旅程分析等,尽可能全面不遗漏地分解业务领域,并梳理领域对象之间的关系,这是一个发散的过程。事件风暴过程会产生很多实体、命令、事件等领域对象,通过将这些领域对象从不同维度进行聚类(将数据集中的对象或数据点按照某种相似性或相关性的标准分成不同的组别,即“簇”。聚类的目标是将相似的数据点分到同一簇中,使得同一簇内的数据点之间更加相似,而不同簇之间的数据点相对较不相似。),形成聚合、聚合根、限界上下文等边界,建立领域模型,这是一个收敛的过程。
事件风暴可以帮助开发团队、业务团队共同理解和共享对业务领域的见解,有助于捕获关键的业务事件(领域事件)、过程和概念,以指导软件系统的设计和实施,从而更好地支撑业务需求落地。此外,事件风暴有助于提高团队的沟通、协助和业务理解能力。
在战略设计中建立了领域模型,划定了业务领域的边界,并建立了通用语言和限界上下文,确定了领域模型中各个领域对象的关系,如上图所示。
2.2 战术设计
当领域模型的设计工作完成后,基本也就确定了应用端的微服务边界。在从领域模型向微服务架构设计落地的过程中,也就是从战略设计向战术设计的实施过程中,开发人员会将领域模型中的领域对象(聚合、聚合根、实体、值对象等)与代码模型中的对象建立映射关系(可以通过表格进行罗列记录),将业务架构和系统架构进行绑定。
战术设计则从技术视角出发,侧重于领域模型的技术实现,完成软件开发和落地,包括:聚合根、实体、值对象、领域服务、应用服务和资源库等代码逻辑的设计和实现。
经验:
可通过 Excel 表格记录、罗列战术设计中的聚合根、实体、值对象等关系、属性
2.3 名词扫盲
DDD 的知识体系提出了很多的名词,像:领域、子域、核心域、通用域、支撑域、通用语言、限界上下文、聚合、聚合根、实体、值对象等等,非常多,下面一一进行解释。
1. 领域和子域
领域,指的是一个特定业务领域或问题领域,它通常涉及一组相关的业务规则、概念和数据。领域可以进一步划分为子领域,我们把划分出来的多个子领域称为子域,每个子域对应一个更小的问题域或更小的业务范围。
2. 核心域、通用域和支撑域
在领域不断划分的过程中,领域会细分为不同的子域,子域可以根据自身重要性和功能属性划分为三类子域,它们分别是:核心域、通用域和支撑域。
- 核心域:决定产品和公司核心竞争力的子域。**核心域是业务成功的主要因素和公司的核心竞争力。**如平安的保险。
- 通用域:没有太多个性化诉求,同时被多个子域使用的通用功能子域。如系统权限、合同。
- 支撑域:既不包含决定产品和公司核心竞争力的功能,也不包含通用功能的子域。如数据字典系统。
3. 通用语言
在事件风暴的过程中,领域专家、业务人员、开发人员会一起建立领域模型,在领域建模的过程中会形成通用的业务术语和用户故事,进而形成能够简单、清晰、准确描述业务含义和规则的通用语言。通用语言可以解决交流障碍问题,使得领域专家、业务人员和开发人员能够更加高效的协同合作,进而确保业务需求的正确表达与落地。
通用语言贯穿 DDD 的整个设计过程(事件风暴 -> 领域故事分析 -> 提取领域对象 -> 领域对象与代码模型映射 -> 代码落地),基于通用语言,可以设计出可读性更好的代码,将业务需求准确转化为代码设计。
4. 限界上下文
任何语言都存在语义环境的,在不同的时空和背景下,同一句话会存在不同的含义,比如语言:“衣服能穿多少就穿多少。”,在夏天表就是要穿少一点儿,冬天却表示需要穿的很多。所以DDD的通用语言也存在它的语义环境,为了避免同样的概念或语义在不同的环境中产生企业,DDD提出了 限界上下文 用来确定语义所在的领域边界。限界上下文可以通过将其拆分为限界、上下文来进行理解。
- 限界:领域的边界;
- 上下文:语义环境;
限界上下文是用来封装通用语言和领域对象,提供上下文环境,保证在领域内的一些术语、业务相关对象等有一个唯一的含义。例如,在电商领域中,商品在不同阶段存在不同的含义,在销售、售卖时是商品,在打包运输时则为货物,所以在销售领域和运输领域之间,存在限界上下文,如下:
限界上下文是微服务设计和拆分的主要依据,它确定了微服务的设计和拆分方向,在事件风暴中,领域专家、架构师和开发人员的主要工作就是划分限界上下文。理论上,可以将一个限界上下文设计为一个微服务,当然还需根据其他限制因素考虑,防止过度拆分。
5. 实体和值对象
实体和值对象都是用来表示领域模型中的事物或概念的重要元素。它们有不同的特性和用途。实体和值对象是组成领域模型的基础单元。
- 实体:通常代表领域中的具体事务,具体唯一标识、生命周期和状态,并且可以被识别、跟踪和区分。领域模型中的实体是多个属性、操作或行为的载体。在事件风暴中,我们可以根据命令、操作或事件,找出产生这些行为的业务实体对象。
- 值对象:通常将多个相关属性组成的集合称为一个值对象。值对象没有唯一标识,是不可变的,通常用来表示领域中的属性和特性,帮助描述实体的特性。
实体一般对应业务对象,它具有业务属性和业务行为。而值对象主要是多个相关属性集合,对实体的状态和特征进行描述。例如人员实体原本包括:姓名、身份证号、性别、年龄以及所在省、市、县和街道等属性。我们可以将 “省、市、县和街道等属性” 抽离出来,构建一个地址属性集合,这个集合对象就是值对象。如下:
一个实体可以存在多个值对象。
6. 聚合和聚合根
由业务和逻辑紧密关联的实体和值对象组合而成的对象称为聚合。聚合都存在一个聚合根和上下文边界。聚合是数据修改和持久化的基本单位。
- 聚合根:如果把聚合比作组织,那聚合根就是这个组织的 “头”。聚合根也称为根实体,它不仅是实体,还是聚合的管理者,在聚合之间,还是聚合对外的接口人,以聚合根ID 关联的方式接受外部任务和请求,在上下文内实现聚合之间的业务协同。聚合之间通过聚合根ID关联引用,如果需要访问其他聚合的实体,需要先访问聚合根,再通过聚合根导航到聚合内部实体,外部对象不能直接访问聚合内实体。
- 上下文边界:上下文边界根据业务单一职责和高内聚原则,定义了聚合内部应该包含那些实体和值对象,而聚合之间的边界是松耦合的。按照这种方式设计出来的微服务很自然就满足“高内聚、低耦合”的特点。
如何设计聚合???
DDD 领域建模通常采用事件风暴,通过用例分析、场景分析和用户旅程分析等方法,列出所有可能的业务行为和事件,然后找出产生这些行为的领域对象,并梳理领域对象之间的关系,找出聚合根,找出与聚合根业务紧密关联的实体和值对象,再将聚合根、实体和值对象组合,构建聚合。
下面我们以大家都熟悉的学校选课业务场景为例,看一下聚合的构建过程主要包括哪些步骤。
第一步:采用事件风暴,通过用例分析、场景分析和用户旅程分析等方法,如下,梳理出在选课过程中发生这些行为的所有的实体和值对象,比如课程、老师、学生、选课规则、上课时间等等。
- 老师通过账号登录教务系统,发布课程相关信息,包括课程学分、上课地址、上课时间、选课规则等。
- 学生通过账号登录教务系统,进行选课。
第二步:从众多实体中选出适合作为对象管理者的根实体,既聚合根。
如何判断一个实体是否为聚合根:可以通过是否有独立的生命周期?是否有全局唯一ID? 是否可以创建或修改其它对象?是否有专门的模块来管这个实体。图中的聚合根分别是课程和用户实体。
第三步:根据业务单一职责和高内聚原则,找出与聚合根关联的所有紧密依赖的实体和值对象。构建出1个包含聚合根(唯一)、多个实体和值对象的对象聚合,在图中我们构建了课程和用户这两个聚合。
第四步:在聚合内根据聚合根、实体和值对象的依赖关系,画出对象的引用和依赖模型。
第五步:多个聚合根据业务语义和上下文一起划分到同一个限界上下文内。
聚合的设计原则:
- 单一职责:聚合内的每个实体和值对象应该具有单一责任。它们应该专注于执行特定的任务,而不应该包含不相关的功能。
- 保持事务边界:聚合应该定义一个明确的事务边界。这意味着所有聚合内的实体和值对象应该作为一个整体一起加载、保存和维护。在跨聚合的操作中,事务应该在每个聚合内进行管理,实现对象数据的一致性,这就是聚合能实现业务高内聚的原因。
- 通过唯一标识引用其它聚合:聚合之间是通过关联外部聚合根ID 的方式引用,而不是直接对象引用的方式。外部聚合的对象放在聚合边界内管理,容易导致聚合的边界不清晰,也会增加聚合之间的耦合度。
- 设计小聚合:如果聚合设计得过大,聚合会因为包含过多的实体,导致实体之间的管理过于复杂,高频操作时会出现并发冲突或者数据库锁,最终导致系统可用性变差。而小聚合设计则可以降低由于业务过大导致聚合重构的可能性,让领域模型更能适应业务的变化。
- 高内聚:聚合内的实体和值对象应该具有高内聚性,即它们应该紧密相关,共同支持聚合的目标。
这些原则有助于创建具有高内聚性、低耦合性和良好一致性的聚合,从而更好地管理领域中的复杂性。在DDD中,良好的聚合设计有助于将复杂的领域问题划分为更容易管理和理解的单元。
2.4 事件风暴
事件风暴是一种协作的过程,通常采用用例分析、业务场景分析和用户旅程分析等,尽可能全面不遗漏地分解业务领域,并梳理领域对象之间的关系,这是一个发散的过程。事件风暴过程会产生很多实体、命令、事件等领域对象,通过将这些领域对象从不同维度进行聚类(将数据集中的对象或数据点按照某种相似性或相关性的标准分成不同的组别,即“簇”。聚类的目标是将相似的数据点分到同一簇中,使得同一簇内的数据点之间更加相似,而不同簇之间的数据点相对较不相似。),形成聚合、聚合根、上下文边界、限界上下文等边界,建立领域模型,这是一个收敛的过程。
事件风暴可以帮助开发团队、业务团队共同理解和共享对业务领域的见解,有助于捕获关键的业务事件(领域事件)、过程和概念,以指导软件系统的设计和实施,从而更好地支撑业务需求落地。此外,事件风暴有助于提高团队的沟通、协助和业务理解能力。事件风暴的过程可以大概分为以下几步:
- 会议准备: 确认会议参与者,通常包括领域专家、业务领域、开发人员等;明确风暴目标,确定需要解决的具体业务问题或挑战,以便确保风暴的焦点明确。
- 会议进行: 会议参与者一起聚焦本次会议需要解决的特定业务问题或理解领域概念。通常采用用例分析、业务场景分析和用户旅程分析 等,尽可能全面不遗漏地分解业务领域。
- 识别事件: 团队开始识别与业务问题或领域相关的事件。事件是业务过程中的关键时刻或状态变化。每个事件都应该有一个名称,例如,“用户注册”或“订单支付”。
- 绘制事件流: 将事件以时间顺序的方式进行绘制,以创建一个事件流。在事件流中,每个事件都有自己的标记,通常包括事件的名称、触发条件、内容和结果。事件之间可以使用箭头表示它们的顺序关系。
- 添加领域概念: 在事件风暴期间,团队还会标识和讨论与事件相关的领域概念,如聚合、聚合根、实体、值对象等。这有助于明确事件与领域中的关键概念之间的关系。
- 讨论和澄清: 团队成员之间会讨论事件和概念,澄清不明确的地方,确保大家对业务领域有一致的理解。
- 可视化领域: 通过可视化,团队能够更好地理解和共享对业务领域的见解。事件和概念的可视化帮助团队在整个过程中保持一致性。
- 生成模型: 根据事件风暴的结果,可以生成领域模型或其他文档,用于指导软件系统的设计和开发。这些模型通常包括领域对象、聚合根、实体和事件。
- 制定项目计划: 最后,团队制定项目计划,包括开发、测试和迭代的任务等。
事件风暴是一种非常有用的工具,用于在项目的早期阶段构建共享理解和对业务领域进行深入挖掘。它有助于软件团队更好地满足业务需求,确保领域知识的一致性,并提高团队协作的效率。
2.5 领域事件
在进行事件风暴时,除了命令和操作等业务行为以外,还有一种非常重要的事件,这种事件发生后通常会导致进一步的业务操作,例如:当老师做完课程信息上传时,需在某一个时间后通知学生进行选课,在 DDD 中这种事件被称为领域事件。
领域事件是领域模型中非常重要的一部分,用来表示领域中发生的事件。一个领域事件将导致进一步的业务操作,在实现业务解耦的同时,还有助于形成完整的业务闭环。领域事件也是微服务解耦的关键。
- 领域事件可以是业务流程的一个步骤,比如学生选课完成后,触发学生当前学期课程列表动作;
- 也可能是定时批处理过程中发生的事件,比如批处理选手选课情况,触发选课邮件通知操作;
- 或者一个事件发生后触发的后续动作,比如密码连续输错三次,触发锁定账户的动作。
如何识别领域事件呢?
在做用例分析、业务场景分析和用户旅程分析时,我们要捕捉业务、需求人员或领域专家口中的关键词:“如果发生……,则……”、“当做完……的时候,请通知……”、“发生……时,则……”等。在这些场景中,如果发生某种事件后,会触发进一步的操作,那么这个事件很可能就是领域事件。
领域事件有的发生在微服务内,有的发生在微服务之间,还有两者皆有的场景,一般跨微服务的领域事件大多会用到消息中间件,实现跨微服务的事件发布/订阅。消息中间件的产品非常成熟,市场上可选的技术也非常多,比如RabbitMQ、Kafka、RocketMQ等。
三、DDD与微服务
3.1 DDD与微服务的关系
DDD 是一种架构设计方法,微服务是一种架构风格,两者都强调从业务出发,其核心要义是强调根据业务发展,合理划分领域边界,持续调整现有架构,优化现有代码,以保持架构和代码的生命力,也就是我们常说的演进式架构。
- DDD 主要关注:从业务领域视角划分领域边界,构建通用语言进行高效沟通,通过业务抽象,建立领域模型,维持业务和代码的逻辑一致性。
- 微服务主要关注:服务设计、拆分,运行时的进程间通信、容错和故障隔离,实现去中心化数据管理和去中心化服务治理,关注微服务的独立开发、测试、构建和部署。
DDD 强调领域模型和微服务设计的一体性,先有领域模型然后才有微服务,而不是脱离领域模型来谈微服务设计。首先通过DDD战略设计,建立领域模型,划分微服务边界,每个边界都由一个或多个领域模型或聚合组成。然后通过战术设计,将领域模型转化为微服务设计,并进行落地。
3.2 基于DDD进行微服务设计
DDD 包括战略设计和战术设计两部分。
-
战略设计:战略设计主要从业务视角出发,建立业务领域模型,划分领域边界,建立通用语言的限界上下文,限界上下文可以作为微服务设计的参考边界。 战略设计通过事件风暴,通常采用用例分析、业务场景分析和用户旅程分析等,找出领域对象和聚合根,对实体和值对象进行聚类组成聚合,划分限界上下文,建立领域模型的过程。
- 战略设计主要包括产品愿景、用例分析、业务场景分析、用户旅程分析、领域建模和微服务拆分等几个主要过程。
- 战略设计阶段建议参与人员:领域专家、业务需求方、产品经理、架构师、项目经理、开发 经理和测试经理。
-
战术设计:战术设计侧重于从技术视角出发,根据领域模型进行微服务设计。这个阶段主要梳理微服务内的领域对象, 梳理领域对象之间的关系,确定它们在代码模型和分层架构中的位置,建立领域模型与微服务模型的映射关系,以及服务之间的依赖关系,进而完成软件开发和落地,主要包括:聚合根、实体、值对象、领域服务、应用服务和资源库等代码逻辑的设计和实现。
- 战术设计包括以下两个阶段:分析微服务领域对象和设计微服务代码结构。
- 分析微服务领域对象;
- 设计微服务代码结构;
- 战术设计阶段建议参与人员:领域专家、产品经理、架构师、项目经理、开发经理和测试经理等。
- 战术设计包括以下两个阶段:分析微服务领域对象和设计微服务代码结构。
3.3 基于DDD重构中台业务模型
“中台” 是一种在软件和业务领域中经常使用的概念,它涉及到软件系统和业务流程的架构和设计。
中台的核心思想是将系统或业务流程中的共享资源、功能和服务抽象成一个中间层,以便多个应用程序或模块可以共享和重用这些资源。这种架构方法有助于提高系统的效率、可维护性和可扩展性,同时减少了冗余工作和开发成本。
中台的设计思想与“高内聚、低耦合”的设计原则是高度一致的。高内聚是把相关的业务行为聚集在一起,把不相关的行为放在其它地方,按照“高内聚、松耦合”的原则,实现企业级的能力复用。
中台的目标是通过资源共享、业务模块化、标准化接口和降低复杂度,使企业的IT系统更具弹性,更容易适应快速变化的业务需求。
将重复的需要共享的通用能力、核心能力沉淀到中台,将分离的业务能力重组为完整的业务板块,构建可复用的中台业务模型。中台业务建模有自顶向下和自底向上两种策略,这两种策略有自己的适用场景,你需要结合自己公司的情况选择合适的策略。
1. 自顶向下
自顶向下策略是先做顶层设计,从最高领域逐级分解为中台,分别建立领域模型,根据业务属性分为通用中台或核心中台。领域建模过程主要基于业务现状,暂时不考虑系统现状。自顶向下的策略适用于全新的应用系统建设,或旧系统推倒重建的情况。
由于这种策略不必受限于现有系统,你可以用 DDD 领域逐级分解的领域建模方法。从下面这张图我们可以看出它的主要步骤:
- 第一步是将领域分解为子域,子域可以分为核心域、通用域和支撑域;
- 第二步是对子域建模,划分领域边界,建立领域模型和限界上下文;
- 第三步是根据限界上下文进行微服务设计。
2. 自底向上
自底向上种策略是基于业务和系统现状完成领域建模。首先分别完成系统所在业务域的领域建模;然后对齐业务域,找出具有同类或相似业务功能的领域模型,对比分析领域模型的差异,重组领域对象,重构领域模型。这个过程会沉淀公共和复用的业务能力,会将分散的业务模型整合。自底向上策略适用于遗留系统业务模型的演进式重构。
如何采用自底向 上的策略来构建中台业务模型,主要分为这样三个步骤。
-
第一步:锁定各个系统所在业务域,构建领域模型。
锁定各个系统所在的业务域,采用事件风暴,找出领域对象,构建聚合,划分限界上下文,建立领域模型。那在构建中台业务模型时,需要重点关注那些存在业务能力重复的领域模型,将这些不同领域模型中重复的业务能力沉淀到中台业务模型中,将分散的领域模型整合到统一的中台业务模型中,对外提供统一的共享的中台服务。 -
第二步:对齐业务域,构建中台业务模型。
构建多业务域的中台业务模型的过程,就是找出同一业务域内所有同类业务的领域模型,对比分析域内领域模型和聚合的差异和共同点,打破原有的模型,完成新的中台业务模型重组或归并的过程。构建中台业务模型的要点总结成一句话就是:“分域建模型,找准基准域,划定上下文,聚合重归类。” -
第三步:中台归类,根据领域模型设计微服务。
完成中台业务建模后,就可以通过其领域模型中看到总共需要构建了多少个中台,中台下面有哪些领域模型,哪些中台是通用中台,哪些中台是核心中台,中台的基本信息等等,都一目了然。最后就可以根据中台下的领域模型进行微服务的设计。
四、总结
我认为,要想应用 DDD,首要任务就是要吃透 DDD 的核心设计思想,搞清楚 DDD、微服务和中台之间的关系。中台本质是业务模型,微服务是业务模型的具体实现,DDD 是一种设计思想,它可以同时指导中台业务建模和微服务设计,它们之间就是这样的一个铁三角关系。DDD 强调领域模型和微服务设计的一体性,先有领域模型然后才有微服务,而不是脱离领域模型来谈微服务设计。DDD主要包括战略设计和战术设计两大部分。战略设计用于定义领域模型,确定业务边界,这对于中台和微服务的构建至关重要。在战术设计阶段,你需要将领域模型映射到微服务设计中,并严格遵循DDD原则,确保微服务与领域模型保持一致性。
拥有一套清晰的微服务设计和拆分方法是确保微服务架构的成功的关键。这种方法可以帮助你建立清晰的微服务边界,确保微服务系统的可维护性和可持续演进。
最终,DDD、中台和微服务的结合可以为企业提供高度灵活性和创新性,帮助他们更好地应对不断变化的市场需求。这种铁三角关系可以帮助企业建立坚实的技术基础,实现持续增长和竞争优势。
相关文章:

DDD与微服务的千丝万缕
一、软件设计发展过程二、什么是DDD?2.1 战略设计2.2 战术设计2.3 名词扫盲1. 领域和子域2. 核心域、通用域和支撑域3. 通用语言4. 限界上下文5. 实体和值对象6. 聚合和聚合根 2.4 事件风暴2.5 领域事件 三、DDD与微服务3.1 DDD与微服务的关系3.2 基于DDD进行微服务…...

S32K324 UDS Bootloader开发-需求篇
文章目录 前言内存分配UDS诊断协议需求CAN ID及时间参数UDS诊断服务Bootloader诊断服务APP诊断服务 DID22服务的DID:2E服务的DID:Routine Control DID: 刷写流程预编程主编程后编程 总结 前言 之前做过一个STM32的UDS Bootloader,协议栈主要是NXP官网下…...
【前端设计模式】之调停者模式(中介者模式)
调停者模式是一种行为设计模式,它通过引入一个调停者对象来集中处理一组对象之间的交互。调停者模式的目标是减少对象之间的直接通信,从而降低耦合度,并且使代码更易于维护和扩展。 调停者模式特性 将对象之间的通信集中在一个调停者对象中…...

【MySQL架构篇】SQL执行流程与缓冲池
文章目录 1. SQL执行流程2. 数据库缓冲池(Buffer Pool)2.1 缓冲池概述2.2 缓冲池如何读取数据2.3 查看和设置缓冲池的大小2.4 多个Buffer Pool实例2.5 引申问题 1. SQL执行流程 查询缓存:因为查询效率往往不高,所以在MySQL8.0之后就抛弃了这个功能解析器…...

[support2022@cock.li].faust、[tsai.shen@mailfence.com].faust勒索病毒数据怎么处理|数据解密恢复
引言: 威胁网络安全的恶意软件不断涌现,而[support2022cock.li].faust勒索病毒则是其中的一员。这个网络黑暗角落的新星,以其数据绑架的方式,一度成为数据安全的威胁焦点。本文将探究[support2022cock.li].faust勒索病毒的运作方…...
力扣学习笔记——49. 字母异位词分组
49. 字母异位词分组 https://leetcode.cn/problems/group-anagrams/?envTypestudy-plan-v2&envIdtop-100-liked 给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。 字母异位词 是由重新排列源单词的所有字母得到的一个新单词。…...

五、Qt中的常用类
1. QString 字符串类 QString是Qt中的字符串类,与C/C不同的是,不再使用ASCII编码,而使用Unicode编码。因此一个字符不是8位的char,而是16位的QChar,这就是为什么之前一个汉字占用一个字符的原因。、 QString几乎向前兼…...

CentOS 7.9.2009 数据盘挂载
一、linux版本: lsb_release -a 二、操作步骤 2.1,查看磁盘挂载情况,确认sdb是需挂载的硬盘 ## 查看磁盘挂载情况,确认sdb是需挂载的硬盘 lsblk 2.2,对硬盘sdb进行分区 ## 对硬盘sdb进行分区 fdisk /dev/sdb# 命令…...
cv::solvePnP使用方法及注意点详解(OpenCV/C++)
cv::solvePnP(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvec, tvec, useExtrinsicGuess, flags); 1、参数说明: objectPoints:一个 vector<cv::Point3f>,包含了在世界坐标系中的三维点的坐标,至少需要4个点…...

DevOps持续集成-Jenkins(4)
❤️作者简介:2022新星计划第三季云原生与云计算赛道Top5🏅、华为云享专家🏅、云原生领域潜力新星🏅 💛博客首页:C站个人主页🌞 💗作者目的:如有错误请指正,将…...
【数据仓库-零】数据仓库知识体系 ing
文章目录 一. 数仓基本概念二. 离线数仓建设方法论三. etl流程四. 数仓规范建设指南四. 数据仓库架构五. 数据可视化 通过熟悉构建数仓整体的过程,可以系统的了解 数仓构建理论:能够站在全局角度看数仓的运行架构,数仓执行流程。了解到构建数…...
css3 3D 转换 技巧详细解析与代码实例
CSS3 3D转换是CSS3中的一项新特性,通过它我们可以比较容易地实现3D效果。在这里,我将向大家介绍CSS3 3D转换的一些基本概念、使用方法和常见技巧。 1. 基本概念 在使用CSS3 3D转换时,需要了解一些基础概念: 三维坐标系…...
[Unity]给场景中的3D字体TextMesh增加描边方案一
取你的文本对象,简单地添加以下脚本: using UnityEngine; using System.Collections; using UnityEngine.UI;public class TextOutline : MonoBehaviour {public float pixelSize 1;public Color outlineColor Color.black;public bool resolutionDependant fal…...

TDengine(taos)数据库导出历史数据
业务需求:导出某个站点的累计充电量,累计放电量,光伏总放电量,进线总功率的所有数据‘ 1、登录taos,使用存数据的库; 提示Database changed;即为使用成功; 2、找到你想要导出的字段…...
算法进修Day-37
算法进修Day-37 73. 矩阵置零 难度:中等 题目要求 给定一个 _m_ x _n_ 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例1 输入:matrix [[1,1,1],[1,0,1],[1,1,1]] 输出:[…...
服务器之日常整活
文章目录 一,序二、服务器相关流水帐未完,待补充 一,序 假如你有一台服务器,你最想做哪些事? 等等,什么叫假如你有一台服务器,假如只有一台,肯定我想搞第二台,顺便第三台…...

交互式 Web 应用 0 基础入门
初探 Gradio:轻松构建交互式 Web 应用 文章目录 初探 Gradio:轻松构建交互式 Web 应用Why Gradio?安装 Gradio创建交互式界面1. gr.Interface2. gr.Blocks 强大的组件库输入输出组件控制组件布局组件 示例交互式数据可视化多组件同时(嵌套&a…...
JSONP的安全性较差,那么在跨域情况下,有没有其他更安全的替代方案呢?
在跨域情况下,为了保证安全性,有几种更安全的替代方案可以考虑使用: 1:CORS(Cross-Origin Resource Sharing): CORS 是一种现代化的跨域解决方案,通过在服务器端设置响应头来控制跨…...

Slax Linux 获得增强的会话管理和启动参数选项
Slax Linux 的创建者和维护者托马斯-马特吉切克(Tomas Matejicek)在自己生日这天(生日快乐!)发布了其小巧便携的 GNU/Linux 发行版的新版本,带来了各种增强功能和错误修复。 新发布的 Slax Linux 版本&…...

C/C++新冠疫情死亡率 2020年9月电子学会青少年软件编程(C/C++)等级考试一级真题答案解析
目录 C/C新冠疫情死亡率 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序编写 四、程序说明 五、运行结果 六、考点分析 C/C新冠疫情死亡率 2020年9月 C/C编程等级考试一级编程题 一、题目要求 1、编程实现 2020年全世界爆发了新冠疫情,请…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...

循环冗余码校验CRC码 算法步骤+详细实例计算
通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)࿰…...
Java - Mysql数据类型对应
Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...
Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?
Redis 的发布订阅(Pub/Sub)模式与专业的 MQ(Message Queue)如 Kafka、RabbitMQ 进行比较,核心的权衡点在于:简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...