很早就看到过MF的这篇The LMAX Architecture,可是之前一来英文水平不够,二来确实看不懂… 今天有幸再次看到,一口气读完终于有所领悟。

1 Overall Architecture

LMAX是一个新的金融交易平台。系统完全构建于JVM之上,却能在一个单线程上每秒处理6m的订单(其实是指核心业务逻辑处理类是单线程的)。系统主要由高并发组件Disruptors和业务服务Business Logic Processor两部分组成。

我们经常听到“免费午餐已经没有了”,现代CPU的主频速度已经很难提升,为了写出更快的代码我们只能寄希望于编写多处理器上的并发软件。但这对程序员来说可不是一个好消息,因为并发编程非常困难,难于开发更难于测试。锁和信号量(semaphore)让我们投入过多精力关注计算机硬件而非我们的领域问题本身。多种编程模型如Actor和STM(software transactional memory)都意在简化并发编程,然而它们还是会引入Bug和不必要的复杂度。

在这种情况下,LMAX的单线程、低延迟、低复杂度使其显得格外引人注目。下面就是LMAX平台的顶层架构。就像刚才介绍的,系统主要就是由两个Disruptor和核心的Business Logic Processor组成。

2 Business Logic Processor

Business Logic Processor业务逻辑处理器(以下简称Processor)几乎没用任何框架,单线程地直接运行在JVM上,顺序地处理一个个输入消息。其最大特点就是完全在内存中计算(operate entirely in-memory),而没有任何的数据或其他持久化介质。这带来两个重要的好处:

1.      因为避免了慢IO访问和等待,所以它非常快

2.      因为再也不需要ORM映射了,所有数据都在Java对象中,所以它简化了编程

当然内存计算架构也带来了连锁反应,有一系列的问题要处理,比如故障恢复、Failover等。那么LMAX是如何应对的呢?其核心是Event Sourcing编程模型

Ø  首先,Processor的状态完全由输入事件源推演而来,所以Processor的状态恢复完全可以通过replay事件或日志来还原。

Ø  同时,定期(比如每天夜里并发量低时)都会做快照(snapshot)。这样通过重启JVM,加载快照,replay日志就可以快速还原。

Ø  最后,Processor会有多个结点组成集群来处理一个输入消息,当然只有一个Processor的输出会被保留。这样,当某个Processor发生故障时,可以及时failover切换。

此外,Event Sourcing模型的另一个好处就是方便了开发人员进行调试和诊断。当发生问题时,直接将事件或日志序列拷贝到本地环境进行replay就能重现问题了,因为Processor都是无状态的。

从实现上来说,Event Sourcing去除ORM层,加入Event Store(可以定制也可以使用关系数据库),通过DDD的Aggregate聚合根来管理Domain对象。



使用Event Sourcing模型最明显的变化首先就是一切慢外部服务都要从Processor中抽离出去,可以形成多个Input-Output-Input Distributor链。这种事件驱动风格其实不罕见,例如开发Nginx模块时,Nginx完全基于事件驱动,所以开发的模块时各个回调函数都要保证能快速返回。第二点就是错误处理。传统数据库出错时可以直接回滚,而LMAX平台没有自动回滚的设施,所以在持久化输入消息前要进行充分验证(持久化是在Disruptor中完成的,下面会讲到)。

3 Input and Output Disruptor

尽管Processor是单线程执行的,但整个系统不可能只有一个线程来处理请求。在LMAX中,Disruptor负责多线程处理请求以及计算前的一系列脏活累活。具体来说它主要负责以下几件事儿:

Ø  Receive message接消息:

Ø  Journal日志:将输入消息保存到磁盘上。只使用普通文件系统,没用任何数据库。

Ø  Replicate复制:将输入消息复制到集群中各个结点,让每个Processor都能处理。

Ø  Un-marshall解码:将原始输入消息解码为Processor能够处理的格式。

Receive message相当于另外三个任务的生产者,而后三个任务都是要在Processor处理前要完成的,但是三者间没有顺序要求。在这里,Disruptor采用了Ring Buffer数据结构。

下面解释一下其工作原理:每个任务都有自己的counter来记录当前处理到哪个Slot了。但每个任务都可以看到其他任务的counter,一是防止操作冲突,二是要保持速度(Receiver > Journaler/Replicator/Un-marshaller > Processor)。为了提高并发,还可以增加消费者,例如使用两个Journaler分别处理单双数的消息。

同样地,Output Disruptor也使用同样的数据结构来处理输出消息。

4 Mechanical Sympathy

“机械同感”(mechanical sympathy)来自于赛车比赛,它反映了车手对赛车有一种内在的感觉,所以他们能够赛车达到最佳状态。然而多数程序员缺少这种对编程与硬件交互的感同身受的情感。要么是没有,要么就是以为自己有,实际上却是基于很久以前硬件工作方式而建立的概念。

现代CPU影响延迟的一个重要因素就是CPU与内存的交互。虽然内存在我们看来很快,但是在CPU看来它实在太慢了。所以CPU内部又有了多层次的缓存,如L1,L2甚至L3,而这正是我们要想方设法利用的 – 尽可能让我们的代码或数据被它们缓存住。LMAX团队在放弃传统金融的事务数据库架构后选择了Actor模型,然而Actor模型尽管简化了并发编程,但实际上当多个客户端并发操作底层队列时,就会涉及到锁。结果,锁会引起上下文切换到内核态,从而使正在处理的CPU很可能丢失缓存中的数据。我们知道并发读是不需要锁的,于是解决问题的关键就在于如何保证单一写(one-writer principle)。

引用一段小测试:Disruptor论文中讲述了我们所做的一个实验。这个测试程序调用了一个函数,该函数会对一个64位的计数器循环自增5亿次。当单线程无锁时,程序耗时300ms。如果增加一个锁(仍是单线程、没有竞争、仅仅增加锁),程序需要耗时10000ms,慢了两个数量级。更令人吃惊的是,如果增加一个线程(简单从逻辑上想,应该比单线程加锁快一倍),耗时224000ms。使用两个线程对计数器自增5亿次比使用无锁单线程慢1000倍。

于是Disruptor首先遵循了single-writer原则(过后再具体分析Disruptor的内部实现),其次它使用单线程运行Processor来处理业务。好处自然就是保证一个CPU内核上只有一个线程在跑,这样能够warm up缓存,尽可能地使内存访问能命中缓存,而非真正访问内存。基于mechanical sympathy的分析和对系统原型的性能测试发挥了巨大作用,指导并验证了最终模型的设计。

5 When to Use?

第一印象可能是这种架构只适用于很少的场景。毕竟大多数应用程序都不是需要在低延迟下处理复杂事务的金融系统,对于这些应用6m的TPS不是必要的。然而,在内存越来越多的情况下,许多应用都放弃了与关系数据库和ORM工具的缠斗,将它们的working set放入内存处理,在这种情况下,LMAX采用的Event Sourcing模型是值得借鉴的

然而在Event Sourcing模型与CQRS(另一种基于事件的内存处理框架)之间有明显的功能重叠。关于二者的区别和使用场景还有待研究。


LMAX高并发系统架构的更多相关文章

  1. 大数据高并发系统架构实战方案(LVS负载均衡、Nginx、共享存储、海量数据、队列缓存)

    课程简介: 随着互联网的发展,高并发.大数据量的网站要求越来越高.而这些高要求都是基础的技术和细节组合而成的.本课程就从实际案例出发给大家原景重现高并发架构常用技术点及详细演练. 通过该课程的学习,普 ...

  2. PHP高并发高负载系统架构

    PHP高并发高负载系统架构 1.为什么要进行高并发和高负载的研究 1.1.产品发展的需要 1.2.公司发展的需要 1.3.当前形式决定的 2.高并发和高负载的约束条件 2.1.硬件 2.2.部署 2. ...

  3. Java互联网架构-直播互动平台高并发分布式架构应用设计

    概述 网页HTML 静态化: 其实大家都知道网页静态化,效率最高,消耗最小的就是纯静态化的 html 页面,所以我们尽可能使我们的网站上的页面采用静态页面来实现,这个最简单的方法其实也是最有效的方法, ...

  4. 不懂这些高并发分布式架构、分布式系统的数据一致性解决方案,你如何能找到高新互联网工作呢?强势解析eBay BASE模式、去哪儿及蘑菇街分布式架构

    互联网行业是大势所趋,从招聘工资水平即可看出,那么如何提升自我技能,满足互联网行业技能要求?需要以目标为导向,进行技能提升,本文主要针对高并发分布式系统设计.架构(数据一致性)做了分析,祝各位早日走上 ...

  5. 浅谈千万级PV/IP规模高性能高并发网站架构(转自老男孩)

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://oldboy.blog.51cto.com/2561410/736710 如果把来 ...

  6. 程序员修神之路--用NOSql给高并发系统加速(送书)

    随着互联网大潮的到来,越来越多网站,应用系统需要海量数据的支撑,高并发.低延迟.高可用.高扩展等要求在传统的关系型数据库中已经得不到满足,或者说关系型数据库应对这些需求已经显得力不从心了.关系型数据库 ...

  7. 3年Java开发6个点搞定高并发系统面试疑惑

    前言 其实所谓的高并发,如果你要理解这个问题呢,其实就得从高并发的根源出发,为啥会有高并发?为啥高并发就很牛逼? 说的浅显一点,很简单,就是因为刚开始系统都是连接数据库的,但是要知道数据库支撑到每秒并 ...

  8. Java面试之高并发系统

    在开发高并发系统时有三把利器用来保护系统:缓存.降级和限流.

  9. (转)浅谈千万级PV/IP规模高性能高并发网站架构

    浅谈千万级PV/IP规模高性能高并发网站架构 原文:http://blog.51cto.com/oldboy/736710 文章架构简图:   高并发访问的核心原则其实就一句话“把所有的用户访问请求都 ...

随机推荐

  1. Diango + uwsgi + nginx 项目部署(可外网访问)

    自己通过nginx uwsgi 部署django项目,查询了很多资料,遇到了很多问题,最终完成了部署,趁着心情愉悦,写个随笔,为曾像我一样苦寻解决方案的小伙伴们提供些思路. 安装Nginx: #安装n ...

  2. [Codeforces 864F]Cities Excursions

    Description There are n cities in Berland. Some pairs of them are connected with m directed roads. O ...

  3. [HNOI2001]求正整数

    题目描述 对于任意输入的正整数n,请编程求出具有n个不同因子的最小正整数m. 例如:n=4,则m=6,因为6有4个不同整数因子1,2,3,6:而且是最小的有4个因子的整数. 输入输出格式 输入格式: ...

  4. [BZOJ]1069: [SCOI2007]最大土地面积

    题目大意:给出二维平面上n个点,求最大的由这些点组成的四边形面积.(n<=2000) 思路:求出凸包后旋转卡壳枚举对踵点对作为四边形的对角线,枚举或二分另外两个点,复杂度O(n^2)或O(nlo ...

  5. [BZOJ]1059 矩阵游戏(ZJOI2007)

    虽然说是一道水题,但小C觉得还是挺有意思的,所以在这里mark一下. Description 小Q是一个非常聪明的孩子,除了国际象棋,他还很喜欢玩一个电脑益智游戏——矩阵游戏.矩阵游戏在一个N*N黑白 ...

  6. 用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- 操作符重载和隐式类型转换

    C#中,某些类型会定义隐式类型转换和操作符重载.Unity中,有些对象也定义了隐式类型转换和操作符重载.典型情况有:UnityEngine.Object.UnityEngine.Object的销毁是调 ...

  7. IDE、SDK、API

    IDE 集成开发环境(IDE,Integrated Development Environment )是用于提供程序开发环境的应用程序,一般包括代码编辑器.编译器.调试器和图形用户界面等工具.集成了代 ...

  8. windows平台下cocos2d-x-3.0beta2创建新项目

    我目前使用的版本是cocos2d-x-3.0beta2 前提: 已安装了python2.7.3 已安装了VS2012 打开我的cocos2d-x-3.0beta2所在文件夹F:\Framework\c ...

  9. Spring消息之JMS.

    一.概念 异步消息简介 与远程调用机制以及REST接口类似,异步消息也是用于应用程序之间通信的. RMI.Hessian.Burlap.HTTP invoker和Web服务在应用程序之间的通信机制是同 ...

  10. ASP.NET Core部署到Windows IIS

    网上已经有许多ASP.NET Core关于Widows IIS部署的文章,在部署到服务器时遇到了一些问题,在这里我就不再对原理进行阐释(复制)了,只写下一些关键环节,想看原理的同学请参考官网,此文章作 ...