写点什么

Erlang 的 Mnesia——为高伸缩性应用准备的数据库管理系统

  • 2007-08-22
  • 本文字数:3220 字

    阅读完需:约 11 分钟

看来我们很可以称 2007 为“数据库正规化的神秘面纱被揭穿的一年”。我们已经看到了一些有意思的讨论,一些大型网站为了能够处理每小时上千万的访问请求,而放弃了传统关系数据库的路子。根据 Joe Gregorio 最近的观察,出现了这样一些常见方案(这里强调的是我的观点):

如果你想伸展到拍字节(Petabyte,2 的 50 次方,约千万亿)的级别,或者每天数十亿请求,你就需要: - 分布式部署。数据必须分布到多台机器上去。

  • 无表连接(Joinless)。至少在数据存储层次上,不能使用表连接(Join),也不要定义关联完整性约束。
  • 去正规化。虽然没有人直说,但我想如果你要避免使用表连接,就会有很多去正规化工作。
  • 无事务。不能按事务方式操作。

这些约束从根本上区别于(传统)关系数据库。

这些特征可以用来描述 Mnesia ,Erlang 的分布式数据库管理系统,通过复制方式支持高伸缩性和容错性,可以不需要传统关系数据库的表连接就检索记录。Mnesia 属于 Erlang/OTP 项目,是为运行于 Erlang 虚拟机上用 Erlang 语言开发的应用设计的(有用于 C/C++ 和 Java 的接口)。

在 1999 年发布的白皮书《 Mnesia——适用于电信应用的分布式健壮数据库管理系统》中,作者(Håkan Mattsson、Hans Nilsson 和 Claes Wikstrom)介绍了这个数据库的概念和关键区别,这些概念和区别所具备的预见能力很是令人惊叹。以下来自摘要:

Mnesia 数据库管理系统运行于数据拥有者应用的同一个地址空间中,但是应用不可能破坏数据库内容。这保障了快速访问的同时能够有效容错,而这二者一般是相互冲突的需求。Mnesia 植根于 Erlang 编程语言,基于 Erlang 的诸多特性而得以实现。

论文第一节解释了当初建立这么一个数据库管理系统的动机是电信应用苛刻的容错和高可靠性需求。这些要求是:

  1. 实时快速的键 / 值检索;
  2. 非实时的复杂查询主要在运营和维护时进行;
  3. 分布式的应用,从而数据也必须分布;
  4. 高容错性;
  5. 动态重新配置;
  6. 复杂对象。

论文第二节概览了 Mnesia 的组件。Mnesia 由多个 Erlang 应用组成,它们提供数据库管理系统的核心服务,比如锁定、事务管理和复制。作者们指出 Erlang 非常适合用来实现这个系统,它包括了大概 2 万行代码。查询语法是 Erlang 的一部分,数据模型类似于对象 - 关系数据库管理系统。

Mnesia 另一个有趣的地方是与 Erlang 编程语言的严密耦合,基本上把 Erlang 变成了数据库编程语言。这样好处很多,最大的好处是数据库使用的数据格式和编程语言用来操作数据的数据格式之间完全不会出现阻抗失配。

其数据模型支持表的概念,一条记录等价于一行,其中每一列都可以存储“任意复杂的组合数据结构,例如树、函数、闭包和代码等等”。一个 Erlang 复杂记录的例子如下:

X = #person{<br></br> name = klacke,<br></br> data = {male, 36, 971191},<br></br> married_to = eva,<br></br> children = [marten, maja, klara]<br></br>}.Mnesia 也支持一个和视图(View)类似的概念,这个概念被称为规则(Rules)。

复制是使 Mnesia 成为一个容错数据库管理系统的机制之一。数据表可以被复制到混合网络中的多个节点,而对应用来说却是透明的。被复制的数据表是对等的,也就是说没有主 - 从结构。

论文第三节详细描述了 Mnesia 的一些独有特性:

  • 复杂值。Mnesia 以自然有效的方式支持复杂值的操作(换言之,通过一次检索操作)。_“以第三(甚至是第一)范式组织电信数据通常不太可能。”_ 列里可以存储复杂值就意味着不再需要表连接。
  • 数据格式和地址空间。此数据库管理系统运行在应用的地址空间里。这就允许检索返回对象指针,而不需要在不同数据格式之间暗地转换对象,或者通过连线去操作对象。论文提及到 Erlang 中一个应用即使崩溃也不会影响到数据库,这克服了这种方式下应用的崩溃有可能影响数据库的常见诟病。“Erlang 进程的效能有一个优势,运行在同一个地址空间但是不可能直接读取或者写入其他进程的存储空间。”
  • 容错。数据表可以被复制到多个计算节点中。事务上下文中的写操作会被应用到所有副本,通过恢复时更新,当时宕机的副本也能够被更新。“这个机制使得多个地理上分开的系统联合提供一个连续运行的不停机系统设计成为可能。”
  • 分布和位置透明。应用开发者能够透明访问数据表——无论远程的还是本地的,还是数据表副本。不过在性能关键的地方,也有办法获知数据表的位置,并且让代码在尽量靠近事发数据的位置执行。
  • 事务和 ACID。Mnesia 支持 ACID(A= 原子性,C= 一致性,I= 隔离性,D= 耐久性),不过也提供仅限于内存的数据表操作能力(以牺牲耐久性为代价)。
  • 绕开事务管理器的能力。“脏接口(dirty interface)”的概念被作为一个轻量级加锁机制引入,从而避免使用事务管理器的额外开销。这个能力对性能关键的操作比较有用,比如检索一条记录。“这些脏操作 是真正的实时数据库操作:无论数据库是大是小,他们都消耗可以预测的执行时间。”
  • 查询。查询通过被称为“列表领悟(List Comprehension)语法”的方式表达。例如,要找到子女多于 X 个的人,表达式可以写成:query [P.name || P < table(person), length(P.children) > X] end.
  • Schema 的修改。Erlang 语言自身既支持不停止进程情况下修改运行中进程代码的能力。这就允许 Mnesia 数据库动态的修改 Schema。“Mnesia 既然是为不停机应用设计的,所有系统活动比如备份、修改 Schema、导出表数据到二级存储, 还有副本复制都必须在后台进行,同时允许应用和平常一样访问和修改数据表。”

在论文第四节中,作者们探索了具体实现的各方面,比如持久、锁管理、查询实现,以及分布应用的各节点可能会运行于不同字节顺序的计算机的情况,进而使得这样一个系统能够工作于混杂环境中。

第五节讨论了性能问题,发现“脏接口”比事务控制下的对应部分快得相当多。如预期一样,同步复制的代价使事务执行时间明显延长。完成一个事务的时间(以毫秒计)在单节点上是:常规锁——1877,显式写入锁——1225,而使用“脏接口”的话是 181。如果是 3 个节点的话,相同事务类型测量到的时间依次为:13372、12185 和 1121。

论文得出如下结论:

Mnesia 系统现在正被爱立信用来构建实际的产品,也就是说它不再只是一个原型系统,它已经成熟到可以贴上产品的标签。

Mnesia 的开发从该论文后一直在继续,加入了如分片表(fragmented tables,类似 shards,但在数据库层次上处理)等更多特性,也被用在开源项目如 YAWS (Erlang Web 服务器)和 ejabberd (XMPP 服务器)中。

对于横向分片数据,Mnesia 在伸缩性和低延迟事务上表现突出, 接下来的一个挑战可能是对于超大规模数据集它如何伸展。有人提到了超过6 千万行的例子。然而如 Bill de hÓra 最近写到的,增长的数据容量将迫使我们重新思考我们的数据库策略:

我想在对日常编程工作的影响上,增长的数据容量要远远超过多核。我过去几年所做的工作,一个不变的主题就是处理越来越大的数据集。被 Joe Gregorio 称为“Megadata(兆数据)”(但现在希望他没这么说过)。大数据集已不再是几家大公司的深奥议题,而是变得非常常见。

然后得出结论:

大容量意味着你需要不用管数据的去向而只是写入。而且对于关键字检索方式的读取,你需要基于文件系统,而不是关系数据库管理系统(在没有表连接、约束或触发器的前提下,关系数据库管理系统就是一个索引了的文件系统)。那样最终就是像 Hadoop Mogilefs S3 一样的东西——并行数据架构。

随着对 Erlang/OTP 的兴趣提升(包括最近的InfoQ 文章),这个项目最终也应该是像Mnesia 一样的东西。

查看英文原文: Erlang’s Mnesia - a distributed DBMS for highly scalable apps - - - - - -

译者简介:岳立东,Ableverse 创始人,技术推广大使。开源项目 WoW (内含 ToB 对象数据库)和 SecureJSH 创建者。目前致力于东道组件接合(Hosting Based Interfacing)理论研究,在此基础上的软件并行分布架构及对象数据库应用,技术博客 http://complystill.javaeye.com/ 。欲参与 InfoQ 中文站内容建设,请邮件至 china-editorial[at]infoq.com

2007-08-22 21:309953

评论

发布
暂无评论
发现更多内容

Chrome操作指南——入门篇(十二)color picker(颜色选择器)

Augus

Chrome开发者工具 9月月更

AI走向何方?我们在GTC 2022看到了这些趋势

脑极体

[Javaweb]JSON

十八岁讨厌编程

json 后端开发 9月月更

Web3.0 杂谈 -#003(49/100)

hackstoic

Web3.0

数据库系统是什么?它由哪几部分组成?

乌龟哥哥

9月月更

Chrome操作指南——入门篇(十一)network

Augus

Chrome开发者工具 9月月更

疫情时代下,线上协同办公成时下热点

Baklib

远程办公 企业 协同办公 在线设计

开发者有话说|在内卷中不断成长

timerring

9月月更 开发者有话说

【云原生 | 从零开始学Kubernetes】六、Pod的镜像拉取策略与各种机制

泡泡

Docker 云计算 云原生 k8s 9月月更

JavaWeb核心之ServletContext

楠羽

Servlet 笔记 9月月更

【云原生 | 从零开始学Kubernetes】五、Kubernetes核心技术Pod

泡泡

Docker 云计算 云原生 k8s 9月月更

Docker多阶段构建实战(multi-stage builds)

程序员欣宸

Docker 9月月更

Baklib|怎样编写内嵌式的帮助文档?

Baklib

产品 产品经理 企业 帮助文档 在线设计

使用 NVIDIA CloudXR 从 Google Cloud 流式传输 VR 和 AR 内容

3DCAT实时渲染

[Spring Framework]AOP初识

十八岁讨厌编程

aop 后端开发 9月月更

2022-09-23:整数数组 stations 表示 水平数轴 上各个加油站的位置。给你一个整数 k 。 请你在数轴上增设 k 个加油站, 新增加油站可以位于 水平数轴 上的任意位置,而不必放在整数

福大大架构师每日一题

算法 rust 福大大

VUE v-bind 数据绑定

HoneyMoose

Chrome操作指南——入门篇(十三)element小技巧

Augus

Chrome开发者工具 9月月更

【Jvm】Jvm类加载机制

石臻臻的杂货铺

JVM 9月月更

[Spring Framework]AOP经典案例、AOP总结

十八岁讨厌编程

Java 后端开发 9月月更

速刷html一周目(上)

吉师职业混子

9月月更

INFINI 产品更新啦 20220923

极限实验室

elasticsearch console Gateway infini 极限实验室

自动化测试神器playwright的安装及常见问题解决

迷彩

playwright 学习记录 9月月更

关于 Angular 应用 tsconfig.json 中的 target 属性

汪子熙

typescript 前端开发 angular web开发 9月月更

我也不想学之PHP系列(1)

吉师职业混子

9月月更

跟着卷卷龙一起学Camera--LTM

卷卷龙

ISP 9月月更

FAQ需要有哪些功能?哪些注意事项

Baklib

产品 产品经理 客户服务 FAQ

峰会倒计时1天!九位行业大咖邀您共启极速统一的数据分析新范式

StarRocks

每日算法刷题Day16-和为S的两个数字、数字排列、二进制中1的个数

timerring

算法题 9月月更

培养技能、增强信心、 获得亚马逊云科技认证

亚马逊云科技 (Amazon Web Services)

培训与认证

速刷html一周目(下)

吉师职业混子

9月月更

Erlang的Mnesia——为高伸缩性应用准备的数据库管理系统_数据库_Gavin Terrill_InfoQ精选文章