内存数据库的分布式数据库架构

2023-11-14

author:skate

time:2012/02/16


转载一篇文章:


本文提出了一种通过引入内存数据库层,建立两层多分区分布式数据库架构。此方案用于解决海量高并发系统的数据存储和访问问题,尤其适用于电子商务等数据模型复杂且业务复杂的互联网站。

 

这些年互联网站发展迅猛,为应对海量数据下的高并发访问,产生了各种分布式架构设计思想,例如Key-Value引擎,数据分区等。而对于电子商务类网站,海量数据问题还有一个重要特点,就是数据结构化及数据之间的关联,淘宝如此,阿里巴巴也是如此,这是与社区、视频、 博客等互联网站的显著差异。

 

1.  NoSQL 是灵丹妙药吗?

NoSQLKey-Value 引擎如BigTableCassendra等在很多大型网站被采用,很好的解决了海量数据存储和访问问题。而对于电子商务类网站,Key-ValueNoSQL并不是解决此问题的灵丹妙药。最多它们仅能用于一些数据模型较为简单的应用。

原因有两个方面:

1)数据模型复杂

淘宝和阿里巴巴的会员、宝贝、供求、订单等核心实体数据模型复杂,属性个数几十到上百个。例如:会员(Member)就包含基本信息、联系、工商、账户等多个域的信息;另外,核心实体之间,外围实体与核心实体之间还存在复杂的关联。

2)业务复杂:

模型的复杂源于业务和逻辑的复杂。电子商务网站大量查询场景是结构化查询,例如:

在淘宝上查询“卖家在江浙沪,价格在50-200元的男士T恤”,

在阿里巴巴上“列出某个会员所有待发货的订单”

这类查询(当然,阿里巴)主要针对多个非主键字段, 即便对于BigTableCassandra 这样的基于ColumnKey-Value数据库,其简单的Query API还无法胜任此类需求。 因此在阿里巴巴和淘宝,OracleMySQL 等关系数据库将仍然扮演重要角色。

 

2. MySQL 集群

引入K-V引擎等非关系数据库无非是要解决海量数据在高并发环境下的高效读写问题,最大程度在可靠的持久化(Durable)与高访问性能 (Performance) 之间选择一个平衡点。在高度结构化系统中,同样的考虑驱使我们需要考虑另外的解决方案。

目前一种通行的做法是 MySQL 读写分离式集群,1个或少数Master写,多数Slave读,MasterSlave进行变更数据的同步。首先,这种方案经过大量的实践,可靠且可行。

然而,直接向DB执行写操作,仍然比较耗时(参见表1,表2),数据复制,也可能存在不一致延时的情形。是否还有更快的方案?

3. 内存型关系数据库

可靠的持久化指数据存储到磁盘等设备上。图1展示了传统磁盘数据库的基本访问模式。

 



 图
1

抛开持久化的可靠性,即数据可以先不存储到磁盘上(Disk),内存存储的性能远高于磁盘存储。下表展示了针对OracleAltibase所做的性能对比,后者在插入和查询上性能是Oracle5-7倍。

 

数据库

测试结果

TPS

Oracle

203

246/

Altibase

28.32

1785/

1. OracleAltibase性能对比 -插入5万条 7

 

数据库

测试结果

TPS

Oracle

885

112/

Altibase

170

588/

2 OracleAltibase性能对比 关联查询10万条7

 

由此可见:Pm  >>>  Pd 

Pm - 内存数据库读写性能, Pd - 磁盘数据库读写性能)

 

结合前面分析的模型复杂性和业务复杂性原因,关系数据库(RDBMS)必须采用。因此,这两点考虑可以推导出另一个解决思路:内存型关系数据库。

 

 

磁盘型关系数据库

Key-Value引擎

内存型关系数据库

功能 -结构化操作和查询等

Y

N

Y

性能

3. DB选型对比分析

 

这个方案里,我们可以将内存先看做一种“磁盘”,读写操作都针对内存数据库进行,不再直接与磁盘数据库交互,这较好的避免了单纯MySQL 读写分离架构存在的时间延迟和一致性问题。如下图所示:

 



 图
2

4. 内存数据库的持久化

数据最终还是要存储到磁盘(Disk)上,内存数据库中的数据变化需要复制到与磁盘数据库上。这时,从内存向磁盘复制数据的过程可以看作原始写操作的异步操作,显然,异步操作使得前端的写操作显得更快。如下图所示:

 



 图
3

在事务型(OLTP)系统中,内存数据库中在启动时需要和磁盘数据库保持一致。 因此,内存数据库需要有相同的库表定义;并且在第一启动时,将所需库表数据加载到内存数据库中。

 

5. 内存数据库集群化

目前,经典的MySQL集群,通过读写分离,水平切分,实现海量数据存储。为应对海量数据存储,内存数据库同样需要做集群。垂直和水平切分策略,可用性策略与MySQL集群架构设计基本相同。如下图所示,其中 Ameoba 是分布式数据库代理,它进行数据路由等控制。

唯一的不同是,由于内存数据库的高性能,可以不再进行读写分离设计。

 



 图
4

 

6. 混合分区(Hybrid Shard

接第4节的分析,内存数据最终仍需要持久化到磁盘。这里需要一种混合分区(Hybrid Shard)来解决。即原来一个MySQL节点承担的一个水平分区,将由一个内存数据库节点和一个MySQL节点共同组成。

H-Shard = MDB + MySQL.

 

这种数据库架构将形成由两级数据库(2LDB),混合分区构成的集群。的如下图所示:

 



 图
5

 

7. 内存数据库选型

常见的内存数据库产品包括商业版和免费版两类。商业版如:AltibaseTimestenBerkley DB等。他们在电信,金融,证券等高性能计算应用中运用较为广泛。商业版功能强大,然而,价格比较昂贵,不适合目前“廉价PC+免费软件”的架构搭建思想。

笔者曾就职与中国移动系统提供商,其中计费、运营等系统就运用Timesten提供高性能运算,但还主要用于高频度小数据计算,如计费批价,优惠计算,信控等,采用单节点模式使用。

开源领域产品主要有H2HsqlDBDerby等。在混合分区架构中,内存数据库将承担OLTP的职责,因此除了读写性能外,功能的完备,事务等都需要作为优先评估的因素。

 

8. 新架构的挑战

通过引入内存数据库作为中间持久层,再加入分布式架构以支撑海量数据访问,这种架构设计颇具挑战。最先而易见的情况就是新架构的复杂度,正如大规模MySQL集群架构诞生初始一样。

我们以 H2 ,一个开源的高性能内存数据库为例说明:

1)  整合 Ameoba H2

Ameoba 是分布式数据库代理,它与 MySQL 整合已经在阿里巴巴核心业务中成功运用。如果仅将数据库节点看作一个存储,MySQL Node H2 Node 并无本质区别。JDBC驱动,DB切分,路由,皆由Ameoba 统一负责。

 

2)  异步持久化

每个逻辑混合分区= H2 + MySQL,谁来完成H2 中的数据变更异步写入 MySQL

比较好的方案是内存数据库提供实时增量的复制器(Replicator) ,例如:基于联机日志复制的双机热备机制。AltiBase 等产品就提供了此功能。

 

3)高可用性

内存数据库一旦崩溃,数据不复存在。因此首先要做到数据快速异步写入MySQL作持久化存储。同时要有健壮的容错和Failover机制,保证一个H2节点崩溃,同一逻辑分区中的替补H2节点立即顶替工作。

一种方案是分布式数据库代理如 Ameoba 来解决,例如:每个ShardH2至少设2个节点,采用Primary-Secondary模式,如图6所示:

 



 图
6

 

另一种方案是前面提到的内存数据库实时复制功能。

虽然有些内存DBH2自身能支持内存,磁盘两级存储,但其自身提供的磁盘存储和访问方案可靠性不如 MySQL。因此,使用内存式Primary-Secondary 模式更为可行。

 

4)分布式事务

数据库切分架构带来分布式事务问题,对一些事务要求较高的场景,这颇具挑战。Ameoba 目前还在解决中。Ameoba + H2组合面临同样的挑战。

目前一种比较一致意见和做法就是冷处理——尽量不用事务。 一致性问题根据业务的特点,采用数据订正来解决;个别业务使用补偿事务。因为目前大部分应用,即便是核心业务,对事务的要求也不高。

 

9. 进一步思考

1) 多种数据切分模式

    在一个大型互联网站,不同的应用和数据需要做不同的处理。在总体垂直切分模式基础上,选择数据量大的功能进行水平切分,例如:供求、订单、交易记录。

   

2)数据缓存(Data Cache

虽然内存数据库层(MDB)能更高效支撑交易型数据库,特别是应对结构化应用及复杂查询服务,但对高频度的查询(Query)和实体查找(Find)Key-Value缓存仍然是一项必要的设计。Cache能提供更高的查询速度,并减少对MDB的访问压力,特别是读写密集的高并发场景。因为这个架构中,内存数据库仍然作为一种存储Store,而不是Cache

 



 图
7

上图展示了,MDB层之上还需要DCL层来提供高性能缓存服务。

 

10. 总结

本文提出了一种通过引入内存数据库层,并建立两层,多分区的分布式数据库架构。此方案用于解决海量高并发系统的高性能数据存储和访问问题,尤其是电子商务类等业务复杂的互联网站。其核心思想是:

1)高性能:是通过内存数据库提供高性能关系数据库存取服务,这是此架构的最主要目标;

2)持久化:通过两级数据库及异步写完成持久化;

3)海量数据支撑:通过垂直和水平分区实现海量数据的支撑;

4)高可用性:在Ameoba基础上,通过主备节点进一步实现MDB的高可用性;二级磁盘数据库可以实现数据的快速恢复。

 

【参考资料】

1.  阿里巴巴 Ameoba分布式数据库设计和实践

2. 岳旭强, 《淘宝网架构师岳旭强的年度展望》, http://www.infoq.com/cn

3. 广东移动BOSS2.0分布式数据库架构方案,计费系统设计和实践.

4. Cassandrahttp://cassandra.apache.org/

5. Oracle, Timesten 官方文档, http://www.oracle.com/timesten/index.html

6. Fenng,Oracle 内存数据库-TimesTen, http://www.dbanotes.net/database/oracle_timesten.html

7. 张澄,包文菖,《内存数据库在BSS账务处理中的应用》,《计费&OSS世界》,http://database.51cto.com/art/200612/36973.htm

8. Titan,《常用内存数据库介绍》,http://titan.javaeye.com/blog/364345

9. Ricky Ho, NoSQL的模式》,程序员2010-1;《NoSQL 数据库的查询处理》,程序员2010-2


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

内存数据库的分布式数据库架构 的相关文章

  • 无法删除数据库 mysql:错误 3664 (HY000)

    我的应用程序中有一个名为X Files 我想要drop它 但每当我运行命令时drop database X Files我收到以下错误 mysql gt drop database X Files ERROR 3664 HY000 Faile
  • 日志中每天的每周活跃用户数

    我想知道是否有人可以帮助我使用一些 SQL 来返回两天或更长时间内登录到数据库表的唯一用户数量 让我们使用 7 天作为参考 我的日志表在每一行中包含时间戳 ts 和 user id 表示该用户当时的活动 以下查询返回此日志中的每日活跃用户数
  • MySQL 跨表计数(*) 查询帮助

    SELECT name COUNT AS count FROM t1 t2 WHERE t2 id t1 id GROUP BY t2 id 我想从 t1 获取名称以及 t2 中 id 与 t1 相同的行数 到目前为止我已经得到了上面的内容
  • Python 的 mysqldb 晦涩文档

    Python 模块 mysqldb 中有许多转义函数 我不理解它们的文档 而且我努力查找它们也没有发现任何结果 gt gt gt print mysql escape doc escape obj dict escape any speci
  • 使用数据库进行日志记录

    大多数日志似乎都是纯文本形式 而不是放入 MySQL 其他类型的数据库中 这是否有原因 在我看来 将它们放入数据库将使分析变得非常非常容易 但这会以牺牲速度还是其他什么为代价 我不太关心可移植性 显然你会有数据库连接的文本日志 我能想到两大
  • IN 子查询中的 GROUP_CONCAT

    SELECT A id A title FROM table as A WHERE A active 1 AND A id IN SELECT GROUP CONCAT B id from B where user 3 如果我启动子查询SE
  • 通过Java从MySQL中获取大量记录

    有一个 MySQL 表 服务器上的用户 它有 28 行和 100 万条记录 也可能会增加 我想从这个表中获取所有行 对它们进行一些操作 然后将它们添加到 MongoDB 中 我知道通过简单的 从用户中选择 操作来检索这些记录将花费大量时间
  • 我应该定义索引(A)和索引(B),还是索引(A,B),或者两者都定义?

    在我的表中 我有两个密切相关的列 A 和 B 我应该考虑哪些因素来决定是否创建 索引 A 和索引 B 索引 A B 以上两者 如果我 仅使用类似的查询where A 5 and B 10 并且从不喜欢where A 5 也可以使用类似的查询
  • 我应该如何审核 MySQL 表中的更改(使用 MySQL 4)?

    我被要求审核 MySQL 表中的任何 所有更改 有谁知道有什么工具可以帮助我做到这一点 还是我需要编写自己的解决方案 如果我编写自己的审计 我最初的想法是制作一个单独的表并在 PHP 代码中构建一系列更改 类似 fieldname1 gt
  • 拉拉维尔; “SQLSTATE[HY000] [2002] 连接被拒绝”

    我在 OSX 主机上设置了 homestead 2 0 并使用 Sequel Pro 我可以进行迁移并确认数据已在Sequel Pro中迁移 因此看起来数据库连接没有问题 但是 一旦我尝试从 Laravel 4 2 应用程序获取数据 它就无
  • PHP,文本从数据库中回显,没有换行,全部一体

    我的数据库中有一个长文本 从 php mayadmin 来看它看起来很好 但是当我将它回显到页面时 它会丢失所有格式 即没有新行 全部都在一个块中 有任何想法吗 Thanks 可能是因为换行符是 n 并且 html 想要 br 所以使用nl
  • 使用 Flot、html、PHP 和 MySql 查询绘制多个图表

    我正在尝试使用 Flot html PHP 和 MySql 查询绘制多个图表 但我陷入了困境 因为我找不到在同一个 html 页面中绘制多个 flot 的方法 为简单起见 在数据库 test db3 映像中包含以下字段 表1 用户名 发送邮
  • 选择前 n 个字符相等的行(MySQL)

    我有一张带有玩家句柄的桌子 如下所示 1 N Laka 2 N James 3 nor Brian 4 nor John 5 Player 2 6 Spectator 7 N Joe 从那里我想选择第一个 n 字符匹配的所有玩家 但我不知道
  • 私人聊天系统MYSQL查询显示发送者/接收者的最后一条消息

    在这里我延伸一下我之前的问题 私人聊天系统MYSQL查询ORDERBY和GROUPBY https stackoverflow com questions 10929366 private chat system mysql query o
  • 当我们有多对多关系时,如何在 firebase 中获取数据

    我读了这个问题Firebase 中的多对多关系 https stackoverflow com questions 41527058 many to many relationship in firebase 这里描述了如何在 fireba
  • SQLAlchemy - 批量插入忽略:“重复条目”

    我有一个名为user data 列id and user id作为唯一的密钥 我想将一些历史数据导入到该表中 我用批量插入映射 http docs sqlalchemy org en rel 1 0 orm session api html
  • 是否可以将新表和旧表从触发器传递到 MySQL 中的过程中?

    是否可以将新表和旧表从触发器传递到 MySQL 中的过程中 我怀疑不会 因为没有过程接受的表这样的数据类型 有什么可能的解决方法吗 理想情况下它看起来像这样 CREATE TRIGGER Product log AFTER UPDATE O
  • 自动删除主键序列中的间隙

    我正在创建一个网页 该网页根据用户操作将数据存储到 MySQL 数据库中 数据库有很多行 行的主键是列 rowID 它只是按顺序对行进行编号 例如 1 2 3 4 用户可以选择删除行 问题是当用户删除最后一行以外的行时 rowID 中有一个
  • MySQL - 选择一行 - 然后相对于所选行的下一个和上一个

    我会尽力澄清这一点 我需要在不使用 id 的情况下选择特定行和该选定行的前一个相对行以及该选定行的下一个相对行 这可能吗 简而言之 上一篇和下一篇 我不能 也许我只是不知道如何 使用 id 的原因是因为它们不是按顺序排列的 正如您从这个相当
  • Hibernate + MySQL + rewriteBatchedStatements=true

    我有以下 Hibernate 配置

随机推荐

  • 微信小程序:动画效果集合

    Life is like riding a bicycle To keep your balance you must keep moving 生活就像骑自行车 为了保持平衡 你必须不断前进 微信小程序 心跳动画 https blog cs
  • 使用 appium 进行微信小程序的自动化测试

    目录 前言 微信小程序结构 自动化用例的调整 示例代码 后记 前言 微信小程序是一种流行的移动应用程序 它在移动设备上提供了丰富的功能和用户体验 为了确保微信小程序的质量和稳定性 自动化测试是必不可少的一环 Appium是一个强大的自动化测
  • assert断言(没有返回值,不需要console.log,断言未通过会抛出错误,通过不会抛出错误)

    1 assert value message 保证value是true就不会抛出错误 2 assert deepEqual actual expected message 表达式 1 表示测试 actual 参数与 expected 参数是
  • Custom numeric format strings

    string Multiplier Multiplier 0 Console WriteLine string Format Multiplier 1000000 string LiteralChar LiteralChar 0 000 C
  • vue3 图片路径转base64 base64转file(二进制一般后台需要格式) file转base64

    1 图片路径转64 function imageUrlToBase64 url let homeImage new Image 解决跨域问题 homeImage setAttribute crossOrigin anonymous home
  • 为什么前端监控要用GIF打点

    1背景 我们知道 目前主流的前端监控 百度统计 友盟 谷歌统计 都在用GIF进行打点 但是 为什么这些系统都会使用GIF 难道是因为没有其他的解决方案吗 这得从前端监控的原理说起 2前端监控的原理 所谓的前端监控 其实是在满足一定条件后 由
  • DataTable筛选出现异常

    异常详细信息 System ArgumentException 在 Range 对象中 Min 37 必须小于或等于 max 1 解决方法 转化字段类型为int 再次出现问题 HH gt 0 and HH lt 35 出来的数据序列为 1
  • Android Jetpack 之 DataStore

    1 概述 Google 推出了 JetPack 的新成员 DataStore DataStore 是一种新的数据存储方案 DataStore 以异步 一致的事务方式存储数据 克服了 SharedPreferences 的一些缺点 Jetpa
  • 相机标定及点云拼接

    文章目录 前言 一 相机标定原理 二 关键代码 2 1 相机标定代码1 2 2 相机标定代码2 2 3 点云拼接代码 三 结果展示 总结 前言 在上一篇中已经完成了从图像到点云的转换 但是只针对单个相机 在这一篇中将再进一步 从两个相机拍摄
  • 【Python 1-5】Python教程之——详解字符串

    字符串或串 String 是由数字 字母 下划线组成的一串字符 字符串 字符串就是一系列字符 在Python中 用引号括起的都是字符串 其中的引号可以是单引号 也可以是双引号 如下所示 This is a string This is al
  • vba中function(自定义函数)

    自定义函数 顾名思义 就是自己定义的函数 为什么使用自定义函数 exce内置了很多有用的函数 但仍无法满足工作需求 自定义函数的作用 简化复杂的公式 可以和工作表函数相互嵌套使用 Function 函数名 参数1 参数2 代码 函数名 代码
  • Go语言面试题--进阶语法(32)

    文章目录 1 关于 channel 下面描述正确的是 2 下面的代码有什么问题 3 下面的代码有什么问题 4 下面代码输出什么 1 关于 channel 下面描述正确的是 A close 可以用于只接收通道 B 单向通道可以转换为双向通道
  • 大端小端以及内存对齐的优势

    为什么区分大小端 编程语言中不同类型的变量所占的字节大小不一样 大端 低位数据存放在高位地址为大端编码 小端 低位数据存放在低位地址为小端编码 如图所示 对于选择大端小端对程序性能的思考 首先 数据离散程度不同 字节序会在很大程度上影响速度
  • 零基础学习cJSON 源码详解与应用 (三)cJSON_Print();打印json

    文章目录 一 cJSON Print 源码分析 二 print value 2 1 ensure 2 2 print string 2 3 print number 2 4 print array 2 5 print object 三 up
  • 在Windows中使用虚拟机

    文章目录 VirtualBox使用教程 安装教程 获取 CentOS 及版本选择 在虚拟机上安装CentOS 在虚拟机中允许linux系统卡的原因 配置CentOS 安装图形界面系统 X Window System 安装图形界面程序 GNO
  • 版本控制工具

    版本控制工具 版本控制工具如何下拉库里边的内容 从无到有 在SVN中 在本地库中右键单击 选择tortoise SVN 版本库浏览器 然后输入地址 账号密码登录 登陆完毕后选择要下载的文件右键单击选择检出即可下拉到本地库 在GIT中 在本地
  • JQuery纯手搓轮播图【支持自动轮播、划动轮播、圆点联动】

    HTML div class lunbo div class lunbo content div class imgContent img class imgItem activeImg Started src img lunbo01 jp
  • RebornDB:下一代分布式Key-Value数据库

    http www csdn net article 2015 07 13 2825186 现实世界有许多的Key Value数据库 它们都被广泛应用于很多系统 比如 我们能够用Memcached数据库存储一个MySQL查询结果集给后续相同的
  • Thread类的用法 && 线程安全 && 多线程代码案例 && 文件操作和 IO && 网络原理初识 &&UDP socket

    第 1 题 编程题 题目名称 编写代码 实现多线程数组求和 题目内容 给定一个很长的数组 长度 1000w 通过随机数的方式生成 1 100 之间的整数 实现代码 能够创建两个线程 对这个数组的所有元素求和 其中线程1 计算偶数下标元素的和
  • 内存数据库的分布式数据库架构

    author skate time 2012 02 16 转载一篇文章 本文提出了一种通过引入内存数据库层 建立两层多分区分布式数据库架构 此方案用于解决海量高并发系统的数据存储和访问问题 尤其适用于电子商务等数据模型复杂且业务复杂的互联网