`
iunknown
  • 浏览: 409327 次
社区版块
存档分类
最新评论

SPHiveDB: 基于 sqlite 的数据库服务器

阅读更多
在 share nothing 的架构中,如果数据规模很大,为了提高可用性,通常采用数据库分片(database sharding)的策略。常见的分片策略是按主键把数据分散到不同的数据库中。在使用常规的 RDBMS 的场景中,分片策略中使用的数据库个数通常在100以下。在某些特殊的场景中,可能希望采用更极端的分片方法,比如在类似地址本这种应用中,可以为每个用户创建一个数据库。

SPHiveDB 就是为这种极端的分片方法而实现的一个数据库服务器。SPHiveDB 基于 sqlite ,用 JSONRPC over HTTP 为 sqlite 提供了网络访问接口。为了能够支持大量的数据库实例,SPHiveDB 把多个 sqlite 数据库合并保存到一个文件中;支持同时使用多个数据库文件。

http://code.google.com/p/sphivedb/
http://freshmeat.net/urls/01b9b3be9ec4e19ebd6a8e6208f3a0a1
http://sphivedb.googlecode.com/files/spmemvfs-0.2.src.tar.gz

×× 内部结构示意图



SPHiveDB 使用 Tokyo Cabinet 作为最终的物理存储,每个用户对应的 sqlite 数据库以用户名为 key 保存在 Cabinet 中。为了支持能够从 Cabinet 中加载 sqlite 数据库,为 sqlite 实现了一个 memvfs 。通过 memvfs ,使得 sqlite 能够在内存中加载和保存数据。SPHiveDB 支持一个进程同时使用多个 Cabinet 文件,使得单一 server 能够支持尽可能大的存储空间。


×× JSONRPC 请求和响应示例

{
        "method" : "execute",
        "params" : [
                {
                        "dbfile" : 0,
                        "user" : "foobar",
                        "dbname" : "addrbook",
                        "sql" : [
                                "insert into addrbook values ( 1, \"foo@bar.com\" )",
                                "select * from addrbook"
                        ]
                }
        ],
        "id" : "foobar"
}


dbfile 指定操作哪一个 Cabinet 文件;user + dbname 指定操作哪一块数据;sql 需要执行的 sql 语句,支持批量执行多个 sql 语句,使用 all-or-nothing 的策略,要么全部成功,要么全部失败。dbname 还用于指明第一次操作一块数据时,用什么语句来创建 sqlite 数据库。用于创建 sqlite 数据库的语句保存在 sphivedbsvr.ini 配置文件中。以 ddl. 开头的配置节用于指定对应数据库的创建语句。

[ddl.addrbook]
create table if not exists addrbook ( id int, addr varchar(64) );


{
        "result" : [
                {
                        "name" : [ "affected", "last_insert_rowid" ],
                        "type" : [ "int", "int" ],
                        "row" : [ [ 1, 1 ] ]
                },
                {
                        "name" : [ "id", "addr" ]
                        "type" : [ "int", "varchar(64)" ],
                        "row" : [ [ "1", "foo@bar.com" ] ],
                }
        ],
        "id" : "foobar"
}


result 返回 sql 语句执行的结果,name 对应的 array 为 column 的名字,type 对应的 array 为 column 的类型,row 对应的 array 是返回 recordset 。特别地,对于 INSERT/UPDATE/DELETE 也使用类似 select 的方式来返回,affected 是 sql 语句执行之后 sqlite3_changes 返回的值,last_insert_rowid 是 sql 语句执行之后 sqlite3_last_insert_rowid 返回的值。
  • 大小: 2.6 KB
分享到:
评论
23 楼 work4blue 2013-05-24  
楼主你好,我们现在做一个云POS系统。 这个架构是否能用SPLiveDB来实现呢?

这个数据库架构是这样的。

1.前台收银机,每一台都有一个sqlite交易数据库。
2.交易数据定时汇总到后台的汇总数据库当中,它也是一个大的Sqlite.
3.但是现在问题是每个交易数据库可能不一定能及时汇总,这样在后台可以就会出现很多
sqlite库同时存在。这种情况合适把Sqlite改成SPHLiveDB的架构吗?比如我就把所有交易数据
单独做一个库放在里面?

4.汇总数据库可以会通过web 进行管理和查询的操作。 如果是一般的SQlite可能会有并发写的失败。这个通过json 会处理这个问题吗?

请指教,我的常在微博上,http://weibo.com/work4blue
22 楼 iunknown 2009-07-07  
willko 写道
请教楼主,tc里的table database是怎么一回事。。
这个类型是新加的。。以前只有hash table、b tree、fixed-array


tctdb 是在 tchdb 的基础上,对 value 部分做了一个增强,value 是一个 map 。
可以对比一下 hdb 和 tdb 的 api 。

引用

bool tchdbput(TCHDB *hdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz);

void *tchdbget(TCHDB *hdb, const void *kbuf, int ksiz, int *sp);

bool tctdbput(TCTDB *tdb, const void *pkbuf, int pksiz, TCMAP *cols);

TCMAP *tctdbget(TCTDB *tdb, const void *pkbuf, int pksiz);


21 楼 willko 2009-07-06  
请教楼主,tc里的table database是怎么一回事。。
这个类型是新加的。。以前只有hash table、b tree、fixed-array
20 楼 iunknown 2009-07-06  
mathgl 写道
good..楼主这个东西开始运用没有?


我自己还没有在实际项目中使用,暂时还未找到合适的项目来应用。
目前还有一些功能想要实现,包括清除一个用户的数据,获取整个数据库的 buffer 。
清除一个用户的数据,在有些场景下,是必须要有的功能。
19 楼 mathgl 2009-07-06  
good..楼主这个东西开始运用没有?
18 楼 iunknown 2009-07-04  
发布 0.5 版。新增特性
1.增加完整的 C++ client api ,支持多个 server
2.增加 java client api ,还不支持 http 长连接
3.增加了一个压力测试工具,压力测试结果表明 sphivedbsvr 的确比 spsqlitesvr 快
4.修正了一个加锁失败的 bug

http://sphivedb.googlecode.com/files/sphivedb-0.5.src.tar.gz

client 端配置文件,配置连接池和多个 server
$bash# cat sphivedbcli.ini 

[SocketPool]
ConnectTimeout = 6
SocketTimeout  = 6
MaxIdlePerEndPoint = 10
MaxIdleTime = 3600

[EndPointTable]
EndPointCount = 2
TableKeyMax = 1000           ; 指明目前使用多少个 cabinet 文件

[EndPoint0]
KeyMin = 0
KeyMax = 499                 ; server0 负责处理的文件是 0-499
ServerIP = 192.168.119.128
ServerPort = 8080

[EndPoint1]
KeyMin = 500
KeyMax = 999                 ; server1 负责处理的文件是 500-999
ServerIP = 192.168.119.129
ServerPort = 8080

17 楼 liusong1111 2009-06-30  
mongodb有针对各平台编译好的包,我没从源码编译。
http://www.mongodb.org/display/DOCS/Downloads

更正,最新版本是0.9.5。

还有个需要更正,关于分布式文件系统和mongodb数据库的由来,作者是这样写的:
http://www.10gen.com/blog/2008/7/you-don-t-need-a-file-system

引用
When we began the 10gen project, we wanted a fast, scalable database.  The question then became: if it is fast and truly scalable, why do I need a separate filesystem?  If we needed one, that would mean we had not achieved our goals in terms of database performance.  It's a great litmus test: take a database, and implement a file system atop it.

Does it work?  Yes, it is working quite well.  GridFS, the 10gen file system interface, is simply a thin layer atop the Mongo db.


我前面说反了。

这篇博客连同后面的comments都值得一读。
读后感:对于桌面系统、服务器和分布式环境上的文件系统,需要的功能有很大差异。而且,分布式环境下的文件系统和数据库在功能需求上有很多重合的地方,所以,这种建立在 “泛数据库”之上的文件系统,想像空间更大,比如,借助数据库的能力给文件添加元数据,借助文件系统的能力让数据库更具可伸缩性。我理解的分布式文件系统,是一种”虚拟文件系统“。

关于map-reduce和RDBMS的争论,那些大牛们都吵过了,总的来说map-reduce核心是个算法,不是存储,与RDBMS不在一个层面上。但多数map-reduce框架都提供存储(GFS、HDFS..)。象GFS、mongodb这样的存储跟RDBMS的不同在于前者的侧重点在于海量数据、分布式、容错,而不看重写操作(比如transaction)。

有什么东西是SQL做不到或做不好而map-reduce做的好的呢?我看到的例子都是如何处理半结构化或非结构化数据。我觉得还有个问题是传统RDBMS只允许用户使用SQL、存储过程进行操作,高级点的允许嵌入java代码,但代码执行的时机或者是用户发起的,或者是特定的触发时机(trigger,scheduler),并没有提供底层更细节步骤的定制入口,比如传入一个函数,用来定制group_by,aggregation等。看mongodb:
http://www.mongodb.org/display/DOCS/Aggregation

引用
Similar to SQL group by. For example:
select a,b,sum(c) csum from coll where active=1 group by a,b


corresponds to the following in MongoDB:

db.group(
           {ns: "coll",
            key: { a:true, b:true },
            cond: { active:1 },
            reduce: function(''obj'',''prev'') { prev.csum += obj.c; },
            initial: { csum: 0 }
            });



这里的reduce是实现的sum算法,但通过传入函数,可以定制更复杂的aggregation函数。同理,group_by可以通过指定keyf传入函数 - 比如做map-reduce的经典工作:对大量文档进行分析,做单词索引。缺少了这个,我不知道建立在RDBMS上的OLAP会不会痛苦?

作为一个开发者,我喜欢:
1. 对SQL执行的细节步骤开放定制接口。
2. 最好是把数据库当成lib用,本地代码和SQL可以混着用,写法可以跟LINQ相似或不同,关键是数据库直接执行混合代码。--难度很大。

有什么东西是map-reduce做不好而SQL做的好的呢?相对于map-reduce算法,RDBMS在机制上,或者SQL语言在表述上有没有本质性的障碍?我看到很多数据库都提供了部分并行计算功能,那么是不是可以认定map-reduce和数据库可以鱼与熊掌可以兼得?这些也是我一直存有疑虑的地方。

让我给拐跑题了。









16 楼 iunknown 2009-06-29  
下载了一份代码,可惜不是用 make 来 build 的,暂时没有办法编译运行。
简单看了一下,有如下几个印象:
1.client 端 api ,使用不是 sql ,而是一套自定义的查询语法
2.用到了 boost, libexecinfo, pcre, spidermonkey 这几套库
3.要使得对象能够保存到 mongodb 中,需要从 Model 类继承

btw:现在有越来越多的项目用 scons 来 build 了
15 楼 liusong1111 2009-06-29  
cabinet可以当HDB、BDB、FDB、TDB,偏偏不是Document-oriented DB,我觉得这是问题的症结:楼主需要的是一个有tokyo cabinet特征(轻量、可靠、高效)的document-oriented DB。
我昨天查了一下,mongodb看上去比较符合上述条件:

http://www.mongodb.org
引用
MongoDB is a high-performance, open source, schema-free document-oriented  database. MongoDB is written in C++ and offers the following features:

    * Collection oriented storage - easy storage of object-style data
    * Dynamic queries
    * Full index support, including on inner objects
    * Query profiling
    * Replication and fail-over support
    * Efficient storage of binary data including large objects (e.g. videos)
    * Auto-sharding for cloud-level scalability (Q209)

A key goal of MongoDB is to bridge the gap between key/value stores (which are fast and highly scalable) and traditional RDBMS systems (which are deep in functionality).


这是一个较新的开源产品,但看起来也有模有样了,目前版本0.9,文档很全,开发活跃度很高,支持多种语言的客户端(它称为Driver),我试了ruby的,感觉相当好。
据说性能不错,能管理大数据量,作者发过一篇博文,大致意思是搞文件系统没用(GFS、HDFS那种分布式文件系统),如果数据库就能做到呢?他们以前做过一个叫GridFS的文件系统,后来成为mongodb的基础了-- 在云计算里弄潮的数据库都走轻量级、简约化路线了。

它提供了master-slave模式和sharding机制,似乎还比较初级(?)。

从它的roadmap上看,我最期待的是map-reduce支持,因为尽管SQL语言作为一种DSL,在应对多数问题上提供了很好的抽象和表达能力,但对于某些复杂情况却不好用。这时,传统数据库只支持SQL(包括存储过程),反而成了一个大大的限制。目前主流数据库只支持有限制的并行计算,而完全支持map-reduce的只看到一个商业产品greenplum。

象cabinet这种作为lib被任意语言直接使用的方式让我感觉很舒服。(或许我需要先恶补一个BI常识?)

用过mongodb或类似轻量级解决方案的朋友,谈谈看法吧。

14 楼 iunknown 2009-06-26  
发布 0.4 版。新增特性
1.支持在一个数据库中创建多个表
2.把 sqlite 的错误代码和错误信息返回给客户端

http://sphivedb.googlecode.com/files/sphivedb-0.4.src.tar.gz

支持多个表,简单的例子如下
[ddl.addrbook]
create table addrgroup ( gid INTEGER PRIMARY KEY AUTOINCREMENT, name varchar(64) );
create table addrbook ( id INTEGER PRIMARY KEY AUTOINCREMENT, gid int, addr varchar(64), freq int, unique( addr ) );


假设地址本需要支持分组,有一个 addrgroup 表,addrbook 表有一个 gid 来标识每个地址所属的组。

至此,sphivedb 的功能算是比较完整了。
13 楼 mathgl 2009-06-24  
iunknown 写道
mathgl 写道
只是类似。。我们是multi-tenant application
每个tenant 对应若干个 .tch file

mysql 存放相关索引。--》 tch的key value



第一次听说 multi-tenant 这个名词,查了一下,貌似是 SaaS 领域中的一个概念?

引用

在多租户(multitenant)模型中,多个客户端使用相同的应用程序体系结构,这有助于控制成本。举个例子来说,公司可以根据需要来购买和使用处理能力,而不会将成本投资于除高峰期之外一直空闲的体系结构中。


这种模型和 one database per user 模型的确很相似。在 multitenant 模型中,应该说是 one database per tenant 。


你这个模型 对我有些启发。。现在我有个比较奇怪的问题是 每个user中需要保存大量的session数据,这些数据多到光用memcached是不能解决的, 用share-nothing结构,为每个user都建立单独的sqlite db很合适。下一步我会考虑这样改进。

有空多交流。
12 楼 iunknown 2009-06-23  
mathgl 写道
只是类似。。我们是multi-tenant application
每个tenant 对应若干个 .tch file

mysql 存放相关索引。--》 tch的key value



第一次听说 multi-tenant 这个名词,查了一下,貌似是 SaaS 领域中的一个概念?

引用

在多租户(multitenant)模型中,多个客户端使用相同的应用程序体系结构,这有助于控制成本。举个例子来说,公司可以根据需要来购买和使用处理能力,而不会将成本投资于除高峰期之外一直空闲的体系结构中。


这种模型和 one database per user 模型的确很相似。在 multitenant 模型中,应该说是 one database per tenant 。
11 楼 mathgl 2009-06-23  
iunknown 写道
mathgl 写道
很好,,这个和我目前的架构有些类似的地方。

不过我是用 mysql来存放tokyo cabinet的key。



能否描述一下你的架构呢?在网上找了一下,很少有类似架构的描述


只是类似。。我们是multi-tenant application
每个tenant 对应若干个 .tch file

mysql 存放相关索引。--》 tch的key value
10 楼 iunknown 2009-06-23  
ideafrog 写道
对数据文件格式,是如何设计的,能否多说点。

我在考虑,这会涉及数据读取方面,而这个是比较关心的


底层的物理存储,sphivedb 用的是 tokyo cabinet ,spsqlitesvr 直接使用 sqlite 。这个项目本身没有设计自己的文件格式。要说有一点相关的,就是在 tokyo cabinet 里面,用 user 作为 key ,sqlite 的数据库整个作为一块 buffer 保存为 对应的 value 。
9 楼 ideafrog 2009-06-23  
对数据文件格式,是如何设计的,能否多说点。

我在考虑,这会涉及数据读取方面,而这个是比较关心的
8 楼 iunknown 2009-06-23  
dogstar 写道
http://timyang.net/architecture/yahoo-pnuts/



引用


物理的存储服务器,每个存储服务器上面含有多个tablets,tablets是PNUTS上的基本存储单元。一个tablets是一个yahoo内部格式的hash table的文件(hash table)或是一个MySQL innodb表(ordered table)。一个Tablet通常为几百M。一个SU上通常会存在几百个tablets。

以hash为例介绍,先对所有的tablets按hash值分片,比如1-10,000属于tablets 1, 10,000到20,000属于tablets 2,依此类推分配完所有的hash范围。一个大型的IDC通常会存在100万以下的tablets, 1,000台左右的SU。tablets属于哪个SU由routers全部加载到内存里面,因此router访问速度极快,通常不会成为瓶颈。按照官方的说法,系统的瓶颈只存在磁盘文件hash file访问上。




从这段描述来看, pnuts 在逻辑上是一个单一的表,然后支持了类似 mysql 分区的功能,当然这个分区的功能比 mysql 强大很多。
7 楼 iunknown 2009-06-23  
花花公子 写道
JSON-RPC不如 cloudkit 使用的REST接口直观



所谓的 REST 接口,现在还不懂,稍后 google 一下。
就以 cloudkit 的接口来看,它的功能是完全针对 json 数据库来做的。

sphivedb 采用 json-rpc ,是使用 json 来封装 sql 和 resultset 。
同时 json-rpc 几乎也在所有的语言中都有实现,容易做多语言的支持。
6 楼 dogstar 2009-06-22  
http://timyang.net/architecture/yahoo-pnuts/
5 楼 花花公子 2009-06-22  
JSON-RPC不如 cloudkit 使用的REST接口直观
4 楼 iunknown 2009-06-22  
mathgl 写道
很好,,这个和我目前的架构有些类似的地方。

不过我是用 mysql来存放tokyo cabinet的key。



能否描述一下你的架构呢?在网上找了一下,很少有类似架构的描述

相关推荐

Global site tag (gtag.js) - Google Analytics