FoundationDB:支持事务的NoSQL数据库

clip_image001

FoundationDB2012年发布了Alpha版本,2013年发布Beta版本,2015年被苹果收购。据说最早是开源数据库,后来被苹果收购闭源了,2018年4月19日,苹果正式发布5.1.7版本,并宣布FDB开源(https://apple.github.io/foundationdb/)。

一、FDB的体系架构:

clip_image002

FDB是一个支持事务的多模型核心KVStore。核心的意思是,FDB仅支持最重要的特性的API。FDB网站很值得学习,不仅仅介绍了自己的产品FDB,还介绍了设计思路。不过FDB的设计并没有什么特别的地方,基本上有5个部分:

1、存储节点集群。只解决数据存储的可靠性问题,针对SSD优化,对HDD依然支持,但没有特别优化

2、协调集群。使用PAXOS算法选主集群,不介入事务处理(为1和3服务)

3、事务管理集群。用来支持ACID事务。

4、层和客户端。层是用来支持多模型的,虽然应用可以直接访问核心层,但是通过层可以封装更简单的API和更复杂的逻辑。这个部分用来完成数据交互,基本策略是,应用需要了解自己数据实际上是分片的,要有一些针对FDB的优化设计。从某种意义上看,NoSQL运动的一个重要作用在于打开了RDBMS这个黑盒子,把存储引擎、管理和仲裁、查询引擎三个部分解耦了。此外NoSQL还带动了分布式数据库的发展。

2.1 FDB的设计限制:

1、一个事务不能超过10,000,000字节,约10MB数据(全部包括)【有方案】

2、Key不能大于10000字节,约10KB数据;Value不能超过100,000字节,约100KB【有方案】

3、不支持细粒度的权限控制,用户可以访问全部数据

4、区段扫描速度慢【有方案】

2.2 FDB 5.1 目前尚未实现的能力:

1、一个事务必须在5秒内结束,否则抛出异常(transaction_too_old 或者 not_committed),一般事务15ms【有方案】

2、集群规模在超过500个core/process之后,性能不能线性增长(20台左右2路16核的服务器)

3、数据库在100TB以上后,数据复制会造成磁盘容量显著增长,以及额外开销。

4、由于尚未对热点数据做多副本,因此集群针对某个Key的读性能不会超过3个节点(或者进程),通常是10万RPS量级【有方案】

二、FDB数据模型

1、FDB的数据模型是非常简单的,主要涉及到核心的排序KV模型,FDB中每个数据都是按照Byte String排序的,因此整数、浮点数、多字节数据都是需要序列化之后才能保持有序,这个任务交给了应用系统。任性!!

2、FDB的灵活性来自Tuple这个数据模型,这个模型可以构成很多个字段构成的元组,而且这些元组也是依次有序的,这一点为复杂数据模型设计提供了基础,包括Map、Array、MultiMap、Table、ER模型、Index、体系化数据、文档、链表。仔细研究了Index、Table部分,立刻就明白了以前看到的AWS SimpleDB的一个设计问题:索引太多问题造成数据膨胀。这个问题实际上是早期应用规划不善,最后造成每个列都要建立索引造成的问题。并不仅仅是NoSQL的问题,SQL领域更为严重,而且无法解决。

3、Key的设计没有更多的新花样,只要知道HBase怎么设计Key,在FDB中依然可用,值得注意的是:(1)Key的结构化很重要,可以消除无效查找(2)缩小Key的范围,避免一个Key映射到太多数据(3)Key要小,32字节最好,小于1KB,不能超过10KB(4)Value小于10KB(最大100KB)… 看来不能用于存储图像了【https://apple.github.io/foundationdb/tutorials.html

三、FDB的应用:支持Java、Python、Ruby、Go、C 5种语言

自带的例子,可以跑的通,JDK8

import com.apple.foundationdb.Database;
import com.apple.foundationdb.FDB;
import com.apple.foundationdb.tuple.Tuple;

public class Example {
public static void main(String[] args) {
FDB fdb = FDB.selectAPIVersion(510);

try(Database db = fdb.open()) {
// Run an operation on the database
db.run(tr -> {
tr.set(Tuple.from(“hello”).pack(), Tuple.from(“world”).pack());
return null;
});

// Get the value of ‘hello’ from the database
String hello = db.run(tr -> {
byte[] result = tr.get(Tuple.from(“hello”).pack()).join();
return Tuple.fromBytes(result).getString(0);
});

System.out.println(“Hello ” + hello);
}
}
}

 

相关信息:

https://en.wikipedia.org/wiki/FoundationDB

https://apple.github.io/foundationdb/

https://apple.github.io/foundationdb/technical-overview.html

发表评论

电子邮件地址不会被公开。 必填项已用*标注