@liuhui0803
2017-06-23T10:13:17.000000Z
字数 5978
阅读 2300
数据科学
NoSQL
关系型数据库
无服务器
云计算
摘要:
FaunaDB无服务器云是托管版本的FaunaDB,这是一种无服务器架构、对象关系型、全球复制、强一致的时间(Temporal)数据库,可部署在诸如AWS、GCP、Azure等多种云中,或用户本地环境内。
正文:
主要结论
- FaunaDB的主要功能包括:无服务器、对象关系型、图形(Graph)、全球复制、ACID、时间(Temporal)、支持联接(Join)、外键、企业安全性等。
- 事务中可进行数据库查询操作,并可由无服务器函数或客户端在边缘位置直接提交。
- 对象级访问控制帮助开发者省略设置身份验证上下文的任务,并可使用纵深防御技术增强安全性。
- 本文对比了DynamoDB和FaunaDB,展示了如何将数据从前者移植至后者。
今年春季,Fauna发布了FaunaDB无服务器云(Serverless Cloud):首个专为无服务器应用程序设计的数据库。与传统的云端数据库即服务产品不同,该产品提供的基本功能可以帮助开发者安全地构建并运行无服务器应用程序,而无须配置或运维基础架构。
Fauna最初于四年前开始开发FaunaDB,远远早于“无服务器”架构的诞生。在体会到管理服务器和数据库基础架构的痛苦后,Fauna团队决定解决这个问题。他们开发的这个数据库为无服务器应用程序提供了完美支持,这其实是一个趋同进化的问题。诞生于2016年的无服务器技术作为一种应用程序架构进一证实了Fauna所采取方法的有效性。
FaunaDB无服务器云是FaunaDB的托管版本,而FaunaDB是首个可自适应的运维数据库。FaunaDB是一种对象关系型、全球复制、强一致的时间数据库。该产品在多个方面进行了适当的取舍,以一种NoSQL的方式对JSON提供了良好支持,但同时也支持联接、外键、唯一索引,以及其他必要关键功能,但并不像SQL那么复杂或不安全。该产品还可原生支持分布式图形和图形函数,尤其适合存储包含数十亿节点和边缘,高度聚集的图形,实现其他系统无法实现的工作负载。所有功能均具备ACID一致性和企业级安全性,因此该产品适合极为广泛的用例,从社交网络映射到将变更引入应用,再到实现需要分类账和全球分布的重要金融应用,均可得到妥善支持。
无服务器架构正在对需要通过现代化开发实践协调数据库基础架构的开发者展现出越来越强的吸引力。虽然很多人依然在忙于将应用程序解耦成微服务,并逐渐迎合持续交付等趋势和原则,但数据库依然固守在单体(Monolithic)应用的模式,而应用程序栈的其他层已经变得更简单、更便宜、更易用。逆流而上的数据库基础架构依然昂贵、脆弱、难以运维。随着应用程序开发工作变得更加高效,数据库方面遭遇的痛点也愈加严重。
对很多人来说,无服务器数据库这一概念与无服务器这一原则是背道而驰的。无服务器架构被称之为“函数即服务”(FaaS),即事件驱动的架构。开发者只需要简单地编写函数并将其部署至基础架构即可。基础架构会在函数被调用时开始执行。其余时间里,函数处于休眠状态,不耗费任何资源。如果将这一特性应用于无服务器数据库,似乎会产生一种悖论:无服务器函数是暂存的,而按照定义,数据层应该是持久的。
最大的问题在于,目前现有数据库主要是面向传统应用程序构建的,需要在一个地理位置通过一系列固定的服务器持续运行。为了恰当地使用这些数据库,应用程序开发者需要知道大量有关数据库配置的信息。在最糟糕的情况下,高可用和性能完全取决于开发者对数据库内部机制的了解。开发者需要了解并配置诸如区域、地域、数据量、内存、软件版本、CPU等信息。团队需要花费大量时间考虑容量规划、配置、切片、备份、性能调优、监视等问题。当你80%的时间用于配置和运维数据库,仅仅是为了向无服务器函数提供支持时,你会发现一定有什么东西被忽略了。虽然AWS Lambda和无服务器架构提高了计算层弹性,但如果你需要存储数据,持久存储层并不能从这样的弹性中获益。
FaunaDB无服务器云通过下列方式解决了这些问题:
在使用FaunaDB无服务器云构建和运行应用时,开发者无需了解有关基础架构的任何细节,例如节点规模、内存,或存储。AWS Lambda正是通过同样的方式提出了按照每一个函数的调用进行收费的举措,FaunaDB无服务器云的消耗则是通过“Fauna点数”的方式衡量的。Fauna点数是对不同工作负载所消耗计算和存储资源进行的量化体现,而这也正是无服务器数据库的精髓:用户绝对不会为闲置的容量付费。数据库用量主要可通过函数的调用和工作负载来体现,仅此而已。
对于标准化DBaaS产品,只能通过超量配置的方式应对流量激增。FaunaDB按用量付费的定价方式可防止浪费的超量配置,因为FaunaDB可在无需用户介入的情况下进行弹性伸缩,开发者可随时使用而无需预先规划容量。应用程序总是能获得足够的容量,不会因为限制容量无谓地产生成本。FaunaDB的使用成本可以随着用量一起伸缩,用户永远无需为未使用的容量付费。
FaunaDB提供了极具表现力的查询语言,非常适合无服务器环境。无需学习新语法,用户即可将FaunaDB查询写入自己使用的任何语言中。
下文列举了一个使用Javascript的FaunaDB查询范例。在这个查询中,我们首先检索用户,随后返回了用户全名组成的字符串:
var faunadb = require('faunadb'),
q = faunadb.query;
q.Let(
{ user: q.Get(q.Ref(q.Class("users"), "279364341312414")) },
q.Concat(
[ q.Select(["data", "first_name"], q.Var("user")),
q.Select(["data", "last_name"], q.Var("user")) ],
" "
)
)
其他语言中的表达同样简单。Fauna提供了适用于Android、Swift、JavaScript、Ruby、Java、Scala、C#、Python,以及Go的驱动。
FaunaDB查询语言的完整文档请参阅这里。
大部分NoSQL查询语言通常只能针对数据提供CRUD操作,因此往往很难在SQL中编写复杂的业务规则。但FaunaDB的查询语言更类似于常规用途的通用编程语言。我们可以用熟悉的功能以直观的方式编写应用程序逻辑,例如if语句、变量赋值,以及Map、Foreach、Filter等丰富的函数化编程工具。此外由于FaunaDB查询是自动事务型的,用户永远无需担心代码在查询过程中崩溃导致数据处于不完整(Half-written)状态。
下文列举了一个功能更强大的例子,可以按照地区显示伍德赛德市(Woodside)犯罪追踪报告中的变化情况,但会排除调用者自身所在的地区。该范例展示了图形查询、多级联接、索引,以及时间等特性,所有这些特性可用在一个查询中。
q.Map(
q.Paginate(
q.Join(
q.Intersect(
q.Join(
q.Difference(
q.Match(q.Index("districts_by_city"), "Woodside"),
q.Ref("classes/districts/1")),
q.Index("users_by_district")),
q.Match(q.Index("users_by_group"), "Crime Watch")),
q.Index("reports_by_user")),
{
events: true,
after: q.Date("2017-1-1")
}
),
function(event), { return q.Get(q.Select("ref", event)) }
)
FaunaDB一个最重要的独有特性在于其无服务器安全模型。FaunaDB固有的安全性意味着用户无需通过中间件执行任何身份验证或授权检查。这样开发者就不需要编写多余,并且非常易于出错的样板功能(Bilerplate function),例如用于设置身份验证上下文或管理应用一致性的代码。举例来说,用户的无服务器FaunaDB数据库可以知道谁撰写了某篇博客文章,随后限制其他用户只具备读取的权限。
下列查询可创建一篇博客文章。所有人均可读取该文章,但我们希望只有作者可以编辑。为此可做如下设置:
q.Create(q.Class("posts"), {
data: {
text: "..."
},
permissions: {
read: "public",
write: q.Ref(q.Class("users"), 123)
}
})
用户向FaunaDB发起的后续请求可以假定用户身份,FaunaDB会强制实施事先配置的权限:只有本文作者可以修改,所有其他人只能读取。Lambda本身无需了解具体所有权,自然也不会产生安全漏洞。由于业务规则已建模在数据库中,因此系统面对可能导致对数据进行未经授权访问的Bug可获得额外的保护。这种方式更简单也更安全,同时大幅减轻了无服务器应用的负担。最棒的地方在于,如果使用API网关,网关可以将用户的数据库访问令牌传递给Lambda函数,这样函数即可透明地以用户身份与FaunaDB交互。
如果打算在诸如AWS Lambda这样的云平台上运行函数,此时可以使用Serverless框架。Serverless框架已成为市场主流,提供了一种简洁的系统,可以帮助我们配置、编写、部署无服务器应用程序代码到不同的云基础架构。
下文的范例展示了将无服务器架构的存储从DynamoDB移植到FaunaDB的过程。借此可直观对比FaunaDB与DynamoDB查询,同时还可以看出设置使用FaunaDB作为持久层的无服务器环境,整个过程到底有多简单。
该应用是一个简单的REST API,可创建、更新、删除“todo”项。此外还可列出所有“todo”的次数。所有代码和相关说明已发布至GitHub。
Serverless框架提供了一种格式化的serverless.yml,该文件定义了服务,并将函数链接至事件处理程序。
readAll
的函数定义如下:
functions:
readAll:
handler: handler.readAll
events:
- http:
path: todos
method: get
cors: true
该配置意味着handler.js中的readAll函数会在todos路径收到HTTP GET后调用,该函数会链接至handler.js。
module.exports.readAll = (event, context, callback) => {
todosReadAll(event, (error, result) => {
const response = {
statusCode: 200,
headers: {
"Access-Control-Allow-Origin" : "*"
},
body: JSON.stringify(result),
};
context.succeed(response);
});
};
Handler.js中的所有内容只需考虑HTTP的管理,因此每个函数的实际逻辑可从模块中导入。本例中的模块是todos-read-all.js。这正是FaunaDB的用途所在。
'use strict';
const faunadb = require('faunadb');
const q = faunadb.query;
const client = new faunadb.Client({
secret: process.env.FAUNADB_SECRET
});
module.exports = (event, callback) => {
return client.query(q.Paginate(q.Match(q.Ref("indexes/all_todos"))))
.then((response) => {
callback(false, response);
}).catch((error) => {
callback(error)
})
};
通过这样的配置,我们便可以轻松地使用通过serverless.yml配置传递的FaunaDB秘密(Secret),为所有todo项运行查询。这个例子远比完整的对象级访问控制所能实现的功能简单。若要进一步了解FaunaDB的访问控制,可参阅Chris Anderson在Serverless.com发表的,有关身份验证和授权的博客文章。FaunaDB查询会使用HTTP,因此无需担心要在不同模块或调用之间共享连接。
DynamoDB和FaunaDB版本之间的主要差异在于,下列语句:
return dynamoDb.scan({TableName: 'todos'}, (error, data) => { … })
变成了:
return client.query(q.Paginate(q.Match(q.Ref("indexes/all_todos"))))
FaunaDB无服务器云是唯一针对无服务器应用设计的数据库。该数据库只需要最少量时间进行设置,不会造成费用负担。对于企业来说,无服务器架构可以帮您随时对业务进行伸缩,同时可真正降低成本。相比其他数据库,该技术的配置步骤少,无需运维介入,管理负担更轻。独特的定价方式意味着您的基础架构成本只取决于实际的资源消耗情况。
尽管无服务器架构是一种新概念,但FaunaDB技术本身已经获得了证实。该技术的开发完全围绕现实世界中的运维工作负载,很多客户已经在生产环境中运行该技术超过一年的时间。目前全球有上千万用户正在使用,这也意味着您可以放心地通过无服务器数据库构建您的无服务器应用。
在这里注册免费试用,您将免费获得1,000,000个Fauna点数。
Matt Freels是Fauna的CTO兼共同创始人。Matt曾担任Twitter数据库团队的技术主管,在Twitter任职时,Matt曾与同是Fauna共同创始人的Evan Weaver合作负责面对爆发性增长过程中服务的伸缩工作。在加入Twitter之前,Matt曾帮助社交游戏公司Serious Business处理伸缩问题,该公司的伸缩规模一度甚至超过了Twitter。Matt主要关注设计编程语言和分布式系统的构建,他住在伯克利,喜欢演奏贝司和攀岩。