NewSQL数据库大对象块存储原理与应用

一、前言

企业内容管理(EnterpriseContent Management,ECM)系统是一种管理非结构化内容的系统,传统代表为EMC Documentum或IBM Filenet等ECM解决方案。随着大数据技术的越发普及,越来越多的客户开始尝试把存放在传统ECM系统中的文件、图片、影像等内容向开放分布式平台迁移。一般来说,用户可以选择的方案根据场景与数据类型来看可以分为几类,包括HDFS方案、对象存储方案、NAS方案、以及分布式数据库方案等。

其中,HDFS方案主要面向数据归档,对大量打成大包的文件直接存放,一般不提供在线读写功能,主要的目的是替代磁带。

而NAS方案则类似HDFS,使用独立第三方传统数据库作为元数据管理系统,同时使用外接NAS设备存放中小型文件。一般来说,NAS作为文件系统可以支持较多数量的小文件,但是当小文件数量达到亿级时同样会产生管理、访问性能与扩展性等一系列问题。

对象存储则以S3等接口为通用标准,设备提供商可以在底层使用K/V存储或块存储等不同存储机制,同时提供类似对象访问、版本管理等一系列功能特性。

最后,分布式数据库方案则使用分布式数据库中的大对象机制,将元数据与大对象统一存放在数据库中,在支持批次管理、版本管理、流程管理等元数据管理特性时不需要借助额外第三方数据库进行支持。

二、功能概述

SequoiaDB(巨杉数据库)是一款新一代分布式文档类数据库,同时支持事务与标准SQL的结构化数据访问方式。在同类开源分布式数据库中,SequoiaDB是唯一一款原生集成行存储与块存储双引擎的数据库。除了JSON存储引擎以外,为了提高非结构化文件的读写性能,SequoiaDB核心引擎提供了分布式块存储模式,可以将非结构化大文件按照固定大小的数据块进行切分并存放于不同分区。当用户需要管理海量的小文件(例如照片、音视频、文档、图片等)时,SequoiaDB的双存储引擎特性能够帮助用户快速搭建一个高性能、高可用的内容管理与影像平台系统。使用SequoiaDB搭建的影像平台系统架构相对简单,元数据与内容数据均可使用SequoiaDB服务器的本地磁盘存放,不再需要额外购买昂贵的外部存储设备,节省企业的开发和运维成本。

SequoiaDB的块存储字段类型叫做LOB(Large OBject,大对象),其核心机制是将内容文件打散成多个数据块,每个数据块被分别发送到不同分区独立存放。与其他解决方案相比,由于不存在独立中控元数据节点,SequoiaDB提供的LOB存储机制理论上可以存放近乎无限数量的对象文件,并且不会由于元数据堆积而造成性能下降。同时,由于数据块被散列分布到所有数据节点,整个系统的吞吐量随集群磁盘数量的增加近乎线性提升。最后,SequoiaDB提供原生的内容管理接口,通过REST访问方式支持批次管理、版本管理、流程管理等一系列基本CM特性。

从使用方式上看,SequoiaDB的LOB机制可以使用原生API的访问形式,对底层LOB对象进行读写访问;同时,用户也可以通过高阶CM API Java接口,Java驱动会将请求封装成RESTful形式,通过发送接收HTTP报文进行对象和批次级别读写更新操作。

三、架构

SequoiaDB的LOB存储结构分为元数据文件(lobm)与数据文件(lobd)。其中,元数据文件存储整个LOB数据文件的元数据模型,包括每个页的空闲状况、散列桶、以及数据映射表等一系列数据结构。而数据文件则存储用户真实数据,数据头之后所有数据页按照page size进行切分,每个数据页不包含任何元数据信息。

图3:LOB元数据与数据文件结构映射

在建立集合的过程当中,大对象存储必须依附于普通集合存在,一个集合中的大对象仅归属于该集合,不能被另外一个集合管理。

当用户上传一个大对象时,会经历几次散列操作。

首先,协调节点或客户端会生成(或者用户指定)一个全局唯一的描述符,同时将传入的数据按照用户指定的pagesize大小切片,最后针对每一个切片按照(描述符+切片id)进行散列,用于决定该切片存在哪个数据分区中。注意,集合的分区键设定并不作用于大对象。

在每个分区中,当接收到数据分片后会根据(描述符+切片id)进行再一次散列,决定元数据桶的位置。而真实数据则通过查找元数据信息,在数据文件中找到一个最近的空闲页写入,然后将该页的ID写入元数据桶中,代表该桶指向这个数据页。如果散列后数据桶已经被占用,则使用常规散列冲突的解决方式找到下一个空闲桶。

当用户读取大对象时,协调节点按照其(描述符+偏移+长度)计算出需要读取多少个切片,以及每个切片所在的数据分区,最后将数据节点返回的数据按顺序排列返回客户端。

由于SequoiaDB将文件切片存储,一个大文件可能存在有非常多个分片,所以在访问的时候协调节点还需要进行请求合并,尽可能使用最小的报文一次性请求多个连续的数据页,以防止访问一个对象时协调节点需要向数据节点发送成千上万的此类请求,同时对数据节点做到I/O合并,一次性读入尽可能多的连续页面。

四、行业应用案例

企业内容管理平台

随着网络技术的渐渐普及,越来越多的银行开始将传统渠道向互联网与移动端靠拢。随之而来的,是更多监管业务的需要,例如针对远程开户等业务,银行需要开始提供“双录”能力,对用户的音频与视频数据进行存储。传统EMC、IBM提供的企业内容管理系统以小机加高端存储硬件为基础,对于仅存票据证照等相对小量的图片存储还可以勉强满足需要,但是当存储类型扩展到音视频等领域性能并不出色,同时开销还会指数级增加。

SequoiaDB提供的分布式、双引擎以及对象存储的功能,天然为海量的音视频、影像、证照等内容提供了分布式存储的能力。SequoiaDB可以使用高存储密度的PC服务器替代传统的小机加高端存储的配置,能够使用户以1/5的拥有成本,提供更多的存储空间与更高的吞吐能力。

图4:基于SequoiaDB的新一代企业内容管理平台与旧平台的对比

在SequoiaDB内容管理解决方案中,数据库除了提供基本的记录与文件的读写操作外,还提供了内容管理平台的批次管理、版本管理、流程控制等一系列后台管控能力,为与用户中间件对接提供了最大便利。

图5:SequoiaDB内容管理平台架构图

五、操作指南

SequoiaDB提供基于shell的命令行界面,以及C、C++、Java、Python、PHP、Nodejs等驱动访问原生LOB API。同时,SequoiaDB提供访问协议的CM API Java接口。本文将会就命令行、C++、Java以及CM API接口进行详细描述。

5.1 命令行

名称

参数

类型

说明

putLob

oid

string

大对象OID

file_path

string

大对象文件的本地路径

forced

boolean

如果大对象OID已经存在则直接覆盖

deleteLob

oid

string

大对象OID

getLob

oid

string

大对象OID

file_path

string

大对象文件的本地路径

forced

boolean

如果本地文件已经存在则直接覆盖

listLobs

-

-

-

表1:命令行操作指令

样例:

>  db.foo.bar.putLob('/opt/sequoiadb/standalone/diaglog/sdbdiag.log')
579f55b7389d2aef0a000000
Takes 0.166125s.
> db.foo.bar.listLobs()
{
   "Size": 29342,
   "Oid": {
     "$oid": "579f55b7389d2aef0a000000"
   },
   "CreateTime": {
     "$timestamp": "2016-08-01-21.59.19.939000"
   },
   "Available": true
}
Return 1 row(s).
Takes 0.6703s.
>  db.foo.bar.getLob('579f55b7389d2aef0a000000',  '/opt/sequoiadb/standalone/test.log')
{
   "LobSize": 29342,
   "CreateTime": {
     "$timestamp": "2016-08-01-21.59.19.939000"
  }
}
Takes 0.910s.

5.2 C++

sdbclient::sdbCollection类:

名称

参数

类型

说明

createLob

lob

sdbLob &

传出对象

oid

bson::OID *

指定OID,如果不指定则自动生成

removeLob

oid

bson::OID &

大对象OID

openLob

lob

sdbLob &

传出对象

oid

bson::OID &

指定OID

listLobs

cursor

sdbCursor &

传出游标

表2:sdbCollection类中LOB相关函数

sdbclient::sdbLob类:

名称

参数

类型

说明

close

-

-

-

read

len

UINT32

一次读取长度

buf

CHAR *

缓冲区指针

read

UINT32 *

真实读取长度,传出参数

write

buf

CHAR *

缓冲区指针

len

UINT32

一次写入长度

seek

size

SINT64

转移偏移

whence

SDB_LOB_SEEK

寻址起始方式

isClosed

-

-

-

isClosed

flag

BOOLEAN &

本对象是否已被关闭的传出参数

getOid

-

-

-

getOid

oid

bson::OID &

本对象的Oid传出参数

getSize

-

-

-

getSize

size

SINT64 *

本对象大小的传出参数

getCreateTime

-

-

-

getCreateTime

millis

UINT64 *

本对象创建时间的传出参数

表3:sdbLob类中的相关函数

样例代码可以参考安装目录下samples/CPP/lob.cpp文件。

5.3 Java

com.sequoiadb.base.DBCollection类:

名称

参数

类型

说明

createLob

id

ObjectId

指定创建对象

createLob

-

-

-

openLob

id

ObjectId

指定打开对象

removeLob

id

ObjectId

指定删除对象

listLobs

-

-

-

表4:DBCollection类中LOB相关函数

com.sequoiadb.base.DBLob类:

名称

参数

类型

说明

getID

-

-

-

getSize

-

-

-

getCreateTime

-

-

-

write

b

byte[]

写入字节数组

read

b

byte[]

读取字节数组

seek

size

long

转移偏移

seekType

int

寻址起始方式

close

-

-

-

表5:DBLob类中的相关函数

样例代码可以参考安装目录下samples/Java/com/sequoiadb/samples/Lob.java文件。

5.4 CM API

名称

参数

类型

说明

createBatch

itemTypeBean

ItemTypeBean

批次信息属性封装对象

userId

String

用户ID

deleteBatch

batchId

String

批次ID

userId

String

用户ID

updateBatch

iteamTypeBean

ItemTypeBean

批次信息属性封装对象

userId

String

用户ID

queryItemByBatchID

batchId

String

批次ID

version

int

版本号

queryItemByType

batchId

String

批次ID

type

String

类型

queryBatch

map

Map

批次匹配条件

queryItem

map

Map

文档匹配条件

putContent

path

String

上传文档

getContent

oid

String

对象OID

path

String

下载文档存储路径

表6:CM API中的相关函数

六、性能指标

6.1 系统配置

本文测试使用3台物理机作为服务器与1台物理机作为客户端。客户端使用C程序与服务端直连,使用LOB API进行读写访问操作。

服务端
 CPU:Intel® Xeon® CPU E5-2420 0 @1.90GHZ(6core *2)  (一台物理机)
 CPU:Intel® Xeon® CPU E5-2620 V2@ 2.10GHZ (6core *2) (二台物理机)
 MEMORY:48
 DISK: 2T/6块
 客户端
 CPU:Intel® Xeon® CPU E5-2420 0 @1.90GHZ(6core *2)  (一台物理机)
 MEMORY:48
 DISK: 2T/6块

集群部署方式为6分区3副本,三台机器构成高可用集群,网络为千兆网,协调节点与编目节点分别部署在3台服务器上。数据节点分布见表3,其中红色部分代表该分区的主节点,黑色为从节点。

部署 角色

分区1

分区2

分区3

分区4

分区5

分区6

192.168.3.78

disk1

disk2

disk3

disk4

disk5

disk6

192.168.3.79

disk1

disk2

disk3

disk4

disk5

disk6

192.168.3.72

disk1

disk2

disk3

disk4

disk5

disk6

表7:数据节点分布

6.2 写操作测试

文件系统的配置分别使用两种方式:打开DIO以及用普通文件系统缓存方式。

表8:DIO模式

表10:文件系统模式

可以看到,打开DIO与普通文件系统缓存相比,性能确实存在一定下降。在三台服务器的情况下,尺寸较小的文件在DIO打开的情况下显示出与普通文件系统缓存更大的差异。当文件尺寸平均达到1-2MB左右后,使用DIO与普通文件系统的差异几乎可以忽略不计。图1显示了启用与关闭DIO的情况下,在800线程并发中整个集群的吞吐量(MB/s)。

图6:写操作吞吐量对比

6.3 读操作测试

不同于写操作,SequoiaDBLOB机制在读操作中受DIO的影响较小。

表11:DIO模式

表12:文件系统模式

在文件读取的过程当中,因为绝大部分读取都是顺序I/O,因此是否打开文件系统缓存基本对性能不构成影响。从性能读数可以看出,SequoiaDB LOB读取时每次读取的缓存大小对于读取性能基本上不构成太大的影响。

测试中吞吐量上限基本达到客户端千兆网瓶颈,因此通过增加网络带宽依然有可以提升的空间。

图7:读操作吞吐量对比

七、结论

SequoiaDB的大对象机制主要为用户存储海量中小型文件所设计。通过配置pagesize大小,SequoiaDB在存储100KB到100MB区间内的文件性能与磁盘开销比例最优,因此针对各个企业的票据、扫描件、合同件、照片、小视频、音频等文件最为适用。

总体来看,使用SequoiaDB替代传统ECM,为企业存储海量中小型文件不单能够大大降低企业的总体拥有成本,还能够大幅度提升数据访问层面的吞吐量,并从开发、运维、管理等各个层面大幅度降低使用难度,帮助企业更快地在企业内容管理系统上落地。

原文发布于微信公众号 - CSDN技术头条(CSDN_Tech)

原文发表时间:2016-08-18

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏沈唁志

【收藏】Python 爬虫的工具列表大全

2264
来自专栏码洞

Python最广为使用的并发库futures使用入门与内部原理

在使用Python处理任务时,限于单线程处理能力有限,需要将任务并行化,分散到多个线程或者是多个进程去执行。

1341
来自专栏腾讯Bugly的专栏

Redex 初探与 Interdex:Andorid 冷启动优化

导语 早在去年10月份,facebook就发布了介绍redex的文章,这个据说可以直接对apk做处理,既提高启动性能,又可减少安装包的利器让安卓开发者们都心动不...

5556
来自专栏happyJared

用Python统计你的简书数据

  说来也巧,之前有一次无意间留意到简书好像没有做文章总阅读量的统计(准确的说法应该叫展示),刚好最近有时间,趁这个机会就用Python写了这么个功能,既是学习...

1561
来自专栏Play & Scala 技术分享

PlayScala 2.5.x - 实现完全异步非阻塞的流数据导出

2884
来自专栏mukekeheart的iOS之旅

JSON与XML的区别比较

1.定义介绍 (1).XML定义 扩展标记语言 (Extensible Markup Language, XML) ,用于标记电子文件使其具有结构性的标记语言,...

4147
来自专栏linjinhe的专栏

LevelDB:Compaction

LevelDB 的写操作是 Append-Only 的,新的数据写入后,相应的旧数据就过期了。过期的数据需要被 Garbage Collection,不然数据文...

4026
来自专栏Youngxj

SpeedTest lite服务器测试源码分享

6555
来自专栏前端大白专栏

基于mpvue开发微信小程序(项目已开源)

花了两周时间,我的微信小程序终于开发完了(平时上班,基本上都是业余时间开发的). 下面来介绍一下项目的功能以及结构. 用到的技术栈 vue2+weui+es6;...

5479
来自专栏北京马哥教育

快收藏!史上最全156个Python网络爬虫资源

awesome系列真是碉堡了~今天把Python的爬虫工具搬过来~ ——————译文分割线—————— 本列表包含Python网页抓取和数据处理相关的库。 网络...

3654

扫码关注云+社区

领取腾讯云代金券