20.LMAX——DDD的极致性能架构

学习视频来源:DDD独家秘籍视频合集 https://space.bilibili.com/24690212/channel/collectiondetail?sid=1940048&ctype=0

文章目录

  • 历史
    • 起源
    • 架构目标
    • 架构要素
  • 时序对比
    • 传统时序
    • 事件溯源时序
    • LMAX时序
  • 单线程非阻塞异步IO(reactor)
    • 多线程
    • 单线程
  • 事件溯源
  • 高可用方案
  • 代价
  • 总结
    • 优点
    • 缺点
    • 适用范围

历史

LMAX是由Martin Fowler 2011年提出,原文地址: https://martinfowler.com/articles/lmax.html

起源

  1. 金融零售平台,要求高性能
  2. 达到单线程600万TPS,一个线程一秒钟能处理600万个交易请求
  3. LMAX架构名称就是以这个交易平台的名字命名的

架构目标

超高TPS。这里的TPS不是指只把数据读出来,是要有写入操作的,有变更的。

架构要素

1. 聚合常驻内存
在领域驱动设计中,不管以什么方式设计,最后要得到的就是“聚合”。在LMAX中,聚合是一直在内存中存在,不像传统的架构,用的时候把聚合从数据库中加载到内存,修改后保存到数据库 ,内存中的聚合就被回收掉了。
2. 事件溯源
需要高可用写入领域事件,宕机重启后可以从领域事件重建聚合。
3. 单线程异步非阻塞IO(串行,无锁)

在这里插入图片描述
外部系统发过来的请求会先写入环形队列Input DisruptorBusiness Logic Processor会串行化地从队列中一个一个取出来请求处理,并将结果写入到OutDisruptor中,这个结果就是领域事件
它没有给客户端直接返回结果,它是完全异步化的过程,客户端发过来请求后不会等待,直接退出。客户端会监听相应的事件,当收到相应的事件,才知道操作是否成功。Disruptor是一个高性能的队列框架,当初就是为了LMAX架构而设计的。

时序对比

传统时序

在这里插入图片描述

事件溯源时序

在这里插入图片描述

LMAX时序

在这里插入图片描述

单线程非阻塞异步IO(reactor)

多线程

- CPU在多线程间切换开销高 (相对于reactor)
- 阻塞
每个请求一线程模式,并发受线程数限制。像传统的tomcat这种方式,一个请求对应一个线程。
- 非阻塞
聚合在内存中只有一个实例,多线程情况下就会出现并发问题,所以就需要对实例加锁,加锁情况下每个聚合实际并发1。

单线程

  • 串行执行,无需加锁,一个CPU执行一个线程。CPU不会频繁在用户态和内核态切换。
  • 阻塞
    如果用阻塞的方式,并发能力1,性能暴跌,所以只能用非阻塞方式。
  • 非阻塞 (超高性能的唯一选择)

事件溯源

为什么要使用事件溯源,主要有两点:

  • 只持久化领域事件,带来高性能写
  • 确保重启服务器时,可以领域事件中,重建聚合。

高可用方案

聚合放在内存中,如果宕机怎么办呢,所以需要设计高可用方案。
所有的高可用方案都是通过冗余来实现的。main(主机器) 会发出所有的事件,follower(从机器) 会不断的重播这些事件,并重建聚合。如果main和follower之间没有高延迟,二者就可以在短时间内保持一致性。supervisor会监测main和follower, 一旦main出现宕机,就会在follower中选择一个作为新的主机器main,并告诉网关,将请求发到新的主机器上去。在这里插入图片描述

代价

1. 无数据库事务
无先操作后回滚,必须严格前置完成所有校验,才能变更聚合内的状态数据,才能发布领域事件。
2. 运行时外部调用变复杂
因为异步的原因,导致它和外边系统交互很复杂。需要写代码处理异步IO,给编写代码带来负担。需要减少主动外部调用: 监听事件提前组装数据 (数据量小)
显式事件驱动方式
3. 受内存大小限制
因为聚合全部在内存中,如果聚合数量太大就需要用多台服务器去做数据分区,架构更复杂。

总结

优点

  1. 极致性能
    全内存化模型设计,更灵活自由,可以大量使用对象和对象之间的引用。不像之前传统设计聚合的时候,是尽量减少聚合和聚合之间的引用。

缺点

  1. 异步编程带来的编程难度
  2. 高可用架构更复杂。传统的架构,只需要将服务复制很多份,服务是无状态的,它们共享同一个数据库。当我们需要高可用的,只需要多部署几台服务器就可以了,不存在主从切换问题、数据不一致问题。

适用范围

聚合数据量适合内存化,需要极致TPS场景,比如:

  1. 某些游戏服务器
    频繁的执行操作,服务端不断的响应。
  2. 火车订票

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/63896.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

记uniapp、android studio开发原生插件时监听globalEvent 事件

globalEvent 事件:用于页面监听持久性事件,例如定位信息,陀螺仪等的变化。 在vue页面: 获取原生组件: var myGlobalEvent uni.requireNativePlugin(globalEvent); 通过plus.globalEvent.addEventListener方法注册全…

MFC集成WebBrowser控件的实例教程

本文还有配套的精品资源,点击获取 简介:本文提供了如何在MFC应用程序中集成WebBrowser控件的详细步骤,该控件利用ActiveX技术实现内嵌IE浏览器引擎功能。读者将学习如何创建对话框、处理控件事件,并添加导航功能以实现网页浏览。…

解决:IDEA中@Autowired自动注入MyBatis Mapper报红警告的几种解决方法

文章目录 解决:IDEA中Autowired自动注入MyBatis Mapper报红警告的几种解决方法问题描述:解决办法:1.将Autowired注解改成Resource2.给Autowired(required false)设置属性3.给Mapper层加注解Mapper/Repository4.改变写法,用RequiredArgsConst…

GTF转为excel文件

1. 加载必需的 R 包 在处理基因组数据时,我们通常需要一些专门的 R 包来读取、操作和导出数据。以下是常用的包: library(rtracklayer) # 用于导入 GTF 文件数据 library(writexl) # 用于导出数据到 Excel 格式 (.xlsx) library(openxlsx) …

python 调Qt C++ 写法配置和坑点

python 示例写法 和调c动态库一样 通过回调函数方式 将python函数注册到c 动态库中 from ctypes import *def DllCall(nParam, nFlag):print(nParam, nFlag)z2 0.6z3 0.4z4 0.0z5 0.3z6 0.5z7 0.8z8 0.3z9 0.9strData str(z2) str(z3) str(z4) str(z5)…

在Docker中运行MySQL的思考:挑战与解决方案

引言 在云计算和容器化技术日益普及的今天,Docker作为一种轻量级的容器化平台,已经成为开发和部署应用的首选工具之一。其提供的便携性、可扩展性和环境一致性对于无状态微服务来说无疑是巨大的福音。然而,并非所有应用都适合在Docker容器中…

Cesium 限制相机倾斜角(pitch)滑动范围

1.效果 2.思路 在项目开发的时候,有一个需求是限制相机倾斜角,也就是鼠标中键调整视图俯角时,不能过大,一般 pitch 角度范围在 0 至 -90之间,-90刚好为正俯视。 在网上查阅了很多资料,发现并没有一个合适的…

Navicat for MySQL 查主键、表字段类型、索引

针对Navicat 版本11 ,不同版本查询方式可能不同 1、主键查询 (重点找DDL!!!) 方法(1) :右键 - 对象信息 - 选择要查的表 - DDL - PRIMARY KEY 方法(2&…

软考系分:今日成绩已出

前言 今年报考了11月份的软考高级:系统分析师。 考试时间:11月9日。 总体感觉偏简单,但是知识点记得不牢,估计机会不大。 今日 12.11 ,成绩已出,每科总分 75分,全部45分以上为通过。 成绩总…

Linux学习笔记15 何为HDD,SSD?sata?PCIE?分区,MBR,GPT分区的理解

Linux学习怎么能不知道电脑的重要组成硬盘的知识呢? 前文有学习文件系统的概念。介绍了Linux组织文件的方式和文件的分类。 但是最初的时候,最先有的并不是文件系统。而是磁盘。 要我说,最关键的那句话就是:分区存在自己的文件…

angular图表echarts设置

angular框架ngx-echarts图表的配置 图表高度设置 默认高度是400px 可以自己动态设置容器高度 <div echarts nz-row nzJustify"start" [options]"option" [style.height]"option.echartHeight"></div>option.echartHeight‘600px’…

springboot402航班进出港管理系统(论文+源码)_kaic

摘 要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统航班进出港管理系统信息管理难度大&#xff0c;容错率低…

umi实现动态获取菜单权限

文章目录 前景登录组件编写登录逻辑菜单的时机动态路由页面刷新手动修改地址 前景 不同用户拥有不同的菜单权限&#xff0c;现在我们实现登录动态获取权限菜单。 登录组件编写 //当我们需要使用dva的dispatch函数时&#xff0c;除了通过connect函数包裹组件还可以使用这种方…

【云原生知识】Kubernets实践-前端服务如何访问后端服务

文章目录 概述步骤1&#xff1a;部署后端服务步骤2&#xff1a;配置Nginx步骤3&#xff1a;创建Nginx服务总结 如何确保 Nginx 能持续访问后端服务&#xff1f;相关文献 概述 假设你正在使用Kubernetes作为容器云平台&#xff0c;以下是如何配置Nginx以及相关服务&#xff0c;…

MySQL中count(*)、count(1)和count(字段名)有什么区别

MySQL中COUNT(*)、COUNT(1)和COUNT(字段名)的区别&#xff1a; 计数类型描述是否计算NULL值性能考虑COUNT(*)计算包括所有列的行数是&#xff0c;不区分列值是否为NULL通常最优&#xff0c;因为不需要检查特定列的值COUNT(1)功能上与COUNT(*)等价&#xff0c;计算行数是&#…

【计算机网络层】数据链路层 :局域网和交换机

&#x1f9f8;安清h&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;【计算机网络】【Mybatis篇】 &#x1f6a6;作者简介&#xff1a;一个有趣爱睡觉的intp&#xff0c;期待和更多人分享自己所学知识的真诚大学生。 目录 &#x1f3af;局域网 &#x1f6a6;局域网…

C# 属性(Property)

C# 属性(Property) C# 中的属性(Property)是一种用于访问和设置类或结构成员的值的特殊类型的方法。属性允许开发者以字段的形式访问方法,提供了更为安全和灵活的数据封装。在本文中,我们将深入探讨 C# 属性的概念、用途、以及如何有效地使用它们。 属性的定义 属性由…

活动预告 |【Part2】Microsoft 安全在线技术公开课:安全性、合规性和身份基础知识

课程介绍 通过参加“Microsoft 安全在线技术公开课&#xff1a;安全性、合规性和身份基础知识”活动提升你的技能。在本次免费的介绍性活动中&#xff0c;你将获得所需的安全技能和培训&#xff0c;以创造影响力并利用机会推动职业发展。你将了解安全性、合规性和身份的基础知…

浏览器定制 | Windows11 编译 Chromium 133.0.6885.0(截稿前Chromium最新版之编译篇[一])

序章回顾 其实&#xff0c;在此之前&#xff0c;我已经发表过如何在Windows下编译Chromium及前期环境准备的系列文章了。 那么&#xff0c;既然之前已然撰写过了&#xff0c;缘何又出这么一篇类似的文章呢&#xff1f; 倘若你看过我那几篇关于windows编译Chromium的系列文章…

【vue2】el-select,虚拟滚动(vue-virtual-scroller)

需求背景​​​​​​ vue2+element-ui项目中,当el-select中数据量较大时(超出5000个dom节点),会导致页面加载和渲染卡顿、el-select下拉列表延迟展开。 在现在的el-select的基础上使用分页或者虚拟列表的形式去处理大量的下拉菜单,可以保证页面的正常渲染及el-select的…