引言
当前大多数流行的应用程序,比如谷歌和亚马逊,已经实现了高可用性和并发服务数百万用户的能力,这些应用程序可以在多台机器之间横向扩展,分布在多个数据中心。
Google 和 Amazon 等大型 Web 应用程序的成功案例已经证明,在水平扩展环境中,NoSQL 解决方案往往比关系应用程序更加出色。按需提供并按需提供的水平扩展环境被称为“云”如果可伸缩性和可用性是您的首要任务,那么云中的 NoSQL 可能是理想的设置。
在某些情况下,关系存储和非关系存储都被结合使用。如果说只有 NoSQL 可以在水平缩放的环境中工作,那是不准确的。很大程度上取决于应用程序中所需的规模、底层数据结构和事务完整性期望。
存在许多云服务提供商,并且有多个 NoSQL 产品可用。在许多情况下,比如 AmazonEC2(弹性计算云) ,您可以选择安装任何您想要使用的 NoSQL 产品。
谷歌通过推出一个服务准备就绪、易于使用的基础设施,彻底改变了云计算的面貌。然而,谷歌并不是第一个推出云服务的公司。当谷歌第一次宣布其服务时,亚马逊 EC2已经是市场上一个成熟的参与者。不过,谷歌的模式是如此方便,以至于它的云平台——谷歌应用程序引擎(Google App Engine,GAE)在很短的时间内就得到了广泛而迅速的采用。应用程序引擎并非没有局限性。它的沙箱环境和缺乏对长时间运行流程的支持是其中一些非常不受欢迎的方面。
谷歌应用程序引擎数据存储
谷歌应用程序引擎(Google App Engine,GAE)为应用程序提供了一个沙箱部署环境,这些应用程序使用可以在 Java 虚拟机(jVM)上运行的 Python 或语言编写。Google 为开发人员提供了一组丰富的 API 和一个 SDK 来构建应用程序引擎的应用程序。
为了解释数据存储特性和用于数据建模的可用 API,我首先介绍与应用程序引擎的 Python SDK 相关的所有内容。
任务管理器:示例应用程序
参考一个简单的任务管理应用程序,用户可以在其中定义任务、跟踪其状态并在完成后检查其完成情况。要定义任务,用户需要给它一个名称和一个描述。可以添加标记来对它进行分类和开始,并且可以指定预期的到期日期。一旦完成,可以记录结束日期。
任务属于用户,在应用程序的第一个版本中,除了所有者之外,它们不与任何人共享。
要为任务建模,最好列出属性,指定每个属性的数据类型,说明它是必需的还是可选的,以及它是单值还是多值。
下表列出了任务的属性及其特征。
| 属性名 | 数据类型 | 要求 | 单个或 多个值 |
|---|---|---|---|
| Name | String | Yes | Single |
| Description | String | No | Single |
| start_date | Date | Yes | Single |
| due_date | Date | No | Single |
| end_date | Date | No | Single |
| Tags | array(list collection) | No | Multiple |
GAE Python SDK 提供了一个数据建模 API,使开发人员能够创建用于表示任务的 Python 类。这种任务模型类的最简单形式如下:
import datetime
from google.appengine.ext import db Available
class Task(db.Model):
name=db.stringProperty()
description=db.stringProperty()
start_date=db.DateProperty()
due_date=db.DateProperty()
end_date=db.DateProperty()
tags = db.stringListproperty()
如果你曾经在一个像 Django 这样的 web 框架中编程,或者使用过像 SQLAlchemy 这样的 ORM,你肯定见过类似的数据建模 API。
GAE Python 数据建模 API 遵循 Python Web 开发人员所熟悉的语法和语义。
ORM,或者对象关系映射,在面向对象编程和关系数据库世界之间架起了一座桥梁。
在上表中,name 和 start_date 被指定为必填字段,但是它们还没有合并到模型中。
在这里,将修改 Task 类以指定约束: import datetime
import datetime
from google.appengine.ext import db
class Task(db.Model):
name=db.StringProperty(required=True)
description = db.StringProperty()
start_date =db.DateProperty(required=True)
due_date=db.DateProperty()
end_date=db.DateProperty()
tags=db.stringListproperty()
GAE 使用 Google 的 Bigtable 作为数据存储。
Bigtable 是一种面向列族的排序、有序、分布式稀疏映射,它对列族中的列的数量或类型或存储在这些列中的值的数据类型几乎没有限制。而且,Bigtable 允许有效地保存稀疏数据集,从而允许表中的两行具有完全不同的列集。它还允许对同一列使用不同的值类型。
换句话说,在单个数据存储中,同一类型的两个实体(例如 Task)可以有不同的属性集,或者同一类型的两个实体可以有一个属性(用相同的名称标识) ,可以包含不同类型的数据。
数据建模 API 在更加通用的 Bigtable 之上提供了一个级别的结构。数据建模 API 对属性数据类型、其值集以及它们之间的关系提供了应用程序级别的限制。在描述“ Task”实体的简单示例中,名为 Task 的 Python 类定义了数据模型。
可以将 GAE 数据存储区看作是一个对象存储区,其中每个实体都是一个对象。这意味着数据存储实体或成员可以是 Python 类的实例,如 Task。类名 Task 转换为实体类型。一个密钥在数据存储中的所有实体中唯一地标识一个实体。密钥是一个组合标识符,包括:
-
继承路径
-
实体类
-
实体 ID 或实体密钥名称
假设,这意味着如果 BaseTask 类型的实体是 Task 实体的父实体,那么 Task 实体的继承路径包括对 BaseTask 类型的父实体的引用。任务本身成为实体类型。这种类型的特定实体 Task 具有一个 ID,可以将其视为主键。ID 可以是以下任意一种:
-
应用程序提供的值名为
key_name,它是一个字符串 -
系统生成(即,GAE 数据存储)唯一的数字 ID 因此,您可以创建和保存一个实体如下:
task=Task(name="Design task manager app",
description ="Design the task management application.Create the initial blueprint and the app architecture.",
start_date=datetime.datetime.now().date())
task.put()
这将创建一个任务实例。该实例是通过将 name、 description 和 start_date 的值传递给构造函数来创建的。或者,您可以创建一个实例,然后为该实例的属性赋值。您需要在实例化时将所有必需属性的值传递给构造函数。非强制属性的值可以通过构造函数或属性分配的方法来分配。
在上面的示例中,没有为 key_name 属性传入值,因此数据存储区为实体创建了唯一的数字 ID。您可以这样查询密钥:
my_entity_key=task.key()
输出是一个附加到类别的数值,在本例中为 Task。或者,您可以为一个实体创建一个密钥,并在创建时传入该密钥。假设您想使用 task1作为 Task 类型的实体的键,您可以像下面这样实例化一个任务实体:
another_task = Task(key_name="task1", name="Yet another task", description="Yet another task is, as the name says, yet another task.",
start_date=datetime.datetime(2011, 2, 1, 12, 0, 0).date())
现在,使用 another_task 查询密钥。Key ()返回 Task: task1,其中包括在创建时分配的 key_name。
在创建 another_task 的示例中,我将 start_date 值指定为2011/02/01。这是我随意选择的日期,只是为了证明它可以是任何有效的日期值。
标准的 Python datetime.datetime 模块用于以正确的格式创建日期值。在默认情况下,datetime.datetime 模块使用 UTC 时区创建和读取日期。您可以选择使用模块的功能设置时区和其他属性。
您可以按照您所习惯的 Python 方式操作日期。
本文正在参加「金石计划 . 瓜分6万现金大奖」