IBM-数据工程-X-笔记-全-
IBM 数据工程 X 笔记(全)
001:NoSQL概述



在本节课中,我们将要学习NoSQL数据库的基本概念。我们将定义“NoSQL”这一术语及其所指的技术,并描述NoSQL在数据库发展历程中的历史背景。
🏷️ 名称的由来
首先,我们来谈谈“NoSQL”这个名称。这个名称是在一次讨论所有新兴开源分布式数据库的活动中被提出的,并沿用至今。




与字面意思相反,NoSQL实际上代表“Not Only SQL”(不仅仅是SQL),而不是“No SQL”(没有SQL)。这个名称实际上描述的是它不是什么。它指的是一个在风格和技术上差异很大的数据库家族,但它们都共享一个共同特征:本质上是非关系型的。
这意味着它们不是标准的行与列结构的关系型数据库管理系统(RDBMS)。因此,描述这类数据库的一个更贴切的名称是“非关系型数据库”。
✨ NoSQL数据库的优势

NoSQL数据库提供了存储和查询数据的新方法,解决了现代应用程序面临的诸多问题。最重要的是,大多数NoSQL数据库旨在处理与大数据运动相关的、不同类型的扩展性问题。




这里所说的“扩展性”,既指数据的规模,也指并发操作数据的用户数量。NoSQL数据库通常在其用例上也更加专业化,并且相比关系型数据库,能为应用程序功能的开发提供更简单的方案。在本课程后续的视频中,我们将更详细地探讨各种NoSQL数据库的优势。

📜 NoSQL运动的历史


接下来,让我们快速回顾一下NoSQL运动的历史。
回溯到1970年至2000年期间,尽管存在一些非关系型数据库,例如IBM的IMS(一种用于阿波罗太空任务的分层数据库),但市场主要由关系型数据库主导。
因此,当应用程序架构师和开发人员需要为其应用程序选择数据存储时,他们基本上是从各种常见的关系型数据库中挑选,其中Oracle、IBM DB2、Microsoft SQL Server和MySQL是较为流行的选择。


当互联网应用和公司在90年代末至21世纪初的互联网泡沫时期开始爆炸式增长时,应用程序的主要服务对象从公司内部的数千名员工,转变为需要服务公共互联网上的数百万用户。对这些应用而言,可用性和性能至关重要。






这些新的扩展性问题推动了创建新的可扩展技术来支持它们。当时,IBM、谷歌和Facebook等几家大型科技公司开发了大量优秀技术,并随之向社区发布了白皮书或开源了这些技术。

具体的例子包括谷歌的MapReduce白皮书(描述了如何在分布式系统上处理大型数据集)和亚马逊的Dynamo白皮书(详细阐述了一种在仲裁风格架构的集群内均匀分布数据和工作负载的方法)。
在21世纪后期,几种新的数据库开始涌现,其中大量来自开源社区。像Apache CouchDB、Cassandra、HBase,以及MongoDB、Redis、Riak和Neo4j等数据库在应用程序中得到了更广泛的使用,特别是在那些需要比关系型数据库所能处理的更大规模的应用中。


在过去十年左右的时间里,一些NoSQL数据库采用了完全托管的服务模式,也称为“数据库即服务”(DBaaS)。这种模式将管理和维护工作从最终用户身上转移,让开发人员能够专注于使用这些现代数据库构建应用程序。一些例子包括IBM Cloudant和Amazon DynamoDB。
🎯 总结
本节课中我们一起学习了以下内容:
- “NoSQL”这个名称代表“Not Only SQL”(不仅仅是SQL)。
- “NoSQL”这个术语指的是一类在架构上为非关系型的数据库。
- 尽管各种NoSQL数据库的实现技术在细节上各不相同,但它们都共享一些共同特征。
- 从历史上看,关系型数据库更为普遍,但自2000年以来,由于大数据的扩展性需求,NoSQL数据库在数据库市场中变得越来越流行。
002:NoSQL数据库的特点 🗄️


在本节课中,我们将学习NoSQL数据库的核心概念、主要类型以及它们的关键特性。我们将探讨NoSQL数据库与关系型数据库的主要区别,并了解采用NoSQL数据库带来的主要优势。


NoSQL数据库的概述

NoSQL数据库最普遍的共同特征是它们在架构上是非关系型的。这意味着它们不依赖于传统的表结构,也不使用SQL作为主要查询语言。


NoSQL数据库的主要类型
业界普遍认为,NoSQL数据库主要分为四种类型。以下是这四种类型的简要介绍:

- 键值数据库:以键值对的形式存储数据。
- 文档数据库:将数据存储为类似JSON的文档格式。
- 列式数据库:按列族存储数据,优化读取和分析。
- 图数据库:专注于存储实体(节点)和它们之间的关系(边)。
这些类型之间存在一些重叠,定义并非总是绝对清晰。在本课程后续部分,我们将详细探讨不同类型及其适用场景。
NoSQL数据库的共同点


尽管技术实现各异,但NoSQL数据库有一些重要的共同特征。
上一节我们介绍了NoSQL数据库的主要类型,本节中我们来看看将它们联系在一起的共同点。一个关键共性是,大多数NoSQL数据库都植根于开源社区,并以开源方式被使用和发展。这对它们在行业内的快速增长起到了根本性的推动作用。许多公司会同时提供商业版本(包含服务和技术支持)并赞助其对应的开源项目,例如IBM Cloudant之于CouchDB,DataStax之于Apache Cassandra,MongoDB公司也维护着开源的MongoDB版本。



从技术角度看,它们虽然差异很大,但仍有一些共同点浮现。以下是NoSQL数据库的一些常见技术特征:



- 水平扩展性:大多数NoSQL数据库为水平扩展而设计,能够比关系型数据库更轻松地在服务器集群间分布数据。这通常需要在整个数据库中使用全局唯一键来简化分区或分片。
- 公式/概念:
数据分布 → 分区(Partitioning) / 分片(Sharding)
- 公式/概念:
- 专用性:相比曾是数据存储“瑞士军刀”的关系型数据库管理系统,NoSQL数据库通常更专注于特定用例。
- 易用性:开发者因NoSQL数据库易于进行数据建模和使用而被吸引。
- 灵活的模式:与关系型数据库的固定模式相比,许多NoSQL数据库通过其灵活的模式支持更敏捷的开发。
采用NoSQL数据库的优势
我们已经了解了NoSQL的含义、其在数据库技术世界中的历史,以及与关系型数据库相比的一些基本特点和差异。那么,为什么要使用NoSQL数据库?为什么这些数据库的普及速度如此之快?



原因有很多,以下列出了一些更常见的优势。请注意,并非所有NoSQL数据库都具备所有这些优点。






可扩展性与性能

首先,采用NoSQL数据库最常见的原因是为了可扩展性,特别是跨服务器集群、机架甚至数据中心进行水平扩展的能力。根据应用需求弹性地向上和向下扩展是关键。NoSQL数据库非常适合满足大数据应用所呈现的海量数据规模和巨大并发用户数。


第二点是性能,它与可扩展性密不可分。现代应用必须能够提供快速的响应时间,即使面对大数据量和高并发。NoSQL数据库能够利用大型服务器集群的资源,使其在这些情况下成为实现高性能的理想选择。
高可用性与成本效益




高可用性是数据库的明确要求。在集群上运行数据库并存储数据的多个副本,比单服务器解决方案更具弹性。



历史上,大型数据库运行在昂贵的机器或大型机上。现代企业采用云架构来支持其应用,而NoSQL数据库的分布式数据特性意味着它们可以部署和运行在云架构的服务器集群上,从而大幅降低成本。成本对任何技术项目都很重要,经常可以听到NoSQL采用者相比其现有数据库显著降低成本,同时仍能获得相同或更好的性能和功能。

灵活的开发模式



灵活的模式和直观的数据结构是开发者在希望高效构建应用时喜爱的关键特性。大多数NoSQL数据库允许灵活的模式,这意味着可以快速为应用构建新功能,而无需任何数据库锁定或停机。


NoSQL数据库还具有多样化的数据结构,这些结构通常比关系型数据存储的行和列更能贴切地满足开发需求。例如,包括用于快速查找的键值存储、用于存储非规范化直观信息的文档存储,以及用于关联数据集的图数据库。



特殊功能
某些NoSQL提供商还提供吸引最终用户的各种专业化功能。例如包括特定的索引和查询功能(如地理空间搜索)、数据复制的健壮性以及现代的HTTP API。



拥有所有这些优势,你可能会问为什么还有人会使用NoSQL以外的数据库。可以说,在当今大多数情况下确实如此,但肯定仍有一些需求最好由RDBMS来满足。我们将在课程后面讨论这一点。


总结



本节课中我们一起学习了以下核心要点:
- NoSQL数据库是非关系型的。
- NoSQL数据库主要分为四种类别。
- NoSQL数据库植根于开源社区。
- 不同的NoSQL数据库在技术实现上各有不同。
- 采用NoSQL数据库能带来多方面的显著好处。
003:键值数据库详解


在本节课中,我们将学习NoSQL数据库的四大主要类别之一:键值数据库。我们将探讨其架构、核心特点、适用场景以及一些流行的实现方案。

🏗️ 键值数据库架构
上一节我们介绍了NoSQL数据库的四大类别。本节中,我们来看看其中架构最简单的键值数据库。
在键值数据库中,所有数据都以一个键和一个对应的值(通常是一个不透明的二进制大对象,即Blob)的形式存储。从架构上讲,它们是NoSQL数据库中最简单的一类,因为其核心数据结构可以抽象为一个哈希映射。



其基本存储模型可以用以下伪代码表示:
# 一个简化的键值存储概念模型
key_value_store = {
"user_session_12345": "{'username': 'alice', 'last_login': '2023-10-27'}",
"shopping_cart_67890": "{'items': [{'id':1, 'qty':2}], 'total': 50.00}",
# ... 更多键值对
}
这种结构使其在基础的创建、读取、更新、删除操作上非常高效。同时,键值数据库通常具有良好的可扩展性,可以轻松地在多个节点上进行分片。每个分片包含一定范围的键及其关联的值。
⚙️ 核心特点与局限性

了解了基本架构后,我们来看看键值数据库的主要特点和需要注意的局限性。


以下是键值数据库的核心特点:
- 简单高效:专为基于键的快速CRUD操作优化。
- 易于扩展:通过键的范围进行分片,水平扩展能力强。
- 原子性:针对单个键的操作是原子的。
然而,这些数据库通常不适合处理复杂查询或连接多个数据片段。由于值(Value Blob)对数据库系统是不透明的,因此在数据的索引和查询方面,通常比其他类型的数据库灵活性更低。
🎯 典型应用场景
基于上述特点,键值数据库有其明确的适用场景。
当您需要为基础的CRUD操作提供快速性能,且您的数据之间关联性不强时,键值数据库是理想选择。以下是几个典型用例:
- 存储和检索Web应用的会话信息:每个用户会话会获得一个唯一键,所有会话数据作为一个整体存储在值中,所有操作都基于这个唯一键进行。
- 存储应用程序内的用户配置和偏好设置。
- 存储在线商店或市场的购物车数据。



在这些案例中,复杂查询或处理不同键之间关系的需求很少。
⚠️ 不适用场景
当然,键值数据库并非万能。了解其不擅长的场景同样重要。
键值数据库不适合需要处理大量数据间关联的场景。例如:
- 当您的数据具有复杂的多对多关系时,例如社交网络或推荐引擎场景,键值数据库可能表现不佳。
- 如果您的用例要求涉及多个键的多操作事务具有高度一致性,您可能需要考虑支持ACID事务的数据库。
- 如果您预期需要基于值(而非键)进行查询,那么明智的做法是考虑文档型NoSQL数据库。


🌟 流行实现方案
最后,我们来了解一些市场上流行的键值数据库实现。

以下是一些知名的键值NoSQL数据库:
- Amazon DynamoDB
- Oracle NoSQL Database
- Redis
- Aerospike
- Riak KV
- Memcached
- Project Voldemort



📝 课程总结
本节课中,我们一起学习了NoSQL数据库的四大类别之一:键值数据库。
我们了解到,键值数据库在架构上最为简单,数据以键-值对的形式存储,核心模型是哈希映射。它的主要优势在于为简单的CRUD操作提供极快的性能,并且易于水平扩展。其典型应用包括存储会话信息、用户配置和购物车数据等场景。但同时,它不适合处理复杂关系查询或多键事务。
下一节,我们将继续探索NoSQL数据库的另一重要类别:文档数据库。
004:文档型数据库


在本节课中,我们将要学习NoSQL数据库的一个重要类别:文档型数据库。我们将了解其基本架构、核心特性、适用场景以及一些流行的实现方案。

概述:什么是文档型数据库?
文档型数据库在键值模型的基础上进行了扩展,其核心特点是让“值”变得可见且可查询。在文档型数据库中,每一条数据都被视为一个文档,通常以JSON或XML格式存储。


上一节我们介绍了键值型数据库,本节中我们来看看文档型数据库如何通过结构化文档提供更强大的数据操作能力。
核心特性与架构


文档型数据库具备以下几个关键特性:

- 灵活的模式:每个文档都可以拥有不同的结构,无需包含相同的信息。这为存储半结构化或非结构化数据提供了极大的便利。
- 可查询的内容:与简单的键值存储不同,文档型数据库允许对文档内容进行索引和查询。这包括基于键和值范围的查找,甚至可以通过类似
MapReduce的范式进行复杂的分析查询。 - 水平可扩展性:它们支持通过分片在多个节点上进行水平扩展。分片通常基于文档中的某个唯一键进行。
- 事务保证:文档型存储通常只保证单文档操作的原子性事务。这意味着涉及多个文档的复杂事务可能无法得到完全支持。
主要应用场景
以下是文档型NoSQL数据库的一些典型应用场景:
- 应用程序或流程的事件日志记录:每个事件实例都可以构成一个新的文档,其中包含与该事件相关的所有信息。
- 在线博客平台:每个用户、每篇博文、每条评论或点赞都可以存储为一个独立的文档。所有文档都包含与其数据类型相关的信息,例如用户名、帖子内容或创建时间戳。
- Web和移动应用的操作数据集:文档型数据库非常适合为Web和移动应用程序存储操作数据或元数据。它们的设计初衷就考虑了互联网、
JSON、RESTful API和非结构化数据。


不适用场景
了解何时不应使用文档型数据库同样重要:
- 需要ACID事务的场景:如果您的用例要求跨多个文档的强一致性ACID事务,文档型数据库可能无法满足需求。在这种情况下,关系型数据库可能是更好的选择。
- 数据天然符合规范化表格模型:如果您发现自己正在强行将数据塞入“面向聚合”的设计中,而数据本身更自然地符合规范化的表格模型,那么您应该考虑使用关系型数据库。


流行实现方案
文档型数据库是当前使用最广泛的NoSQL数据库类别之一。以下是一些流行的文档型NoSQL数据库实现:
- IBM Cloudant
- MongoDB
- Apache CouchDB
- Terrastore
- OrientDB
- Couchbase
- RavenDB

总结



本节课中,我们一起学习了文档型NoSQL数据库。我们了解到,文档型数据库使用文档(通常为JSON或XML格式)来存储数据,每个文档都提供灵活的模式。它们的主要应用场景包括应用事件日志记录、在线博客以及为Web和移动应用提供操作数据存储。同时,我们也明确了其在需要跨文档ACID事务或数据高度规范化场景下的局限性。
005:列式NoSQL数据库类别


在本节课中,我们将学习列式NoSQL数据库。我们将了解其架构、核心概念以及主要应用场景。

🏗️ 列式数据库的起源与架构



列式数据库源自谷歌创建的名为Big Table的架构。因此,这些数据库通常也被称为Big Table克隆、列式数据库或宽列数据库。
从名称可以看出,这类数据库在存储和访问数据时,关注的是列和列组。
🔑 核心概念:列族
列族由若干行组成,每一行都有一个唯一的键或标识符,并且属于一个或多个列。这些列被分组在一起形成列族,因为它们经常被一起访问。


需要特别指出的是,列族中的行并不要求共享相同的列。它们可以共享所有列、一个子集的列,或者完全不共享任何列。此外,列可以被添加到任意数量的行中,而不必添加到所有行。

💡 列式数据库的典型应用场景
以下是列式NoSQL数据库的一些典型应用场景。



优势场景
- 处理大量稀疏数据:与面向行的数据库相比,列式数据库在处理大量稀疏数据时表现更佳。它们能更好地压缩数据,节省存储空间。
- 水平可扩展性:与键值数据库和文档数据库一样,列式数据库延续了水平扩展的趋势,能够部署在跨节点的集群上。
具体用例
- 事件日志和博客:类似于文档数据库,列式NoSQL数据库也可用于事件日志和博客,但数据存储方式不同。例如,在企业日志记录中,每个应用程序可以写入自己的一组列,并且每行的键可以按特定方式格式化,以便于根据应用程序和时间戳进行查找。
- 计数器:计数器是列式数据库的一个独特用例。有些应用程序需要一种简单的方法来计数或在事件发生时递增。像Cassandra这样的列式数据库具有特殊的列类型,允许简单的计数器功能。
- 具有时效性的数据:列可以设置生存时间参数,这使得它们适用于具有过期日期或时间的数据,例如试用期或广告定时。
不适用场景
另一方面,在以下情况下应避免使用列式数据库:
- 需要传统ACID事务:如果应用需要关系数据库提供的传统ACID事务保证,则不适合。列式数据库的读写原子性仅在行级别。
- 查询模式在早期开发中可能频繁变化:如果在开发早期查询模式可能发生变化,并需要对列式设计进行大量修改,这可能会代价高昂并拖慢生产时间线。
🛠️ 流行的列式NoSQL数据库实现

一些更流行的列式NoSQL数据库实现包括:
- Cassandra
- HBase
- HyTable
- Accumulo




📝 课程总结
本节课中,我们一起学习了列式NoSQL数据库。


我们了解到,列式数据库源自谷歌的Big Table存储系统架构。这类数据库将数据存储在列或列组中。
列族是由若干具有唯一键的行组成的,这些行属于一个或多个列。

列式NoSQL数据库的主要应用场景包括:事件日志和博客、计数器以及具有时效性值的数据。
006:图形数据库 🕸️


在本节课中,我们将要学习NoSQL数据库的最后一个类别——图形数据库。我们将了解其架构、核心特性、适用场景以及一些流行的实现。
概述
图形数据库是NoSQL数据库的一个重要分支,它采用独特的方式存储和查询数据。与之前讨论的键值、文档和列族数据库不同,图形数据库专注于实体之间的关系。本节我们将深入探讨图形数据库的架构和主要用例。
图形数据库架构

上一节我们介绍了其他NoSQL数据库类别,本节中我们来看看图形数据库的独特架构。



图形数据库将信息存储在实体(或称节点)和关系(或称边)中。其核心思想可以用以下概念模型表示:

(节点A) --[关系]--> (节点B)
当您的数据集类似于图形数据结构时,图形数据库的表现会非常出色。遍历所有关系既快速又高效。然而,这类数据库在水平扩展方面往往表现不佳。
核心特性
以下是图形数据库的一些关键特性:
- 不推荐分片:由于遍历一个节点分散在多个服务器上的图形会变得困难并损害性能,因此通常不推荐对图形数据库进行分片。
- ACID事务兼容:与之前讨论的其他NoSQL数据库非常不同,图形数据库通常遵循ACID(原子性、一致性、隔离性、持久性)事务原则。这可以防止节点之间存在不存在的悬空关系。
典型用例


现在让我们看看图形数据库的一些典型应用场景。当您的数据高度互联并以某种方式相关时,图形数据库会非常强大。

以下是图形数据库的主要适用领域:
- 社交网络:可以快速定位朋友、朋友的朋友、点赞关系等。
- 路由、空间和地图应用:可以轻松地为其数据建模,以查找附近位置或构建最短路径导航。
- 推荐引擎:可以利用产品之间的紧密关系和链接,轻松为客户提供其他选项。

不适用场景


就图形数据库的不适用场景而言,当您需要其他NoSQL数据库类别提供的某些优势时,图形数据库并不是一个好的选择。
当应用程序需要进行水平扩展时,您很快就会遇到这类数据存储相关的限制。
另一个普遍的缺点是,当尝试用给定参数更新所有或部分节点时,这类操作可能被证明是困难且非平凡的。



流行实现
以下是一些较流行的图形NoSQL数据库实现示例:
- Neo4j
- OrientDB
- ArangoDB
- Amazon Neptune(亚马逊网络服务的一部分)
- Apache Giraph
- JanusGraph
总结


本节课中,我们一起学习了图形数据库。我们了解到,图形数据库将信息存储在实体(节点)和关系(边)中。当您的数据类似于图形数据结构时,图形数据库表现优异。图形数据库不适合分片,但遵循ACID事务。图形NoSQL数据库类别的主要用例适用于高度互联和相关的数据,例如社交网站、路由、空间和地图应用以及推荐引擎。
007:ACID与BASE对比 🆚


在本节课中,我们将要学习关系型数据库与NoSQL数据库在数据一致性模型上的核心区别,即ACID与BASE模型。我们将定义这两个术语,识别它们各自的适用场景,并描述它们之间的关键差异。
关系型数据库管理系统(RDBMS)与NoSQL数据库之间最显著的区别之一,在于它们的数据一致性模型。当今最广为人知且广泛使用的两种一致性模型是ACID和BASE。关系型数据库采用ACID模型,而NoSQL数据库则采用BASE模型。



尽管ACID和BASE模型常被视为对立面,但事实上,两者都各有其优缺点。接下来,让我们深入了解这两个术语的含义。





ACID模型详解 💎

ACID是一个缩写,代表原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。以下是其核心概念的详细解释:




- 原子性 (Atomicity):一个事务中的所有操作要么全部成功,要么全部失败回滚。这确保了事务的完整性。
- 公式/代码描述:
事务 = {操作1, 操作2, ...}。若任一操作失败,则整个事务状态回滚到开始之前。
- 公式/代码描述:
- 一致性 (Consistency):事务完成后,数据库的结构完整性不会被破坏,数据必须符合所有预定义的规则。
- 隔离性 (Isolation):并发执行的事务彼此隔离,一个事务在完成前,其中间状态不会影响其他事务。
- 持久性 (Durability):一旦事务提交,其所做的数据更改将是永久性的,即使发生系统故障(如断电)也不会丢失。

许多开发者通过使用关系型数据库而熟悉ACID事务,因此ACID一致性模型曾长期是数据一致性的标准。



ACID模型的适用场景

ACID一致性模型确保已执行的事务始终保持一致,这使其非常适合处理在线事务处理(OLTP)业务,例如金融机构或数据仓库类型的应用程序。


这些组织需要能够处理大量小型、并发事务的数据库系统,就像关系型数据库那样。ACID系统提供了一个可靠的一致性模型,您可以信赖其数据的结构完整性。
在众多ACID数据库的用例中,有一个尤为突出:金融机构几乎完全使用ACID数据库进行资金转账。因为这些操作依赖于ACID事务的原子性。一个被中断但未立即从数据库中清除的事务可能导致严重问题,例如资金从一个账户扣除后,由于错误而从未或未能存入另一个账户。


BASE模型详解 🏗️


上一节我们介绍了强调强一致性的ACID模型,本节中我们来看看在可用性上做出权衡的BASE模型。BASE同样是缩写,代表基本可用(Basically Available)、软状态(Soft State)和最终一致性(Eventually Consistent)。

以下是其核心概念的详细解释:




- 基本可用 (Basically Available):BASE模型的NoSQL数据库不强制要求即时一致性,而是通过跨数据库集群节点分布和复制数据来确保数据的可用性。
- 软状态 (Soft State):由于缺乏即时一致性,数据值可能会随时间而变化。在BASE模型中,数据存储不必始终保持强一致,不同的数据副本也不必时刻保持相互一致。
- 最终一致性 (Eventually Consistent):BASE模型不强制即时一致性,但这并不意味着它永远无法达成一致性。系统保证,在没有新的更新操作后,经过一段时间,所有副本最终会达到一致状态。然而,在达到最终一致之前,读取的数据可能是不一致的。

在NoSQL数据库领域,ACID事务不那么流行,因为一些数据库放宽了对即时一致性、数据新鲜度和准确性的要求,以换取其他优势,如高可用性、可扩展性和弹性。



BASE模型的适用场景

BASE一致性模型被处理情感分析和社交网络研究的市场营销与客户服务公司、包含海量数据并需要始终保持可用的社交媒体应用,以及像Netflix、Spotify和Uber这样需要全球可用的在线服务所采用。


BASE数据存储将可用性置于一致性之上,但它不保证在写入时复制数据的一致性。NoSQL数据库使用BASE一致性模型。本质上,BASE一致性模型提供了高可用性。
BASE数据存储可以并且确实被用于许多特定用例。BASE数据库的知名度之所以提升,是因为Netflix、Apple、Spotify和Uber等全球知名在线服务在其应用(如用户配置文件数据存储)中使用了它们。
这些服务的一个共同特点是,无论您身处世界何处,它们都需要随时可访问。因此,如果其数据库集群的某一部分变得不可用,系统也需要能够无缝地响应用户请求。


总结 📝
本节课中我们一起学习了ACID和BASE分别是关系型数据库和NoSQL数据库中使用的一致性模型。


- ACID 代表原子性、一致性、隔离性、持久性。
- BASE 代表基本可用、软状态、最终一致性。

ACID模型侧重于数据一致性,而BASE模型侧重于数据可用性。两种一致性模型各有其适用性,应根据具体案例分析来选择使用哪一种。
008:分布式数据库 🗄️





在本节课中,我们将要学习分布式数据库的核心概念。我们将了解什么是分布式数据库,以及它如何通过数据分片和复制来工作。同时,我们也会探讨分布式系统的优势与面临的挑战。
分布式数据库概述
分布式数据库是由多个相互连接的数据库组成的集合。这些数据库物理上分布在不同的地理位置,并通过计算机网络进行通信。



数据分片与复制
为了在分布式系统的所有服务器上存储大量数据,你需要将数据分解成更小的片段。这个过程被称为数据分片,在某些NoSQL数据库中也称为数据分区或分片。
无论名称如何,所有分布式系统都需要提供一种存储大块数据的方法。这个过程通常通过键值对记录中的键以两种方式完成:
- 按字典顺序对所有键进行分组。例如,所有以A开头或在A到C之间的键可以存储在特定的服务器上。
- 将所有具有相同键的记录分组,并将它们放在同一台服务器上。例如,所有以商店ID为键的交易记录。这样,当查询“给我某个商店的所有销售额”时,所有记录都将位于单个服务器上。



数据现在已经分布到集群的所有节点。但如何确保一个节点故障时,不会丢失该节点上的所有数据?这是通过复制实现的,即你的数据的所有分片或分区都冗余地存储在两个或更多站点。

因此,在复制中,系统维护数据的副本。复制提高了数据在不同站点的可用性。如果一个节点故障,可以从另一个节点检索该数据片段。
分布式系统的优势与挑战


分布式系统具有众多优势。它们提供了更高的可靠性和可用性。数据在多个站点复制。如果本地服务器不可用,可以从另一个可用服务器检索数据。


分布式数据库的另一个优势是提高了性能,尤其是在处理海量数据时。查询处理时间减少,这也有助于提升性能。你可以轻松地扩展系统容量,只需向集群添加新服务器即可。分布式系统还提供持续运行,减少了对中心站点的依赖。
分布式数据库解决了当今应用服务的许多技术问题,如可用性、快速扩展和全球覆盖。但其架构也引入了一些挑战。

其中之一是并发控制。因为同一份数据存储在多个位置,如果你修改、更新或删除数据,如何确保数据同步的安全性?为了解决这个问题,一些分布式数据库将针对某个数据分片的操作定向到仅一个节点,然后由集群与其他节点同步。
另一些数据库则写入所有持有该特定数据分片的节点,并根据一致性要求从尽可能多的节点读取。在这两种情况下,开发者都可以控制操作的一致性,或者规定需要多少个节点响应才能使某个操作被视为成功。


由于并发控制问题,分布式数据库在设计上并不真正支持事务,或者只提供非常有限的事务支持。请记住上一视频中的BASE模型。分布式数据库遵循BASE模型,即基本可用、软状态、最终一致性。系统始终保持可用,数据有时可能不一致,但最终可以达到一致性。
总结



本节课中,我们一起学习了分布式数据库。我们了解到,分布式数据库通过数据分片和复制在物理上分布于各个数据站点。分片使组织能够通过将数据分解成更小的片段,将大量数据存储在分布式系统的所有服务器上。复制意味着你的数据的所有分区都冗余地存储在两个或更多站点;通过复制,如果一个节点故障,可以从另一个节点检索该数据片段。分布式数据库提供了若干优势,但也有其缺点,并且分布式数据库遵循BASE一致性模型。
009:CAP定理 🧩




在本节课中,我们将学习CAP定理。通过本节内容,你将能够定义CAP定理,描述其核心特性,并了解其历史背景与现实意义。


CAP定理的起源与背景
在21世纪初,大数据Hadoop架构作为首个能够存储和处理海量数据的开源分布式架构被创建。与此同时,越来越多的服务要求数据库也实现分布式部署。这些业务不仅需要其服务在全球大部分地区保持活跃和可访问,还要求服务始终保持可用性。
对于高度依赖数据一致性的关系型数据库而言,在分布式系统中同时保证可用性这一新概念似乎是不可能的。CAP定理证实了这一点。
CAP定理也被称为布鲁尔定理,因为它最初由埃里克·A·布鲁尔教授在2000年的一次分布式计算演讲中提出。两年后,麻省理工学院的塞斯·吉尔伯特和南希·林奇教授对其进行了修订,此后还有许多其他贡献者。
该定理指出,在分布式系统中成功设计、实现和部署应用程序需要三个基本的系统需求。它们是:一致性、可用性和分区容错性。一个分布式系统最多只能同时保证这三个理想特性中的两个。
理解CAP的三个特性
上一节我们介绍了CAP定理的由来,本节中我们来看看这三个核心特性的具体含义。
一致性
一致性指的是系统是否完全运行。集群中的所有节点是否都能看到它们应该看到的所有数据?
公式描述:对于任何数据读取操作,系统返回的值必须是最近一次成功写入操作的结果。




可用性


可用性正如其名,指的是每个请求是否都能得到响应,无论该响应是成功还是失败。
公式描述:对于每一个向非故障节点发起的请求,系统必须在有限时间内给出响应。


分区容错性


分区容错性代表一个系统即使在发生数据丢失或网络故障的情况下,也能继续运行的能力。
公式描述:系统在遇到网络分区(即节点间通信中断)时,仍能继续提供服务。




深入探讨分区容错性
一致性和可用性的概念相对直观,那么分区容错性具体指什么呢?
在分布式系统中,分区是指通信中断,即节点之间连接丢失或暂时延迟。


分区容错性意味着,尽管系统中节点之间发生任意数量的通信故障,集群也必须能够继续工作。
在分布式系统中,分区是无法避免的。因此,分区容错性成为了像NoSQL这样的原生分布式系统的一个基本特性。
例如,在一个有八个分布式节点的集群中,可能会发生网络分区,导致所有节点间的通信中断。在这种情况下,我们将不再是一个八节点集群,而是变成两个可用的、更小的四节点集群。只有当网络通信重新建立时,两个集群之间的一致性才能恢复。
对于分布式系统,分区容错性已从一种可选项变为一种必需品。它通过跨节点和网络组合充分复制记录来实现,NoSQL等系统就是如此。
CAP定理在NoSQL中的应用
由于分区容错性是强制性的,一个系统只能在一致性+分区容错性 或 可用性+分区容错性 之间做出选择。
现有的NoSQL系统,如MongoDB或Cassandra,可以用CAP定理来分类。
以下是两种典型选择:
- MongoDB:选择一致性作为解决方案的主要设计驱动力。
- Apache Cassandra:选择可用性。
这并不意味着MongoDB无法保持可用性,或者Cassandra无法实现完全一致性。它意味着这些解决方案首先确保自己是一致的(对于MongoDB)或可用的(对于Cassandra),而另一个特性则是可调整的。

总结
本节课中我们一起学习了CAP定理。你了解到CAP定理可用于对NoSQL数据库进行分类。NoSQL数据库需要在可用性和一致性之间做出权衡选择,而分区容错性是NoSQL数据库的一个基本特性。



010:从RDBMS迁移到NoSQL数据库的挑战



在本节课中,我们将要学习从关系型数据库管理系统迁移到NoSQL数据库时可能遇到的挑战。我们将探讨RDBMS和NoSQL各自最适合的应用场景,并详细分析两者之间的主要区别。

🎯 RDBMS与NoSQL:并非替代关系

有时存在一种误解,认为NoSQL是RDBMS的替代品,或者必须在关系型数据库和非关系型数据库之间做出选择。实际上,RDBMS和NoSQL数据库并非竞争关系,因为它们服务于截然不同的需求和用例。
虽然从RDBMS系统迁移到NoSQL系统是可行的,但这一决策应基于最终解决方案所需的特性。这种变更可能由对更高性能或更灵活性的需求驱动。无论出于何种原因,都需要根据NoSQL能为你带来的价值来分析这些需求。




让我们看看一些通常选择关系型或非关系型数据库的通用场景。

🔍 何时选择关系型数据库
以下是适合使用关系型数据库的情况:

- 数据需要完全一致性:例如银行交易系统,要求数据时刻保持精确一致。
- 数据结构化程度高:数据可以清晰地组织成行和列,并具有预定义的模式。
- 需要多文档/记录事务:操作涉及多个数据项,要求要么全部成功,要么全部失败。
- 涉及复杂的表连接:查询需要频繁地在多个表之间建立关联以获取信息。

在这些情况下,关系型数据库是更合理的选择。


🚀 何时选择NoSQL数据库

上一节我们介绍了关系型数据库的适用场景,本节中我们来看看NoSQL数据库的优势领域。

以下是适合使用NoSQL数据库的情况:



- 数据量巨大且需要高性能系统:例如处理海量用户日志或传感器数据。
- 数据结构非结构化或半结构化:数据格式灵活多变,可以从灵活的模式中受益。
- 系统需要高可用性和可扩展性:服务需要能够应对流量激增,并保证持续在线。

在这些情况下,NoSQL数据库是更合理的选择。

🤝 混合架构的可能性

在某些情况下,可能需要同时使用关系型和非关系型数据库。
如果你面临海量数据、需要高性能和快速扩展,但同时你的数据又需要事务支持和复杂连接,那么你可能会考虑一种组合解决方案。例如,核心交易数据存放在RDBMS中以保证一致性,而用户生成的内容或日志数据则存放在NoSQL数据库中以实现扩展。



💡 迁移时需要关注的核心概念差异
从关系型世界转向NoSQL世界时,有几个关键点需要注意。
首先,数据建模的驱动因素不同。
在关系型数据库中,解决方案设计始于数据本身,即实体及其关系。而在NoSQL中,数据模型由你的查询需求驱动,而非数据本身。NoSQL模型应基于应用程序如何与数据交互来设计,而不是如何将模型存储为一个或多个表中的行。
其次,数据规范化与反规范化。
在RDBMS中,数据通常是规范化的,以减少冗余。而在NoSQL中,数据是反规范化的。从查询出发意味着你将相应地构建磁盘上的数据结构。因此,你可能需要以不同的模型存储相同的数据,只是为了回答特定的查询问题,这会导致数据反规范化。
第三,对一致性与可用性的权衡理解。



回顾我们之前关于ACID与BASE的视频,从关系型数据库迁移到NoSQL数据库时,需要理解有时服务对可用性的要求高于一致性。当同时需要高可用性和高性能时,在分布式系统中,一致性无法得到绝对保证。
记住CAP定理,当今许多在线服务更看重可用性而非强一致性。正因如此,它们寻找能够提供高可用性的系统,同时考虑到它们处理的数据量及其地理分布。
最后,关于事务与连接的支持。
需要了解的一点是,NoSQL数据库并非设计用于支持事务、连接或复杂处理(除少数有限情况外)。从RDBMS迁移到NoSQL时,你需要考虑这一点。

📝 总结
本节课中我们一起学习了以下核心内容:

- NoSQL系统并非RDBMS的事实替代品,RDBMS和NoSQL服务于不同的用例。
- 你的解决方案可以同时使用RDBMS和NoSQL。
- 从RDBMS到NoSQL的迁移可能由数据量驱动的性能需求、模式或系统可扩展性的灵活性需求所触发。
- 从RDBMS迁移到NoSQL需要采纳NoSQL的设计理念,特别是由查询驱动数据模型以及接受数据的反规范化。
011:MongoDB概述


在本节课中,我们将要学习MongoDB的基础知识。MongoDB是一种流行的NoSQL数据库,它采用文档模型来存储数据。通过本节课的学习,你将能够解释MongoDB是什么,列举其核心组件,并描述其适用场景。
🧩 什么是MongoDB?




MongoDB是一种文档型NoSQL数据库。与SQL数据库将数据存储在由行和列组成的表中不同,MongoDB数据库中的每条记录都是一个文档,数据以非关系型方式存储。

文档类似于关联数组,例如JavaScript对象或Python字典。以下是一个表示学生信息的文档示例:



{
"first_name": "John",
"last_name": "Doe",
"email": "john.doe@example.com",
"student_id": 12345
}

📂 MongoDB的核心组件
上一节我们介绍了MongoDB的基本概念,本节中我们来看看它的核心组件是如何组织数据的。
集合(Collection)



在MongoDB中,相似类型的文档被分组到一个集合中。例如,一个校园管理系统会将所有学生记录(文档)存储在名为 students 的集合中。同样,所有员工文档则存储在 employees 集合中。


数据库(Database)
一个MongoDB数据库用于存储与特定应用相关的所有不同类型的数据。沿用之前的例子,校园管理系统的所有数据可以存储在一个名为 CampusManagementDB 的MongoDB数据库中。



文档结构


让我们剖析一下前面的学生文档。文档由字段(或属性)及其对应的值组成。例如,first_name、last_name、email 和 student_id 都是字段。每个字段名在该文档内是唯一的。


🔢 MongoDB支持的数据类型
MongoDB支持多种数据类型,这使你能够使用正确的类型来存储信息。


以下是MongoDB支持的一些关键数据类型:

- 日期:应存储为ISO日期或Unix时间戳格式。这有助于执行诸如“查询所有出生在1月15日至2月15日之间的学生”这类操作。
- 数字:可以存储为整数或小数。
- 子文档:MongoDB允许在文档中嵌套存储子文档,以便将次要信息分组在一起。
- 数组:支持存储值的列表,列表中的元素不仅可以是文本,还可以是不同类型的数据混合在一起。

⚙️ MongoDB的优势与特性
了解了MongoDB的数据组织方式和类型后,本节我们来看看它为何如此受欢迎,以及它提供了哪些强大特性。
使用MongoDB非常便捷,因为你可以专注于要写入的数据以及如何读取它。
- 灵活的模式:传统的关系型数据库要求你先创建模式(Schema),然后创建用于存放数据的表结构。如果你决定存储一个额外的字段,就必须修改表结构。而在MongoDB中,你可以随需而变。
- 处理多样数据:MongoDB使你能够轻松引入任何结构化或非结构化数据。
- 高可用性:通过保存数据的多个副本(我们将在后续主题中详细讨论),MongoDB提供了高可用性。
- 易于设计复杂结构:你可以在MongoDB中轻松设计复杂的数据结构,而无需担心其存储方式和关联方式的复杂性。例如,如果你的校园管理应用也在美国推出,那里不存储邮政编码(postcode)而是使用邮政编码(zip code),你可以轻松调整文档结构。
- 可扩展性:MongoDB提供的可扩展性意味着,随着数据需求的增长,你可以通过引入更大、更快、更好的硬件进行垂直扩展,或者通过分区数据(分片)进行水平扩展。
- 灵活的部署:所有这些功能,无论你是在本地运行自我管理的MongoDB,还是使用混合或云托管的全托管服务(如IBM Cloud Databases for MongoDB,或AWS、Azure和Google Cloud上的MongoDB Atlas)都可以实现。
📝 课程总结
本节课中我们一起学习了MongoDB的基础知识。


我们了解到:
- MongoDB是一个文档型NoSQL数据库。
- MongoDB支持多种数据类型,为数据存储提供了灵活性。
- 文档提供了一种灵活的数据存储方式。
- 相似类型的MongoDB文档被分组到集合中。
- MongoDB允许你按照读写需求来建模数据,可以处理结构化和非结构化数据,并提供高可用性。
- 由于其存储结构化或非结构化数据的灵活性,MongoDB可以用于多种用途。
012:MongoDB的优势



在本节课中,我们将学习MongoDB这一流行的NoSQL数据库的几个关键优势。我们将了解它如何通过灵活的模式、代码优先的开发方式、强大的查询能力以及高可用性设计,来满足现代应用不断变化的数据需求。

🎯 灵活的模式


第一个关键优势是MongoDB模式的灵活性。
请看这里展示的两个地址。英国地址没有邮政编码(zip code),而美国地址没有邮政编码(postcode)。

在关系型数据库的世界里,每个字段名必须在每一行中都存在,这会导致我们不得不使用过于宽泛的字段,或者产生大量空值的字段。




但在MongoDB中以这种格式存储数据不是问题,因为它允许我们拥有这种模式上的灵活性。这也使我们能够存储非结构化数据。例如,可以合并来自不同来源、不同形状的数据进行分析或存储。
🚀 代码优先的开发方式



使用MongoDB的第二个好处是其代码优先的开发方式。
关系型数据库在开始时增加了复杂性,因为你首先需要创建表设计,然后才被允许操作数据库。


由于MongoDB基于文档工作,这意味着你可以在没有任何中间复杂性的情况下访问数据。没有复杂的表定义。一旦连接到MongoDB数据库,你就可以立即开始写入你的第一条数据。这也消除了使用任何第三方框架来进行读写操作的需要。
🔄 可演进的模式
第三个关键优势是可演进的模式。





想象一下你经营一家快递公司,需要存储送货地址。随着2020年引入的送货程序发生巨大变化,你需要以最小的干扰快速演进你的模式,以存储关于无接触配送的额外信息。

使用MongoDB,这很容易实现。你只需要开始在送货文档中存储这些额外信息即可。
📊 查询与分析能力





下一个关键优势是查询和分析能力。
MongoDB查询语言(MQL)提供了许多操作符,可以用来构建相当复杂的查询来查找数据。如果你的查询更加复杂,你可以在MongoDB内部使用聚合管道。
例如,按年级分组所有学生的成绩,并按学期找出得分最高的学生。



🛡️ 高可用性


我们将讨论的最后一个关键优势是高可用性。
MongoDB通过冗余的方式,原生支持成为一个高可用性系统。


典型的MongoDB设置是三个节点的副本集,其中一个是主成员,其他的是次要成员。复制会在集群中的其他数据承载节点上保留一份数据副本。如果一个系统发生故障,另一个会接管,你不会看到任何停机时间。
这也适用于系统维护的情况,例如你可能需要将一个节点下线以进行软件、操作系统、文件系统、安全补丁或MongoDB版本的更新。我们将在课程后面的复制和分片部分更多地讨论这个主题。
📝 总结


本节课中,我们一起学习了MongoDB的主要优势。

你了解到,在使用MongoDB时,数据库模式可以是灵活的,你可以根据需要更改它,而无需涉及复杂的数据定义语言语句。MongoDB采用代码优先的开发方式,而不是先设计再编码的方式。MongoDB还利用了可演进的模式,可以在服务器上使用聚合管道进行复杂的数据分析,并且MongoDB提供了原生高可用性。
013:MongoDB的常见用例 🎯


在本节课中,我们将学习MongoDB数据库在不同领域的具体应用场景。通过学习这些用例,你将能够理解MongoDB如何凭借其灵活性和可扩展性,解决现实世界中的复杂数据问题。
概述:多源统一视图 📊
上一节我们介绍了MongoDB的基本特性,本节中我们来看看它的第一个核心应用场景。


MongoDB允许你将来自不同源头的数据整合进来。这意味着,你的数据不必再分散在各个孤立的系统中。你可以将多种形态和格式的数据摄取到MongoDB中,从而获得一个统一的整体视图。这得益于MongoDB支持的灵活模式。



物联网用例 🌐


物联网设备在全球范围内有数十亿台,从自动驾驶汽车中的微小组件到联网的智能灯泡。这些设备会产生海量数据,例如,一个气象站可能每分钟都会发送温度和风速读数。
凭借其可扩展能力,MongoDB可以轻松地在全球范围内分布式存储所有这些数据。一旦数据存入MongoDB,利用其强大的查询能力,所有这些数据都可以用于复杂的分析和决策制定。
电子商务用例 🛒


MongoDB同样适用于电子商务解决方案。电商网站上销售的商品具有不同的属性。例如,一部手机有存储容量、网络制式和颜色等属性;一本书则有出版社、作者和页数等属性。

此外,商品还有诸如热门评论、价格、库存和其他元数据等属性。借助MongoDB中的文档、子文档和列表属性,你可以将这些信息存储在一起,从而优化读取性能。这使得MongoDB成为需要动态模式的用例的绝佳选择。

实时分析用例 📈
当你需要进行实时分析时,MongoDB是一个很好的选择。大多数组织都希望基于数据做出更好的决策。进行历史分析相对容易,但只有少数能够对每分钟发生的变化做出响应,而这通常是由于复杂的提取、转换和加载过程造成的。
使用MongoDB,你可以在数据存储的位置完成大部分分析工作。这些数据可以是半结构化的,也可以是完全非结构化的。所有这些分析都可以实时进行。
游戏用例 🎮


MongoDB在游戏世界中也有一席之地。随着全球范围内多人游戏的普及,数据的跨地域传输变得至关重要。凭借其原生可扩展性,MongoDB使得触达全球用户变得更加容易。


此外,借助灵活的模式,支持不断变化的数据需求也变得更为简单。

金融用例 💳
MongoDB在金融行业也有应用场景。如今,我们希望银行交易尽可能快捷,同时也期望金融行业能保障我们的信息安全。

使用MongoDB,你可以每秒在数据库上执行数千次操作,并且所有信息在传输和磁盘存储时都是加密的。你还可以额外加密单个字段,以避免任何数据泄露事件。
最后,与所有行业一样,金融机构对服务的可靠性和全天候可用性有更高的要求。我们期望金融服务能够不间断地可用。这使得MongoDB成为银行、交易公司和整个金融行业的良好选择。
总结



本节课中,我们一起学习了MongoDB在多种场景下的应用。它提供的可扩展性使其易于在全球范围内工作,并使你能够对数据进行实时分析。从整合多源数据到支持物联网、电子商务、实时分析、游戏和金融等关键领域,MongoDB的灵活架构和强大功能使其成为处理现代数据挑战的有力工具。
014:CRUD操作 🛠️




在本节课中,我们将学习如何使用Mongo Shell连接MongoDB数据库,并执行基本的CRUD操作。CRUD是创建、读取、更新和删除操作的缩写,是数据库管理的核心。

概述 📋

Mongo Shell是MongoDB提供的一个命令行工具,用于与数据库进行交互。它是一个交互式的JavaScript接口,可以用来执行数据操作和管理任务。
连接数据库与查看信息 🔗





上一节我们介绍了Mongo Shell的基本概念。本节中我们来看看如何连接数据库并查看其结构。

首先,通过提供连接字符串连接到集群。连接成功后,可以查看所有数据库的列表。为简化说明,我们假设Shell已经连接到MongoDB实例。

要开始操作campus_management数据库,请运行以下语句:
use campus_management
然后,使用以下命令查看campus_management数据库中存在哪些集合:
show collections
该命令显示两个集合:staff和students。





创建操作 ➕

现在,让我们开始进行创建操作。


我们将向students集合中插入一个新文档。操作格式如下:
db.students.insertOne({ "first_name": "John", "last_name": "Doe", "email": "john.doe@example.com" })
操作结果是确认操作成功的回执。由于这是插入操作,它会显示insertedId。

_id是MongoDB中每个文档的必填字段。由于我们在John Doe的文档中没有自己提供,Mongo Shell驱动程序将自动添加_id字段并为我们生成对象ID。



Mongo Shell是一个JavaScript解释器,这意味着您也可以在其中定义变量和执行其他函数。以下是创建包含两个文档的变量,并将其传递给insertMany函数的示例:
let students_list = [
{ "first_name": "Jane", "last_name": "Doe", "email": "jane.doe@example.com" },
{ "first_name": "Bob", "last_name": "Smith", "email": "bob.smith@example.com" }
];
db.students.insertMany(students_list);


读取操作 👁️


上一节我们学习了如何创建数据。本节中我们来看看如何读取数据。


以下是几种读取操作的示例。

在第一个操作中,我们调用不带任何过滤条件的findOne函数。这将返回自然顺序中的第一个文档,即数据库在磁盘上引用文档的顺序。
db.students.findOne()


在第二个读取操作中,我们希望查找具有特定电子邮件地址的第一个学生。
db.students.findOne({ "email": "john.doe@example.com" })
如果有多个文档符合条件,由于我们使用的是findOne函数,只会读取第一个。


接下来,我们想检索所有姓氏为“Doe”的学生。
db.students.find({ "last_name": "Doe" })

最后,如果我们想计算有多少学生的姓氏是“Doe”,可以调用count函数。这个计数将在MongoDB上执行,只返回数值。
db.students.count({ "last_name": "Doe" })

更新操作 ✏️




现在我们将执行替换操作。让我们检索一个学生记录并对文档进行一些更改。
我们创建一个新字段来标识哪些学生是在校生或仅在线学习。我们还将用校园邮箱更新电子邮件。完成所有更改后,我们将调用replaceOne函数。
// 首先,检索并修改文档
let student = db.students.findOne({ "last_name": "Doe" });
student.student_type = "on_campus";
student.email = "john.doe@campus.edu";

// 然后替换文档
db.students.replaceOne({ "last_name": "Doe" }, student)
此语句的结果是一个确认回执,包含有关多少文档匹配我们的过滤条件以及实际修改了多少文档的计数信息。




在替换示例中,我们将整个文档与新更改一起发送回去。对于较大的文档,这将在客户端和数据库之间占用大量传输时间。相反,对于小的更改,我们可以使用MongoDB的原位更新。


我们通过构建一个更改文档来实现这一点,在我们的例子中,该文档只有两个赋值,它们属于$set操作符。然后,我们将调用updateOne函数。
db.students.updateOne(
{ "last_name": "Doe" },
{ $set: { "student_type": "on_campus", "email": "john.doe@campus.edu" } }
)
由于封锁,要将所有学生更新为仅在线学习,我们可以运行不带任何过滤条件和带有更改文档的updateMany函数。
db.students.updateMany(
{},
{ $set: { "student_type": "online_only" } }
)




删除操作 🗑️

与更新和查找类似,deleteOne函数将过滤条件作为第一个参数。运行该删除语句会提供一个确认回执和一个表示已删除文档数量的数字。
db.students.deleteOne({ "last_name": "Smith" })


同样,您可以使用deleteMany函数删除多个符合条件的文档。
db.students.deleteMany({ "student_type": "online_only" })
总结 🎯

本节课中我们一起学习了以下内容:
- Mongo Shell是MongoDB提供的一个交互式命令行工具,用于与数据库交互。
- 要使用Mongo Shell,首先需要通过连接字符串连接到集群。
- 使用
show dbs列出数据库,使用use <database_name>选择数据库,使用show collections显示数据库中的集合。 - CRUD操作包括创建、读取、更新和删除。
- 有用的函数包括:
insertOne、insertMany、findOne、find、count、replaceOne、updateOne、updateMany、deleteOne和deleteMany。 - 最后,根据运行的操作,会返回不同种类的确认回执。
015:索引


在本节课中,我们将要学习数据库索引的概念、作用及其在MongoDB中的实现方式。索引是提升数据库查询效率的关键工具,理解其工作原理对于设计高效的数据应用至关重要。
🎯 为什么需要索引?



索引帮助我们在不进行全局搜索的情况下快速定位数据。想象一下,大英图书馆收藏了2500万册图书。如果你想找到马丁·克莱普曼所著的《设计数据密集型应用》这本书,在没有索引的情况下,你需要逐一检查所有藏书。而有了索引,你可以直接前往计算机类图书区域,再进入数据库分类的书架,最后在标有“M”的书架上找到目标书籍。
我们每天都在使用索引来快速查找信息。例如,过去的电话簿非常流行,其中所有姓名都按姓氏和名字进行了索引。要找到“John Doe”,你可以直接跳转到姓氏为“Doe”的部分,然后在其中查找名字以“J”开头的条目。其他日常例子包括字典和书籍末尾的索引。




🔍 数据库中的索引应用


在数据库系统中,应为最频繁执行的查询创建索引。以校园管理数据库中的课程注册集合为例,我们经常需要根据课程ID查找学生信息。为了避免扫描整个集合,我们在课程注册集合的courseID字段上创建一个索引。


创建索引的命令如下:
db.courseEnrollment.createIndex({ courseID: 1 })
其中,courseID: 1表示按升序存储索引。



我们在courseID上创建的索引能帮助更高效地找到相关文档。但是,如果我们需要按学生ID升序来组织学生信息,MongoDB将需要在内存中进行排序,这在某些情况下可能效率不高。
📊 复合索引




为了解决上述问题,我们可以将索引改为复合索引,即对多个字段进行索引。命令如下:
db.courseEnrollment.createIndex({ courseID: 1, studentID: 1 })


由于索引中的条目是按升序组织的,一旦我们找到所有courseID为1547的文档,它们将因为此索引而自动按studentID排序。


🌳 MongoDB如何存储索引?
MongoDB中的索引是特殊的数据结构。它们存储被索引的字段以及文档在磁盘上的存储位置。


MongoDB以树的形式存储索引,具体来说是一种平衡树。以我们最后的例子为例,在我们的复合索引中,courseID作为第一个字段按升序排列。在每个树节点下,学生ID也按升序排列。这使得查找文档更加高效,无论是进行等值查询还是范围查询。如果你在一个已经建立索引的字段上进行排序,MongoDB无需再次对其进行排序。




📝 总结
本节课中我们一起学习了:
- 索引的作用是帮助快速定位数据,避免全局扫描。
- 应为最频繁的查询创建索引。
- 复合索引可以对多个字段进行索引。
- MongoDB在索引条目中存储被索引的数据以及文档在磁盘上的位置。
- MongoDB将索引存储为树形结构,以提高查找文档的效率。



理解并合理使用索引,是优化NoSQL数据库性能的核心技能之一。
016:聚合框架 🧮



在本节课中,我们将要学习MongoDB中的聚合框架。聚合框架是MongoDB中一个强大的数据处理工具,它允许我们对数据进行一系列操作,以得到我们想要的分析结果。我们将了解聚合框架是什么、它是如何构建的、最常用的阶段有哪些,以及它可以在哪些场景下使用。


什么是聚合框架? 🛠️
聚合框架,有时也被称为聚合管道,是一系列应用于数据的操作,目的是获得期望的结果。例如,为了了解学生是否真正掌握了知识,你可能希望查看2020年各课程的平均学生分数。这通常意味着需要先筛选出2020年的文档,然后按课程对这些文档进行分组,最后计算每年的平均分数。
聚合框架的工作方式就像一个管道:文档从一端进入,经过一个或多个处理阶段,最终以期望的格式从另一端输出。





聚合框架的核心阶段 📊
聚合管道由多个阶段组成,每个阶段对数据进行特定的转换。以下是一些最常用的阶段:

$match:用于筛选文档。例如,只选择年份为2020的文档。
{ $match: { year: 2020 } }



$group:用于按指定字段对文档进行分组,并可以执行聚合计算,如求平均值。
{ $group: { _id: "$course_id", averageScore: { $avg: "$score" } } }


$project:用于改变文档的结构,或选择性地包含或排除某些字段。
{ $project: { courseName: 1, averageScore: 1 } }

$sort:用于对文档进行排序。
{ $sort: { averageScore: -1 } }


$count:用于计算文档数量,并将结果赋值给一个字段。
{ $count: "totalStudents" }
$merge:用于将前一阶段的结果存储到目标集合中。
{ $merge: { into: "results_collection" } }



聚合阶段可以在管道中重复使用,这为我们提供了极大的灵活性来构建复杂的数据处理流程。
聚合框架的应用场景 🎯

上一节我们介绍了聚合框架的核心阶段,本节中我们来看看聚合框架可以在哪些实际场景中应用。



聚合框架非常适合生成各种报告和分析。例如:
- 在教育应用中,可以跟踪学生按课程的进度。
- 在电子商务应用中,可以计算每个国家产品的平均销售额。


这些报告可以通过聚合管道轻松创建。无论是复杂的计算,还是简单的数据分组以提供数据的不同视角,聚合框架都能胜任。


总结 📝



本节课中我们一起学习了MongoDB的聚合框架。我们了解到,使用聚合框架可以对MongoDB中的数据进行复杂的分析。我们可以通过构建包含$match、$group、$project、$sort等阶段的聚合管道来处理数据。最终的结果可以直接查询,也可以通过$merge阶段存储到另一个集合中,为数据分析和报告生成提供了强大的支持。
017:复制与分片 🧩



在本节课中,我们将学习MongoDB中两个核心概念:复制和分片。它们是实现数据库高可用性与可扩展性的关键技术。我们将了解它们如何工作,以及它们如何帮助构建健壮、高性能的数据库系统。



复制:实现高可用性 🔄
上一节我们介绍了NoSQL数据库的基本概念,本节中我们来看看复制。复制是MongoDB中用于确保数据高可用性和冗余的关键机制。



一个典型的MongoDB集群由三个数据承载节点组成。这三个节点拥有相同的数据,因此被称为副本集。数据首先写入主节点,随后被复制到从节点。
通过复制创建数据的多个副本,可以实现冗余。这样,即使某台服务器硬件发生故障,你仍然拥有数据的多个副本。


这为你在故障期间或计划维护期间提供了一个高可用的数据库。


此类计划维护应以滚动方式进行,例如,一次将一个节点下线以进行操作系统、安全、硬件或软件更新,或升级MongoDB本身。
关于复制的一个常见误解是,它可以防止灾难,例如意外删除数据库。由于它是一个副本集,在主节点上发生的任何操作都会被复制到从节点。

对于灾难恢复场景,我们依赖于备份和恢复。
分片:实现水平扩展 📊


在使用MongoDB一段时间后,你可能会发现硬件资源不足。例如,你需要存储更多数据,或者希望提高读写性能。自然地,你会投资于更大、更快的硬件来增加容量,但有时这并不可行。
在这些情况下,你可以通过实施分片来进行水平扩展,即对你最大的集合进行分区。


以下是分片的主要好处:

- 提高吞吐量:当你将数据分区到多个分片上时,通过将查询仅定向到相关的分片,可以提高吞吐量。
- 增加存储容量:你能够存储更多数据,这些数据之前无法存放在单个节点上。
- 基于区域的数据分布:你还可以根据区域跨分片分割数据。例如,美国客户的数据仅存储在美国运行的分片上,而欧洲客户的数据则存储在基于欧洲的分片上。

作为一个全球性应用程序,你获得的是一个统一的数据库视图来进行管理。



总结 📝
本节课中我们一起学习了MongoDB的两个核心扩展概念。


- 复制是数据的复制以及对数据所做的任何更改。它提供了数据的容错能力、冗余和高可用性。但复制无法防止灾难,例如文档、集合甚至数据库的误删除。对于这些人为错误,我们需要依靠备份。
- 对于不断增长的数据集,你可以使用分片来进行水平扩展,以应对更大的数据量和更高的性能需求。
018:从Python访问MongoDB 🐍


在本节课中,我们将学习如何使用Python与MongoDB数据库进行交互。具体来说,我们将了解什么是MongoClient,并学习如何使用Python对校园管理数据库执行基本的CRUD(创建、读取、更新、删除)操作。

🧩 理解MongoClient
MongoClient是一个帮助您与MongoDB交互的类。要使用它,我们首先需要从pymongo导入它,pymongo是Python的官方MongoDB驱动程序。

以下是建立连接并获取集合引用的基本步骤:
- 导入MongoClient:从
pymongo库中导入MongoClient类。 - 创建客户端实例:使用MongoDB服务器的地址(URI)创建一个
MongoClient实例。这个操作在代码中通常只执行一次。 - 获取数据库对象:通过客户端实例获取指向特定数据库(例如“campus_management”)的对象。
- 获取集合对象:从数据库对象中获取指向特定集合(例如“students”)的对象。
这个过程可以用以下代码概括:
from pymongo import MongoClient
# 创建MongoClient实例,连接到本地MongoDB服务器
client = MongoClient('mongodb://localhost:27017/')

# 获取‘campus_management’数据库对象
db = client['campus_management']


# 获取‘students’集合对象
students_collection = db['students']


现在,我们已经获得了对students集合的引用,可以开始执行数据操作了。


➕ 创建(Create)操作
我们可以向集合中插入新的文档。以下是两种插入数据的方法。
插入单个文档
使用insert_one函数插入一个文档。该函数以要插入的文档字典作为输入。


new_student = {
"first_name": "John",
"last_name": "Doe",
"email": "john.doe@example.com"
}
result = students_collection.insert_one(new_student)
print(f"插入的文档ID: {result.inserted_id}")


批量插入文档

使用insert_many函数一次性插入多个文档。该函数接受一个文档字典的列表作为输入。
new_students = [
{"first_name": "Alice", "last_name": "Smith", "email": "alice@example.com"},
{"first_name": "Bob", "last_name": "Johnson", "email": "bob@example.com"}
]
result = students_collection.insert_many(new_students)
print(f"插入的文档ID列表: {result.inserted_ids}")
🔍 读取(Read)操作


从集合中查询数据是常见的操作。MongoDB提供了多种查询方法。
查询单个文档
使用find_one函数。如果不提供过滤条件,它将返回集合中自然顺序下的第一个文档(即数据库在磁盘上引用文档的顺序)。


# 获取第一个文档
first_student = students_collection.find_one()
print(first_student)
# 根据条件获取第一个匹配的文档(例如,按邮箱查找)
student_by_email = students_collection.find_one({"email": "john.doe@example.com"})
print(student_by_email)


注意:即使有多个文档匹配条件,
find_one也只会返回第一个。
查询多个文档
使用find函数可以获取匹配条件的所有文档。它返回一个游标(Cursor)对象。


# 查找所有姓氏为‘Doe’的学生
cursor = students_collection.find({"last_name": "Doe"})

理解游标(Cursor)
当对MongoDB集合执行find操作时,返回的是一个游标。这个游标指向MongoDB中的文档。要获取所有文档,需要遍历或转换这个游标。
# 将游标转换为列表以获取所有文档
all_does = list(cursor)
for student in all_does:
print(student)


统计文档数量

如果只想统计匹配条件的文档数量,可以使用count_documents函数。计数操作在MongoDB服务器端完成,只将数字结果返回给客户端。

count = students_collection.count_documents({"last_name": "Doe"})
print(f"姓氏为Doe的学生数量: {count}")

✏️ 更新(Update)操作

更新文档有两种主要方式:替换整个文档或进行局部更新。
替换整个文档

首先检索一个文档,在本地修改后,使用replace_one函数将其替换回数据库。第一个参数是过滤条件,第二个参数是更新后的Python字典对象。

# 1. 检索一个学生文档
student_to_update = students_collection.find_one({"last_name": "Doe"})
# 2. 修改文档(添加新字段,更新邮箱)
student_to_update["on_campus"] = True
student_to_update["email"] = "john.doe@campus.edu"

# 3. 替换文档
result = students_collection.replace_one({"last_name": "Doe"}, student_to_update)
print(f"匹配到的文档数: {result.matched_count}, 修改的文档数: {result.modified_count}")


对于大型文档,这种方式会在客户端和数据库之间传输大量数据,可能效率较低。
局部更新(推荐)
对于小的更改,可以使用MongoDB的原地更新操作符(如$set)。这不需要先检索整个文档,只需构造一个描述更改的文档。


# 定义要更新的字段
update_data = {
"$set": {
"on_campus": False,
"email": "john.doe@online.edu"
}
}
# 执行更新
result = students_collection.update_one({"last_name": "Doe"}, update_data)
print(f"匹配到的文档数: {result.matched_count}, 修改的文档数: {result.modified_count}")
更新多个文档

使用update_many函数可以一次性更新所有匹配过滤条件的文档。


# 例如,由于封锁,将所有学生更新为仅在线学习
result = students_collection.update_many({}, {"$set": {"on_campus": False}})
print(f"所有学生已更新为仅在线模式。修改的文档数: {result.modified_count}")

🗑️ 删除(Delete)操作
与更新和查找类似,删除操作也提供了删除单个或多个文档的函数。


删除单个文档

使用delete_one函数,其第一个参数是过滤条件,用于找到要删除的文档。
result = students_collection.delete_one({"email": "john.doe@online.edu"})
print(f"删除的文档数量: {result.deleted_count}")
删除多个文档


使用delete_many函数,删除所有匹配给定条件的文档。

result = students_collection.delete_many({"on_campus": False})
print(f"删除的文档数量: {result.deleted_count}")
📝 总结
在本节课中,我们一起学习了如何使用Python连接和操作MongoDB数据库。
- MongoClient:是从
pymongo导入的一个类,是与MongoDB交互的主要入口点。 - 连接与引用:我们学会了如何建立连接,并获取数据库和集合的引用。
- CRUD操作:
- 创建:可以使用
insert_one进行单条插入,或使用insert_many进行批量插入。 - 读取:使用
find_one查询单个文档,使用find查询多个文档并返回游标,使用count_documents进行计数。 - 更新:可以使用
replace_one替换整个文档,但更推荐使用update_one或update_many配合$set等操作符进行高效的局部更新。 - 删除:使用
delete_one或delete_many根据条件删除文档。
- 创建:可以使用

通过掌握这些基本操作,你已经能够使用Python脚本有效地管理MongoDB中的数据了。
019:Apache Cassandra概述 🗃️


在本节课中,我们将学习Apache Cassandra的基本概念、核心特性、适用场景以及它与MongoDB等NoSQL数据库的主要区别。课程旨在帮助初学者理解Cassandra的设计哲学和典型应用案例。
什么是Apache Cassandra? 🤔



上一节我们介绍了NoSQL数据库的多样性,本节中我们来看看其中一款重要的数据库:Apache Cassandra。
根据《Cassandra权威指南》一书中的定义,Apache Cassandra是一个开源、分布式、去中心化、弹性可扩展、高可用、容错、可调一致性的数据库。其分布式设计基于亚马逊的Dynamo,数据模型则借鉴了谷歌的Bigtable。它最初由Facebook创建,目前被许多主流网站所使用。

以下是一些使用Cassandra的知名服务:
- Netflix
- Spotify
- Uber


Cassandra与MongoDB的对比 ⚖️
我们已经了解了面向文档的数据库MongoDB,现在我们来对比一下Cassandra与它的不同。
NoSQL数据库通常针对特定用例设计。例如,MongoDB通常适用于数据可以表示为键值对文档类型的搜索相关场景。但是,对于那些需要极快速记录数据并立即提供读取,同时面对数十万请求的场景呢?



比如,记录在线商店的交易流水,或存储Netflix这类服务的用户访问信息或配置文件。在这种情况下,Apache Cassandra这样的解决方案可能更为适用。



以下是两者的主要区别:
- 设计目标不同:MongoDB侧重于读取密集型用例,非常注重数据一致性。Cassandra则服务于需要快速存储数据、按键检索、始终可用、快速扩展和服务器地理分布的用例。
- 架构不同:MongoDB采用主从架构,而Cassandra采用更简单的点对点(P2P) 架构。
Cassandra的核心特性 ✨


Cassandra拥有一系列使其区别于其他NoSQL解决方案的特性。
以下是其主要功能列表:
- 分布式与去中心化:采用简单的点对点架构,这使得Cassandra成为最易安装部署的NoSQL数据库之一。
- 始终可用与可调一致性:优先保证可用性,同时允许调整一致性级别,具备容错能力。
- 极高的写入吞吐量:在保持集群其他操作(如读取)性能的同时,实现极快的写入速度。
- 线性快速扩展:能够以线性方式极其快速地扩展集群,无需重启或重新配置服务。
- 多数据中心部署支持:对于需要全球访问的服务极其有用。
- 类SQL的友好查询语言:使用
CQL进行查询,降低了学习成本。

Cassandra的定位与限制 ⚠️




Apache Cassandra是目前全球最受欢迎的数据库解决方案之一,它可靠、高性能且可扩展。由于其流行度,有时会被误认为是关系型数据库的直接替代品。


但Cassandra在设计上不包含关系型数据库的三个主要特性,因此不应被视为其直接替代品:
- 不支持连接(Joins)
- 聚合(Aggregation)支持有限
- 对事务(Transactions)的支持有限
虽然Cassandra的写入操作本身具有原子性、隔离性和持久性,但“一致性”部分并不完全适用,因为它没有参照完整性或外键的概念。
简而言之,如果你考虑用Cassandra来跟踪银行的账户余额,可能并不合适。如果您的应用涉及连接和聚合需求,最好将Cassandra与Apache Spark这类处理引擎配合使用。





Cassandra的最佳适用场景 🎯
那么,Apache Cassandra在哪些使用场景下是一个好的选择呢?
以下是Cassandra表现优异的几种情况:

- 写入密集型应用:当应用程序的写入量超过读取量时,例如存储网站的所有点击记录或服务的所有访问尝试。
- 数据更新或删除较少:数据以近似追加的方式进入系统。
- 通过已知主键(分区键)访问数据:分区键有助于数据在集群内均匀分布。
- 查询中无需连接或复杂聚合:如前所述,这是Cassandra的设计限制。


常见用例 🌍
如前所述,Cassandra非常适合需要全球范围、始终在线的在线服务和应用程序,如Netflix、Spotify和Uber。当然,还有许多其他用例可以利用其能力。



以下是几个典型用例:
- 为电子商务网站存储交易数据以进行分析,或存储用户与网站的交互数据以实现个性化体验。
- 存储用户配置文件信息,用于会话丰富化或授予个性化的服务访问权限。
- 时间序列数据:Cassandra在时间序列用例中表现出色,数据按时间顺序追加进入,例如来自传感器的天气更新。您的查询可以针对特定传感器在特定时间间隔内发生的情况。
总结 📝
本节课中我们一起学习了Apache Cassandra。我们了解到,Apache Cassandra是一个开源、分布式、去中心化、弹性可扩展、高可用、容错、可调一致性的数据库。

它最适合被那些需要数据库始终可用、能在高流量情况下快速扩展、可以地理分布式部署、且要求高写入性能的“始终在线”型在线应用程序使用。

典型的应用者包括Netflix、Uber和Spotify等在线服务,电子商务网站以及时间序列应用程序。
020:Apache Cassandra的关键功能 🚀




在本节课中,我们将学习Apache Cassandra数据库的核心特性。我们将探讨其分布式与去中心化架构、数据复制机制、可用性与一致性的权衡、可扩展性、高写入吞吐量以及其查询语言CQL。这些特性共同构成了Cassandra作为高性能、高可用NoSQL数据库的基础。
分布式与去中心化架构
上一节我们介绍了Cassandra的概览,本节中我们来看看其架构的两个核心特征:分布式与去中心化。



- 分布式意味着Cassandra集群可以运行在多台机器上。对于用户和应用程序而言,整个集群呈现为一个统一的整体。其架构设计使得Cassandra应用客户端和服务器能够提供足够的信息,以最优方式在集群中路由用户请求。因此,作为最终用户,你可以向集群中的任何Cassandra节点写入数据,Cassandra都能理解并处理你的请求。
- 去中心化意味着Cassandra集群中的每个节点都是相同的,即没有主节点或从节点之分。Cassandra使用点对点(P2P)通信协议,并通过一种名为
gossip的协议来保持所有节点的同步。




数据分布与复制
理解了架构基础后,我们来看看数据是如何在这种分布式架构中存储和复制的。
数据在集群中的分布始于计划执行的查询。例如,如果你的查询是“我想知道某个州的所有用户”,那么你需要根据“州”这一列来分组数据。这是通过声明一个以“州”列作为分区键的表来实现的。Cassandra会根据你声明的分区键对数据进行分组,然后通过哈希每个分区键(称为令牌)来在集群中分布数据。
每个Cassandra节点都有一个预定义的、支持的令牌区间列表。数据根据键值的哈希结果和集群中预定义的令牌分配,被路由到相应的节点。
数据在集群中初始分布后,Cassandra会进行数据复制。



以下是数据复制的关键点:
- 副本数量指的是在特定时间有多少个节点包含某一份数据。
- 数据复制在集群中顺时针进行,同时会考虑节点的机架和数据中心位置。
- 复制根据设定的复制因子进行,该因子指定了每个分区数据副本将存储在多少个节点上。

高可用性与最终一致性
数据复制带来了高可用性。Cassandra经常被称为具有最终一致性或可调一致性,因为默认情况下,它会为了实现高可用性而在一定程度上牺牲强一致性。
根据CAP定理,分布式系统无法同时保证强一致性和高可用性。Cassandra被设计为始终可用,这意味着即使集群部分节点失效,仍然会有节点可以响应服务请求,尽管返回的数据可能不是最新的。
好消息是,开发者可以精确控制他们需要的一致性级别(强一致性或最终一致性)。数据的一致性可以在操作级别进行控制。如果存在数据不一致,这些冲突将在读操作期间得到解决。

容错性与线性可扩展性
容错性是Cassandra分布式和去中心化特性的固有优势。所有节点功能相同、以点对点方式通信、数据被分布式存储和复制,这些特点使得Cassandra在节点发生故障时具有很高的容错性和适应性。
用户联系集群中的一个节点。如果该节点无响应,用户将收到错误信息并联系另一个节点。
同样的架构灵活性也体现在Cassandra扩展集群能力的方式上。集群通过简单地添加节点来扩展,性能随节点数量的增加而线性提升。新添加的节点会立即开始处理流量,而现有节点会将其部分职责转移给新节点。添加和移除节点的操作都可以无缝进行,不会中断集群运行。
高写入吞吐量
Cassandra通过以下方式优雅地处理大量写入操作:
- 并行地向所有持有数据副本的节点进行写入。
- 一个重要的特性是,默认情况下,在节点级别没有“先读后写”的操作。
- 写入操作在内存中执行,然后刷新到磁盘。
- 在磁盘上,数据以顺序追加的方式写入,后续通过压缩过程来调和数据。

Cassandra查询语言(CQL)


最后,我们来了解与Cassandra交互的语言。Cassandra查询语言,简称CQL,是用于数据定义和操作的语言。


CQL的语法与SQL相似,这减少了开发者开始使用Cassandra所需的时间。诸如CREATE TABLE、INSERT、UPDATE、DELETE、ALTER等操作都可以在CQL中使用。
需要注意的是,虽然CQL和SQL在语法上有相似之处,但相似性仅止于此。Cassandra中读写操作的执行方式与关系型数据库中的执行方式不同。




总结

本节课中,我们一起学习了Apache Cassandra的关键功能:
- 其分布式和去中心化架构帮助Cassandra实现了高可用性、可扩展性和容错性。
- 数据分布和复制发生在一个或多个数据中心的集群中。
- Cassandra提供了高写入吞吐量。
- CQL是用来与Cassandra通信的语言。

理解这些核心功能是有效使用和设计Cassandra数据库系统的基础。在接下来的课程中,我们将更深入地探讨数据建模和查询执行的具体细节。
021:Cassandra数据模型(第一部分)📊



在本节课中,我们将学习Apache Cassandra数据模型的基础知识。我们将了解Cassandra如何存储数据,以及其核心概念如键空间、表、主键和分区键。这些知识对于理解Cassandra的高性能读写机制至关重要。

概述

Cassandra将数据存储在表中,表的结构定义了数据在集群和节点级别的存储方式。表被分组在键空间中。键空间是一个逻辑实体,包含一个或多个表,并定义了一些应用于其所有表的选项,其中最突出的是键空间使用的复制策略。通常建议每个应用程序使用一个键空间。
键空间与表



在后续视频中,我们将详细讨论键空间及其操作。现在,让我们看一个键空间和表定义的例子。


我们创建了一个名为intro_cassandra的键空间,其复制因子为5,数据在两个数据中心之间分割,数据中心1的复制因子为2,数据中心2的复制因子为3。

CREATE KEYSPACE intro_cassandra
WITH replication = {
'class': 'NetworkTopologyStrategy',
'datacenter1': 2,
'datacenter2': 3
};


下一步是在这个键空间中创建表。为此,我们可以声明工作键空间(即intro_cassandra),或者直接创建表。在后一种情况下,我们需要在表名前加上目标键空间名称,例如intro_cassandra.groups。
CREATE TABLE intro_cassandra.groups (
group_id int,
group_name text,
username text,
age int,
PRIMARY KEY (group_id, username)
);




我们创建了一个名为groups的表及其模式。这个例子中展示的只是CQL(Cassandra查询语言)语法,我们在之前的“关键特性”视频中介绍过。我们将在本视频后面回到表模式。

表与主键

表是组织集群和节点级别数据存储的逻辑实体,它们包含列的行。你可以在不影响数据更新或运行查询的情况下创建、删除和修改表。为了创建一个表,我们需要使用Cassandra查询语言声明一个模式。表模式至少包括表的主键定义和表的常规列。
回到我们之前的例子,groups表存储关于几个组的信息,例如组ID、组名,以及每个组成员的用户名和年龄。你可以看到主键由两列组成:group_id和username。在Cassandra的术语中,group_id列被称为分区键,username列被称为聚类键。


让我们更多地谈谈主键。首先,主键基本上是创建表时声明的表列的子集。除了声明表的列之外,还必须指定主键。一旦定义,主键就不能更改。
主键的双重角色
在Cassandra中,主键有两个角色。第一个角色是优化查询的读取性能。请记住,NoSQL系统是查询驱动的数据建模系统,这意味着只有在定义了你想回答的查询之后,才能开始表定义。你应该基于你的查询来构建主键。



第二个角色是为查询提供唯一性。主键有两个组成部分:强制性的部分称为分区键,可选地,你可以有一个或多个聚类键。

当数据被插入到集群的表中时,数据按分区键分组到分区中,第一步是对分区键应用哈希函数。分区键的哈希用于确定哪个节点及其后续副本将获得数据。
分区键与数据局部性
简单来说,分区键决定了数据在集群中的位置。


你可以在图表和表中看到,数据根据分区键group_id分组,并且每个分区被分布到集群的一个节点上。分区是Cassandra中的存储原子,这意味着一个分区的数据总是可以在一个节点及其副本上找到(在复制因子大于1的情况下)。

因此,如果我们想回答查询“组12中的所有用户”,那么查询可以只寻址第四个节点,并得到答案。在大型集群中,那些由数百或数千个节点组成的集群,限制回答查询所需联系的节点数量对于查询性能至关重要。
在我们进入下一个视频详细讨论聚类键之前,首先让我们定义另外两个概念:静态表和动态表。
静态表与动态表
当表的主键只包含分区键(单列或多列)而没有聚类键时,该表被称为静态表。


当表的主键由分区键(一个或多个)和聚类键(一个或多个)组成时,该表被称为动态表。


这个users表是一个静态表,正如你所看到的,主键只包含分区键。这意味着我们将拥有的不同用户数量就是我们表中将拥有的分区数量。
在静态表中,分区只有一个条目,因此被称为静态分区。
总结
在本节课中,我们一起学习了Cassandra数据模型的基础知识。我们了解到:
- Cassandra将数据存储在表中,表被分组在键空间中。建议每个应用程序使用一个键空间。
- 你可以在不影响数据更新或运行查询的情况下创建、删除和修改表。
- 主键有两个角色:优化表上查询的读取性能,以及为条目提供唯一性。
- 主键有两个组成部分:一个强制性的分区键和一个或多个可选的聚类键。
- Cassandra有两种类型的表:静态表和动态表。静态表是那些主键只包含分区键而没有聚类键的表。



理解这些核心概念是掌握Cassandra高效数据存储和检索机制的关键。在下一部分,我们将深入探讨聚类键的作用以及动态表的工作方式。
022:Apache Cassandra 数据模型(第二部分)🔑


在本节课中,我们将继续学习Apache Cassandra的数据模型。我们将重点介绍聚类键的概念、动态表的特性,以及设计数据模型时需要遵循的基本指导原则。通过本课的学习,你将能够理解如何通过合理的主键设计来优化查询性能。




在上一节中,我们介绍了主键、分区键的作用以及静态表的定义。本节中,我们来看看主键的另一个关键组成部分——聚类键。
聚类键的作用
回顾上一节提到的 groups 表,其主键定义如下:
PRIMARY KEY (group_id, username)
其中,group_id 是分区键,而 username 是聚类键。



分区键决定了数据在集群中的物理存储位置(数据局部性)。而聚类键则负责指定分区内部数据的排序方式(升序或降序),并优化对分区内相似值(列数据)的检索。

聚类键可以是单列或多列。在我们的例子中,聚类键只包含 username 这一列。这意味着在 group_id 分区内部,数据默认会按照 username 的升序进行存储。因此,当我们查询某个特定组的所有用户时,返回的数据将默认按用户名升序排列。
聚类键如何提升查询性能



聚类键除了为主键条目提供唯一性外,更重要的是能显著提升读查询的性能。以下通过一个例子来说明。
假设我们需要回答这样一个查询:“给我组ID为12且年龄为32的所有用户”。为此设计的数据模型可能如下:

PRIMARY KEY (group_id, age, username)
这里,分区键是 group_id,聚类键由 age 和 username 两列组成。
在每个分区内部,数据首先会按照 age 进行分组和排序,然后在每个年龄组内,再按照 username 进行分组。这样,同一个组内所有年龄相同的用户会被存储在一起。
因此,执行上述查询时,系统只需定位到存储 group_id=12 分区的节点,并读取该分区内 age=32 的连续记录即可,极大地减少了需要扫描的数据量。
从分区中减少需要读取的数据量对于查询时间至关重要,尤其是在处理大型分区时。 如果没有聚类键的有序组织,Cassandra可能不得不读取数百MB的数据,而实际只需其中几KB的信息。





动态表与分区增长
在动态表中插入新数据,例如向 groups 表插入新条目,操作会定位到正确的分区并增加其大小。由于主键中包含聚类键,分区会随着不同条目数量的增加而动态增长。

需要说明的是,在讨论的示意图中,为了简化,未考虑数据复制。例如,可能只有一个节点持有 group_id=45 的分区。只要集群结构不变,所有对组45的读写操作都会被路由到该特定节点。如果集群发生变更(如节点加入或离开),则会触发新的令牌分配和数据重新分布。
数据建模的基本指导原则
我们刚才所做的——为了以最优时间回答查询而构建主键——是数据建模过程的开始。Cassandra建模远不止定义主键,但为了保持简单,我们聚焦于这个最重要的部分。
以下是设计表主键时应考虑的简单规则:
- 选择合适的分区键:分区键应能启动你的查询,同时确保数据在集群中均匀分布。例如,如果存在许多不同的组且各组大小相似,那么
group_id可能是一个好的分区键选择。 - 最小化需要读取的分区数量:设计的主键应能让你在回答特定查询时,尽可能减少需要读取的分区数量。请记住,数据是分布在集群中的。如果需要读取多个分区,则可能需访问多个节点,这会增加查询时间甚至导致超时。因此,最优的设计是通过读取一个分区来回答查询。
在总结之前还有一点需要注意:除了上述基本规则,请确保构建的聚类键能通过根据查询需求对列进行排序,来进一步减少需要读取的数据量。


课程总结
本节课中,我们一起学习了Apache Cassandra数据模型的关键概念:
- 聚类键指定了数据在分区内部的排列顺序(升序或降序)。它可以是单列或多列键。
- 聚类键不仅为主键提供唯一性,还能通过组织分区内数据来显著提升读查询性能。
- 减少从分区中读取的数据量对查询时间至关重要,尤其是在处理大型分区时。
- 在动态表中,分区大小会随着条目数量的增加而动态增长。
- 数据建模的核心是从你想要回答的查询出发,然后基于查询来构建主键,以期获得最佳的读取性能。构建一个能在最优时间内回答查询的主键,是数据建模过程的重要开端。
023:Cassandra查询语言Shell(CQLSH)简介


在本节课中,我们将学习Cassandra查询语言(CQL)以及其交互式Shell工具CQLSH。你将了解CQL的基本概念、如何运行CQL查询、CQLSH的常用命令行选项以及一些特殊的Shell命令。


🗣️ 什么是Cassandra查询语言(CQL)?
Cassandra查询语言,简称CQL,是与Apache Cassandra集群通信的主要语言。CQL具有简单直观、类似SQL的语法,允许创建键空间(keyspace)、表(table),以及执行插入、更新、删除和选择查询。
虽然CQL语法与SQL有相似之处,但两者之间存在许多差异。最显著的区别之一是CQL不支持JOIN语句。在Cassandra中,如果需要连接数据,你需要在存储时就将数据预先连接好。此外,尽管某些操作在语法上看似与SQL相似,但它们在Cassandra中的行为是不同的。例如,插入、更新和删除操作是直接在内存中进行的,无需事先读取数据来定位。
在后续的实践练习中,你会看到CQL关键字是大小写不敏感的。标识符(如表名)也是大小写不敏感的,除非它们被双引号括起来。例如,select 和 SELECT 被视为相同。如果你使用大写字母输入标识符名称,Cassandra默认会将其存储为小写。

注释文本由双斜杠 // 表示,CQL会忽略这些注释。
💻 如何运行CQL查询?
运行CQL查询主要有两种方式:
- 通过编程方式运行:使用获得许可的Cassandra客户端驱动程序。有多种选择,包括Java、Python和Scala。默认的驱动程序是开源的DataStax Java驱动。
- 通过CQL Shell客户端运行:使用随Cassandra软件包提供的CQLSH工具。




CQLSH是一个基于Python的命令行Shell,它使用CQL与Cassandra集群通信。该软件随每个Cassandra软件包一起提供。CQLSH默认连接到运行命令的单个节点,也可以通过命令行选项指定要连接的节点。


市场上还有其他使用CQL与Cassandra通信的CQL编辑器。
🛠️ CQLSH命令行选项简介
在使用CQLSH之前,了解一些常用的命令行选项很有帮助。以下是几个关键选项:


--help:显示关于CQLSH命令选项的帮助信息。--version:用于检查正在使用的CQLSH版本。--user和--password:用于身份验证。--keyspace:指定要连接到的键空间。--file:启用从给定文件执行命令。--request-timeout:可以为查询设置超时时间,默认为10秒。

📝 CQLSH使用示例
让我们看一个简单的CQLSH输出示例。假设我们使用 intro_cassandra 键空间。

首先,我们选择组ID为12的用户:




USE intro_cassandra;
SELECT * FROM users WHERE group_id = 12;


接着,我们向 groups 表插入一条组ID为12的新记录:

INSERT INTO groups (group_id, group_name) VALUES (12, 'New Group');
最后,再次选择组ID为12的用户,并查看插入的数据:
SELECT * FROM groups WHERE group_id = 12;



执行这些命令后,你将在CQLSH中看到相应的查询结果。




⚙️ CQLSH的特殊命令
CQLSH还提供了一些特殊命令来辅助操作和管理。以下是其中几个:
CAPTURE:捕获命令的输出并将其添加到文件中。CONSISTENCY:显示当前的一致性级别并设置新的级别。COPY:将数据复制到Cassandra或从Cassandra复制出来。DESCRIBE:描述当前的Cassandra集群及其对象。EXIT:终止CQL会话。PAGING:启用或禁用查询结果的分页显示。TRACING:启用或禁用请求跟踪。
在实践环节中,你将有机会体验其中一些命令。接下来,我们将更详细地了解 CONSISTENCY 和 COPY 命令。






深入理解 CONSISTENCY 命令



Cassandra具有可调一致性(tunable consistency)。这意味着你可以在操作级别设置Cassandra的一致性级别。
在Cassandra中,一致性(consistency)指的是,为了使一个写或读操作被视为成功,需要从所有副本节点中获得响应的节点数量。
CONSISTENCY 命令可用的选项包括:
ONE,TWO或THREE:指定需要响应的具体节点数量。QUORUM:需要集群中所有副本节点的大多数节点响应。ALL:需要所有副本节点都响应。LOCAL_QUORUM:需要本地数据中心(根据键空间设置的复制策略)中大多数节点响应。
示例:假设我们有一个包含8个节点和2个数据中心的Cassandra集群。一个数据中心的复制因子(Replication Factor)为2,另一个为3,那么总复制因子就是5。

如果我们在一个写操作上设置一致性级别为 QUORUM,那么:
QUORUM意味着需要副本节点中的大多数节点响应。在这个例子中,大多数是3个节点。- 写操作会发送给所有5个副本节点,但需要至少3个来自两个数据中心的节点响应,操作才能被视为成功。



深入理解 COPY 命令
虽然Cassandra中的批量复制通常应通过特殊程序完成,但如果你只是想测试模型,或者正在处理较小的文本分隔数据集,那么可以使用 COPY FROM 或 COPY TO 操作将数据导入Cassandra或从Cassandra导出。
COPY TO:将表中的数据导出到CSV文件中。每一行都被写入目标文件的一行,字段之间由分隔符分隔。COPY FROM:将CSV文件中的数据导入到现有表中。源文件中的每一行都被导入为一行数据。数据中的所有行必须包含相同数量的字段,并且主键字段必须有值。该过程会验证主键并相应地导入数据。



🎯 课程总结
在本节课中,我们一起学习了以下内容:

- CQL是与Apache Cassandra集群通信的主要语言。CQL关键字和标识符是大小写不敏感的。
- CQL查询可以通过编程方式(使用Cassandra客户端驱动程序)运行,也可以在Cassandra提供的基于Python的CQL Shell客户端上运行。
- 使用CQL Shell,你可以创建、修改和删除键空间与表,插入、更新和删除数据,以及使用
SELECT执行查询。 - CQL Shell提供了一些特殊命令,包括
CONSISTENCY和COPY命令。CONSISTENCY命令可用于调整数据的一致性级别,而COPY命令可用于向Cassandra导入数据或从Cassandra导出数据。
024:CQL数据类型


在本节课中,我们将学习Cassandra查询语言(CQL)支持的数据类型。我们将了解其主要分类,并学习如何在定义Cassandra表时使用这些数据类型。
CQL支持多种数据类型,它们主要可以分为三大类:内置数据类型、集合数据类型和用户定义数据类型。用户可以根据应用程序和数据模型的需求选择合适的数据类型。





接下来,我们将逐一讨论这些类别,以理解它们的含义。

🏗️ 内置数据类型


内置数据类型是Cassandra中预定义的。用户可以将变量声明为这些类型中的任何一种。


除了像ASCII、BOOLEAN、DECIMAL、DOUBLE、FLOAT、INT和TEXT这样比较直观的常规数据类型外,还有一些其他类型可能需要稍作解释。


例如,BLOB数据类型。虽然Cassandra主要存储基于文本的信息,但它也可以存储BLOB,即二进制大对象。BLOB通常用于存储图像、音频或其他多媒体对象。在Cassandra中,BLOB代表作为单个实体存储的二进制数据集合,建议其大小不要超过1兆字节。
因此,您可以使用BLOB存储一个小图像或字符串。

BIGINT数据类型可用于64位有符号长整数。与INT数据类型相比,此数据类型存储的整数范围更大。
众所周知的VARCHAR在Cassandra中也可作为数据类型使用,它代表UTF-8编码的字符串。
🧺 集合数据类型
接下来是更复杂的数据类型。Cassandra提供集合类型,作为一种将数据分组并存储在单个列中的方式。


例如,在关系型数据库中,像用户的多个电子邮件地址这样的分组,是通过用户表和电子邮件表之间的多对一连接关系来关联的。Cassandra通过在用户表中将用户的电子邮件地址存储在集合列中,来避免两个表之间的连接。每个集合都指定了所持有数据的数据类型。
集合适用于存储数据量有限的情况。如果数据具有无限增长潜力(例如每秒发送的消息或记录的传感器事件),则不应使用集合数据类型。相反,应使用具有复合主键的表,并将数据存储在聚类列中。
在集合数据类型类别中,有三种数据类型:


以下是集合数据类型的三种具体形式:



- 列表:此Cassandra数据类型表示表中一个或多个元素的集合。在需要维护元素顺序且值可以存储多次(例如日志条目)的情况下使用列表。
- 映射:此Cassandra数据类型表示键值对的集合。映射是一种用于存储元素键值对的数据类型,例如使用日期然后文本输入的日记条目。
- 集合:此Cassandra数据类型表示表中一个或多个已排序元素的集合。集合是一种用于存储一组元素的数据类型。集合的元素将按排序顺序返回,例如电子邮件地址列表。


🔧 集合数据类型应用示例
让我们回到用户表,并向表中添加一个名为jobs的新列,它基本上就是一个工作列表。



我们希望按照工作发生的顺序来存储它们。请记住,用户表是一个静态表,其主键由user_id列组成。


在Cassandra中,我们将把所有用户的工作存储在一个列中,因为我们无法在这种情况下执行连接。我们将使用集合数据类型中的列表类型,因为我们希望保留工作的顺序。另一个原因是,一个人可以在特定公司工作不止一次,因此不需要唯一性。

我们可以在列表的开头、结尾或特定位置添加一个工作。列表中的条目可以是重复的,因为它们不是唯一的。
在CQLSH中对我们的表进行SELECT查询显示,当前为我们的用户记录了两份工作。
我们也可以从列表中删除一个条目。现在对我们的表进行SELECT查询显示,我们的用户只列出了一份工作。


🧩 用户定义数据类型

我们已经看到,集合数据类型可以用来模拟一对多的连接关系。然而,对于一对一的关系,我们可以使用Cassandra的用户定义类型。


UDT可以将多个数据类型附加到单个列。可以想象一个地址是由公寓号、楼栋、街道等组合而成的。
CQL允许用户创建自己的数据类型。创建的UDT中使用的字段可以是任何有效的数据类型,包括集合和其他现有的UDT。创建数据类型及其字段后,用户可以修改、验证甚至删除一个字段或整个数据类型。一旦创建,UDT就可以用来定义表中的列。
在这个例子中,我们创建一个名为address的新数据类型。创建后,我们可以用它来定义新表location中的列。
我们可以使用新的地址数据类型插入数据,也可以删除该数据类型。


📝 课程总结



在本节课中,我们一起学习了Cassandra支持内置、集合和用户定义数据类型。
集合和用户定义数据类型都提供了一种将数据分组和存储在一起的方式。集合数据类型可以模拟一对多关系。集合数据类型有三种:列表、映射和集合。

用户定义数据类型可以模拟一对一关系,并且可以将多个数据字段附加到一个列上。
025:键空间操作 🔑



在本节课中,我们将学习Apache Cassandra中的键空间操作。我们将了解键空间的作用、复制因子与复制策略的概念,并掌握如何创建、修改和删除键空间。
概述
上一节我们介绍了Cassandra中的表和键空间这两个逻辑实体。本节中,我们将深入探讨键空间及其相关操作。键空间必须在创建表之前定义,因为它没有默认值。一个键空间可以包含任意数量的表,而一个表只能属于一个键空间。复制是在键空间级别指定的。



键空间的作用与创建

键空间是Cassandra中数据的顶层容器。在创建表之前,必须先定义一个键空间。复制因子在创建键空间时指定,但之后可以修改。
以下是创建键空间的CQL示例:





CREATE KEYSPACE Intro_Cassandra
WITH replication = {
'class': 'NetworkTopologyStrategy',
'datacenter1': 3,
'datacenter2': 2
};


在这个例子中,我们创建了一个名为 Intro_Cassandra 的键空间。它使用 NetworkTopologyStrategy 复制策略,将数据(即表的分区)在集群节点间复制5次:数据中心1的3个节点和数据中心2的2个节点。
要检查键空间是否创建成功,可以使用以下命令:


DESCRIBE KEYSPACES;
或
DESCRIBE Intro_Cassandra;
复制因子与复制策略

复制因子指的是数据在不同节点上放置的副本数量。复制策略则决定了在根据分区键哈希和令牌预分配完成初始数据分布后,这些副本将位于集群的哪些节点上。数据复制依赖于这两个信息:复制因子和复制策略。
关于Apache Cassandra中的副本,有两个重要的注意事项:
- 所有副本同等重要,没有主副本或从副本之分。
- 通常,复制因子不应超过集群中的节点数量。

复制示例分析



让我们看一个简单的例子。假设有一个包含4个节点的Cassandra集群,只有一个数据中心。我们定义一个名为 Intro_Cassandra 的键空间,复制因子为3。
在CQL中创建键空间时,我们需要指定 class 为 NetworkTopologyStrategy(这是生产系统推荐的唯一选项),并在数据中心级别指定复制因子。
假设集群拓扑中,节点1和节点2在同一个机架,节点3和节点4在另一个机架。我们假设图中名为 P 的分区最初被分配到节点1。
复制因子为3意味着我们需要将数据复制到另外两个节点上。数据复制在集群中顺时针进行,同时考虑服务器的机架分配。
由于节点1和节点2在同一个机架,Cassandra会尝试将下一个副本放在不同机架的节点上,即节点3。最后一个副本将放在节点4上。因为有两个副本放置在不同的机架,所以节点3和节点4在同一个机架不会成为问题。
现在,我们来看一个多数据中心环境的例子。这里有两个数据中心,我们的键空间复制因子为5。
与上一个例子类似,我们需要使用CQL创建键空间,再次指定 class 为 NetworkTopologyStrategy,并在数据中心级别指定复制因子:数据中心1为3,数据中心2为2。
我们假设图中名为 P 的分区最初被分配到数据中心1的节点1和数据中心2的节点5。
与上一个例子类似,在数据中心1,根据服务器的机架位置顺时针放置另外两个副本,因此节点3和节点4将获得分区 P 的副本。在我们的例子中,有两个数据中心,所以在完成第一个数据中心的副本放置后,Cassandra会转到下一个数据中心放置另外两个副本。由于分区 P 已经最初分配到数据中心2的节点5,我们现在只需要在数据中心2再放置一个副本。考虑到节点的机架位置,节点7被选为存放我们数据的第五个副本。这就是我们的五个副本最终分布在Cassandra集群节点上的方式。



修改与删除键空间
我们已经在本视频中看到了使用 CREATE KEYSPACE 的例子,现在让我们看看如何修改或删除一个键空间。
你可以使用CQL的 ALTER KEYSPACE 命令来修改现有的键空间,例如修改键空间的复制因子。




一个例子是,你可以通过将数据中心2的复制因子从2增加到3,从而将整体键空间复制因子从5增加到6。


你也可以使用CQL中的 DROP KEYSPACE 命令来删除或丢弃一个键空间,这将导致删除该键空间的所有表及其包含的数据。为了保护系统免受意外删除的影响,Cassandra默认会在执行删除操作之前对键空间进行快照。这意味着在需要时,你将能够恢复你的数据。
总结


本节课中我们一起学习了以下内容:
- 键空间在创建表之前定义,一个键空间可以包含任意数量的表。
- 复制在键空间级别指定。
- 数据复制依赖于复制因子和复制策略,两者均在键空间级别设置。
- 复制因子设置副本的数量。
- 复制策略决定副本将位于集群的哪些节点上。
- 常见的键空间操作是:创建键空间、修改键空间和删除键空间。
026:Apache Cassandra表操作


在本节课中,我们将学习Apache Cassandra中表的核心概念与操作方法。我们将了解表的角色、关键属性,并掌握如何创建、修改和删除表。
上一节我们介绍了键空间及其操作,本节中我们来看看Cassandra中数据存储的核心单元——表。


🗂️ Cassandra表的作用


Cassandra将数据存储在表中,表的模式定义了数据在集群和节点级别的存储方式。

🛠️ 创建表
创建表的通用语法如下:

CREATE TABLE [IF NOT EXISTS] keyspace_name.table_name (
column_name data_type [PRIMARY KEY],
...
) [WITH options];

以下是创建表时需要注意的几个关键点:
IF NOT EXISTS参数是可选的。如果尝试创建已存在的表,除非使用此选项,否则会返回错误。- 表名之前可以指定键空间名。如果未通过
USE keyspace语句指定当前键空间,则必须在此处指明。 - 列定义在表名后的括号内,多个列使用逗号分隔。
- 可以在列定义中通过
PRIMARY KEY参数指定该列为表的唯一主键。


如果主键由多个列组成,则需要在表定义的末尾声明。


静态表示例
我们来看一个课程中提过的 users 表的例子。这是一个静态表,意味着主键仅包含一个分区键列 username。
在这种情况下,有两种方式指定主键:

方式一: 在列定义中直接添加
CREATE TABLE users (
username text PRIMARY KEY,
email text
);

方式二: 在表定义末尾声明
CREATE TABLE users (
username text,
email text,
PRIMARY KEY (username)
);
两种方式创建的表是相同的。创建表后,可以使用 SELECT 语句查询,但由于尚未插入数据,查询结果将为空。
动态表示例


现在,让我们创建一个动态表。回顾课程中提过的 groups 表,动态表意味着主键由分区键和聚类键共同组成。
在这个例子中,分区键是 group_id,聚类键是 username。


CREATE TABLE groups (
group_id int,
username text,
group_name text STATIC,
PRIMARY KEY (group_id, username)
);
你可能注意到了 group_name 列定义中的 STATIC 子句。STATIC 用于定义分区内所有行共享的特殊单值列,也称为分区键的描述性列。静态列不能用作主键。
同样,对 groups 表使用 SELECT 语句也会得到空结果,因为我们尚未插入任何数据。
⚙️ 表的属性与描述
如果我们使用 DESCRIBE TABLE 命令,可以看到表的定义和属性。

以下是一些需要解释的新属性:



- 数据排序:默认情况下,分区内的数据按聚类键
username升序排列。可以使用WITH CLUSTERING ORDER BY参数来指定分区内数据的排序方式。 - 生存时间:
default_time_to_live意味着可以为表中的数据设置过期时间。例如,一个仅有效期五分钟的优惠。TTL也可以在操作级别设置,例如在INSERT语句中,这意味着只有该行数据会在TTL后过期。 - 数据刷盘:写入数据(如插入、更新、删除)会先从内存刷入磁盘,在三种情况下触发:
- 内存表已满时。
- 提交日志已满时。
- 达到特定时间间隔时。
memtable_flush_period_in_ms这个设置指的就是按表设置的、定期将数据刷入磁盘的时间间隔,默认为0,表示未激活。

本幻灯片展示的仅是Cassandra表属性和选项的一部分。其他如 gc_grace_seconds 和 compaction 等属性,我们将在下一节讨论数据如何持久化到磁盘以及Cassandra中删除操作的实现方式时再详细讲解。
🔄 修改表

与之前介绍的键空间类似,表也可以被修改。
你可以对表模式执行以下操作:
- 添加新列。
- 删除列。
- 重命名列(注意:此操作适用于常规列和聚类键,但不支持分区键)。
- 更改表属性。

请注意,虽然我们提到添加和删除列,但这些操作仅适用于常规列,不适用于主键列。



在Cassandra中,主键一旦定义就无法更改,因为它决定了数据在集群和节点级别的存储方式。如果想要更改,需要创建新表并重新导入数据。
不支持更改现有列的数据类型。
🗑️ 删除表
可以使用 TRUNCATE 或 DROP 命令删除表。
TRUNCATE:移除指定表中的所有数据,但保留表的定义模式。需要注意,TRUNCATE命令要求ALL一致性级别,即所有副本都必须可用。DROP:移除所有数据以及表的定义模式。
在执行截断或删除操作之前,Cassandra会为数据创建快照作为备份。
📝 总结



本节课中我们一起学习了以下内容:

- Cassandra中的数据在逻辑上组织在表中。
- 表的元数据指定了主键,指示Cassandra如何在集群级别和节点级别分布表数据。
- 可以在表级别添加生存时间参数,这意味着可以令超过TTL的所有数据过期或删除。
- 可以修改列和列名,但仅限常规列。在创建表时定义的主键一旦确定就无法修改。
- 可以通过
DROP命令删除表,或使用TRUNCATE命令清空其数据。
027:CRUD操作 第1部分


在本节课中,我们将学习Apache Cassandra数据库中的写入操作,具体聚焦于如何插入和更新数据。CRUD是创建、读取、更新和删除的缩写,本节课将涵盖前两个核心操作。



🖥️ 集群与节点级别的写入过程
在深入了解Cassandra的写入语法之前,我们先来看看在集群和节点级别,一次写入是如何完成的。

集群级别的写入


在集群级别,当发生写入时,接收写入请求的节点将成为该操作的协调器。这意味着它将确保操作完成,并将写入结果返回给用户。
写入操作会定向到它们要写入的分区的所有副本。但为了使操作成功,至少需要从满足一致性级别要求的最少节点数那里收到确认。


让我们以一个键空间复制因子为3,写入操作一致性级别设置为2的例子来说明。假设我们的分区位于节点1、2和3。在这种情况下,写入操作到达节点4,节点4根据复制因子将写入发送到节点1、2和3。然而,节点2不可用,因此只有节点1和3发送了写入确认。

协调器节点4检查确认响应的数量,并将其与预期的一致性值进行比较,然后返回操作成功的信号。
节点级别的写入
在节点级别,有几个重要的事实需要记住。
关于Cassandra写入的一个重要提醒是:默认情况下,在执行写入操作之前不会进行读取。
在节点级别,写入首先存储在内存中,然后刷新到磁盘上称为SSTable的文件中。我们执行的写入越多,内存表填充得越快,数据也就越快被刷新到磁盘。每次刷新操作都会创建一个新的SSTable文件。

在磁盘上,数据被追加到后续的SSTable中。之后,数据会通过一个称为“压缩”的过程在磁盘上进行优化。Cassandra为每个写入操作附加一个时间戳。时间戳用于数据协调,最新的数据胜出。

✍️ 插入操作详解
以下是关于Cassandra插入操作的一些基本事实:
- 完整主键:插入操作要求指定完整的主键。这意味着插入只能逐条记录进行。
- 插入即更新:由于Cassandra默认在写入前不执行读取,插入操作同时具有插入和更新的行为。如果我们向已存在的条目插入数据,那么数据将被更新。
- 列值要求:插入操作要求为所有主键列提供值,但对于表定义中指定的其他常规列则不是必须的。只有指定的列会被填充数据。
- 生存时间:你可以为插入的数据指定一个特定的生存时间,就像我们在表级别所做的那样。现在我们可以在记录级别这样做,这意味着数据只在定义的时间内可见。
让我们基于示例数据看几个例子。在粗体字中,你可以看到主键的列。
我们可以向表中插入新数据。在这个例子中,我们指定了表的所有列。我们向第12组(烘焙组)插入了两个用户。
INSERT INTO users_by_group (group_id, user_id, group_name, user_age) VALUES (12, 101, 'Baking', 30);
INSERT INTO users_by_group (group_id, user_id, group_name, user_age) VALUES (12, 102, 'Baking', 28);
插入数据时,主键是强制性的,你不能在不完全指定主键的情况下插入数据。如本例所示,我们向第45组插入一个新用户,只添加了必需的信息。既没有添加组名,也没有添加用户的年龄。
INSERT INTO users_by_group (group_id, user_id) VALUES (45, 201);
我们还可以插入带有生存时间的数据。在这种情况下,我们向第25组(纯素烹饪组)添加了一个新用户,TTL为10秒。这意味着从插入起10秒后,该数据将不再可供查询。


INSERT INTO users_by_group (group_id, user_id, group_name, user_age) VALUES (25, 301, 'Vegan Cooking', 35) USING TTL 10;


当对现有数据进行插入时,我们可以将插入用作更新。在这种情况下,第12组中用户的年龄将被更新为45。
INSERT INTO users_by_group (group_id, user_id, user_age) VALUES (12, 101, 45);
如果对我们的表执行查询,在所有插入操作之后,结果将如下所示。这是一个CQLSH的数据视图,所以不要被空值误导。在这种情况下,它意味着这些单元格没有数据。


🔄 更新操作详解
现在让我们对数据进行两次更新。
我们可以更新第45组的名称,因为它是一个静态列。我们可以仅使用分区键来更新它。这是更新命令不需要提及完整主键的唯一情况。
UPDATE users_by_group SET group_name = 'New Group Name' WHERE group_id = 45;
我们也可以更新现有记录。在这种情况下,我们将更新第12组中一个用户的年龄。

UPDATE users_by_group SET user_age = 50 WHERE group_id = 12 AND user_id = 101;
我们可以在一个不存在的条目上调用更新命令,在这种情况下,更新将表现为插入操作。
UPDATE users_by_group SET group_name = 'Hiking', user_age = 40 WHERE group_id = 99 AND user_id = 401;


此时,让我们看看对表进行查询会得到什么结果。




⚖️ 轻量级事务

正如你所见,插入和更新的行为可能非常相似,因为默认情况下,Cassandra在执行写入之前不会定位和读取数据。然而,可以指示Cassandra查找数据、读取它,然后才执行给定的操作,这是通过轻量级事务实现的。

语法上,轻量级事务通过在INSERT和UPDATE语句中引入IF条件来支持。

让我们看一些例子。
我们可以仅在记录存在的情况下更新组中用户的年龄。
UPDATE users_by_group SET user_age = 55 WHERE group_id = 12 AND user_id = 101 IF EXISTS;
我们可以仅在记录存在且年龄为某个特定值的情况下更新组中用户的年龄。
UPDATE users_by_group SET user_age = 60 WHERE group_id = 12 AND user_id = 102 IF user_age = 28;

我们可以仅在数据不存在的情况下向Cassandra表插入数据。在我们的例子中,记录已存在,因此不会执行插入。
INSERT INTO users_by_group (group_id, user_id, group_name, user_age) VALUES (12, 101, 'Baking', 30) IF NOT EXISTS;

轻量级事务比Cassandra中的普通插入和更新至少慢四倍,你需要在应用程序中谨慎使用它们。
📝 课程总结
在本节课中,我们一起学习了以下核心内容:

- 默认情况下,Cassandra在写入前不执行读取,因此插入和更新操作行为相似。
- 轻量级事务可用于强制执行“先读后写”,但由于会导致性能下降,应谨慎使用。
- 在集群级别,写入被发送到所有分区副本,与一致性因子无关。为了使操作成功,至少需要从满足一致性级别要求的最少节点数那里收到确认。
028:CRUD操作第二部分


在本节课中,我们将学习如何在Apache Cassandra中进行数据的读取和删除操作。CRUD是创建、读取、更新和删除的缩写,本节课将重点讲解后两部分。
🔍 Cassandra中的读取操作
上一节我们介绍了如何向Cassandra插入数据,本节中我们来看看如何读取数据。
当读取操作被发送到集群中的一个节点时,该节点会成为此次读取操作的协调器,并负责完成该操作。在我们的示例中,节点4是此次读取的协调器。
读取请求只会被发送到由一致性级别设置所指定数量的副本节点。例如,一致性级别为2意味着三个副本节点中只有两个会被联系。
协调器会协调从被联系节点收到的响应。如果存在任何不一致,将根据操作的时间戳来解决。然后,结果将被返回。

在语法上,Cassandra和许多数据库一样,使用SELECT操作来执行读取。
以下是关于Cassandra中SELECT操作的一些重要规则:
- 始终以分区键开始查询:这可以将读取范围限制在仅包含你所需分区的副本节点上。
- 遵循主键字段的顺序:在查询中遵循主键字段的顺序可以获得最佳性能。
例如,如果你的主键由一个分区键和两个聚类键组成:
- 筛选分区键的特定值是可行的。
- 筛选分区键的可能值列表也是可行的。
- 筛选分区键和第一个聚类键是可行的。
- 筛选分区键以及第一和第二个聚类键将只读取一条记录,这也是可行的。
然而,在生产系统中,从表中选取所有数据是不可取的,因为这会将请求发送到集群中的所有节点。想象一下,一个拥有1000个节点的集群,你的查询性能会令人满意吗?查询虽然能执行,但性能会非常差,即使没有发生超时。
筛选常规列是不可行的,并且不会生效。
最后,在没有分区键的情况下筛选聚类键也是不可行的,并且不会生效。
让我们看一些基于groups表的例子,该表的主键由group_id和username列组成:
- 筛选
group_id或group_id和username将生效,并且性能非常好。 - 筛选常规列
age将不会生效。Cassandra会返回一个错误。在这种情况下,你可以选择重新设计表结构,或者在age列上创建索引,这样SELECT查询就能生效了。

但是,虽然之前的查询会生效,但最佳性能是通过将age列与特定的分区键group_id一起筛选来获得的。这样做可以将查询限制在仅托管该分区键的节点上,这再次引出了Cassandra这条非常重要的规则:始终以分区键开始你的查询。

🗑️ Cassandra中的删除操作
我们接下来演示一些删除操作。在Cassandra中,你可以删除由完整主键标识的条目,也可以删除由完整主键标识的条目中的某个单元格。
如果我们执行一个SELECT查询,可以看到名为Elaine的用户已经不存在了,并且名为Allen的用户的age单元格已被删除。
删除也可以在分区级别进行。如果你的分区键是sensor_id,并且数据是按记录时间聚类的,你可以删除一个分区内某个连续范围的数据。例如,你可以删除某个传感器在下午1点到3点之间的所有记录,或者删除由分区键标识的整个分区。
我们已经看到了删除数据的语法,但在Cassandra中,你应该谨慎使用删除操作,因为它们的使用会极大地影响系统性能。

从像Apache Cassandra这样的分布式和复制系统中删除数据,比在关系型数据库中要复杂得多。特别是要记住,Cassandra是一种对等架构,读写操作可以定向到集群中的任何节点,因此没有专门用于写入或读取的主节点。
在这样的系统中,为了记录删除发生的事实,需要写入一个称为墓碑的特殊值,作为指示先前值应被视为已删除的标记。
从某个条目被标记为墓碑的那一刻起,它的数据对查询就不再可见。然而,实际数据仍会在磁盘上保留一段时间。
什么是墓碑?
在Cassandra中,删除操作就是一种写入操作,它附加了一个特殊值,用于指示数据已被删除以及删除的时间。这个值就叫做墓碑。
如图所示,我们的删除操作被节点1和节点3确认。现在我们有了一个墓碑,指示我们特定的主键数据在时间T1被删除。节点2的数据是初始的,在时间T0插入的数据。由于删除操作在节点2上没有成功。
现在,当一个读取操作到达时,数据将由节点1和节点2返回。节点1将返回时间为T1的“无数据”,节点2将返回时间为T0的请求数据。由于T1比T0更新,协调器节点(节点1)将决定最新的数据来自节点1,并作为读取结果返回“无数据”。
另一件需要记住的事情是,墓碑只有在经过一个可配置的时间段后才会被删除。这个时间段称为GC宽限期秒数,默认设置为10天,并在表级别进行设置。
📝 课程总结
本节课中我们一起学习了:
- 在集群级别,读取操作只会根据一致性设置发送给指定数量的副本节点。
- 为了获得最佳性能,读取操作应遵循主键列的顺序。
- 删除操作可以在记录、单元格、范围和分区级别进行。


通过理解这些核心的读写和删除机制,你将能更有效地在Cassandra中管理和操作数据。
029:IBM Cloudant 概述 🗄️


在本节课中,我们将学习IBM Cloudant的基本概念、核心特性以及如何访问它。IBM Cloudant是一个为现代应用设计的托管数据库服务。


概述
IBM Cloudant是一个完全托管的数据库服务,也称为数据库即服务。它基于开源的Apache CouchDB构建,为混合云和多云应用提供数据层支持。

核心特性


上一节我们介绍了Cloudant的基本定位,本节中我们来看看它的关键特性。
Cloudant旨在成为所有Web和移动应用的数据层,它使用简单但功能丰富。

以下是Cloudant的一些核心能力:

- 内置高级功能:Cloudant集成了在线分析、全文搜索、高级地理空间查询和复制功能,无需第三方集成。
- 灵活模式:Cloudant使用灵活的模式,这意味着您可以快速迭代新功能,实现敏捷开发。
- 分布式与高性能:Cloudant是一个分布式数据库,针对处理Web、移动、物联网和无服务器应用特有的大规模、快速增长的工作负载进行了优化。
- 完全托管服务:作为一项有服务等级协议保障的数据库即服务,它没有管理开销。IBM的专家提供全天候的安全托管、监控和维护。
复制与兼容性
了解了核心特性后,我们来看看Cloudant强大的数据同步与生态系统兼容性。
Cloudant的复制技术提供了降低可扩展性风险、成本和干扰的选项。其强大的复制协议和API与Apache CouchDB等开源生态系统兼容,也与主流移动和Web开发栈的开源库兼容。
由于Cloudant和CouchDB共享通用的复制协议,开发者可以轻松地将云端数据同步到本地的CouchDB实例。
其他关键能力
除了复制,Cloudant还提供其他关键能力以支持复杂应用场景。
以下是这些能力的简要说明:
- 搜索:Cloudant Search基于Apache Lucene实现,提供快速、简单的搜索功能。
- 地理空间查询:Cloudant Geospatial支持对编码的地理数据结构进行内置空间查询和地图可视化。
- 离线优先:结合Cloudant Sync的“离线优先”能力支持移动数据同步,允许用户离线使用本地存储的数据,之后再将数据同步到云端数据库。
- 多语言支持:您可以使用特定的语言库或封装器来开发应用,这些工具帮助您更便捷地使用API。
如何访问IBM Cloudant


最后,我们来了解如何开始使用IBM Cloudant。

访问Cloudant托管服务非常简单。您只需登录IBM Cloud,在顶部导航栏点击“目录”,选择“服务”,然后从类别列表中选择“数据库”,最后在数据库服务列表中选择“Cloudant”。
或者,您也可以直接访问 ibm.com/cloud/cloudant 注册免费试用。此外,您还可以下载Cloudant进行本地安装。


总结
本节课中我们一起学习了IBM Cloudant。它是一个基于Apache CouchDB构建的完全托管数据库即服务,使用JSON文档存储。作为一个分布式数据库,它针对Web、移动、物联网和无服务器应用的大规模工作负载进行了优化。

作为一项有SLA保障的DBaaS,它意味着没有管理开销,您的数据库被安全地托管在云端。Cloudant提供了强大的复制协议和API,与许多开源生态系统和库兼容。它提供了搜索、地理空间查询、离线移动访问以及多语言库支持等功能,并且非常易于访问和使用。
030:IBM Cloudant 架构与关键技术 🏗️💡



在本节课中,我们将学习IBM Cloudant的云架构及其提供的核心技术组件。我们将了解其全球数据部署、高可用性设计、离线同步能力以及内置的强大功能。

概述
IBM Cloudant是一个基于文档的NoSQL数据库服务。它提供了全球化的数据部署、高可用性架构以及多项关键技术,旨在支持现代Web和移动应用开发。
IBM Cloudant的云架构 🌐




上一节我们介绍了NoSQL数据库的基本概念,本节中我们来看看IBM Cloudant背后的具体云架构。

IBM Cloudant的架构设计旨在提供全球数据存在、高可用性和最优性能。
以下是其架构的关键特点:
- 全球数据部署:您可以将数据托管在全球超过55个不同的数据中心。
- 云平台无关性:Cloudant支持IBM Cloud、IBM基础设施即服务、Rackspace、Microsoft Azure和Amazon Web Services等多个云平台。
- 数据复制与完整性:Cloudant拥有稳健且易用的复制协议,确保数据永不损坏,并提供最佳的数据可用性。数据在数据中心之间复制,实现全球可用。
- 集群与高可用性:所有Cloudant实例都部署在跨越区域可用区的集群上,以增强持久性,且不向组织收取额外费用。如果一个数据中心离线,请求将被路由到另一个活跃的数据中心,从而提供高可用性、灾难恢复以及最优性能。
- 智能请求路由:用户请求根据网络延迟(ping时间)被路由到最快的数据中心,而不仅仅是地理上最近的数据中心。


关键技术组件 ⚙️

了解了其全球架构后,我们来看看IBM Cloudant提供的具体技术组件,这些组件使其成为一个强大的操作型数据存储。
作为操作型数据存储
Cloudant非常适合任何Web或移动应用程序。它是一个基于文档的NoSQL数据库,并非像Hadoop那样的数据仓库。

HTTP API

Cloudant使用一个简单且定义良好的HTTP API,其工作方式类似于RESTful Web服务。它旨在融入现代架构,并能无缝集成到面向服务的架构中,无需构建抽象层。您可以在您选择的云中部署数据库。
代码示例:通过HTTP API交互
您可以通过浏览器或curl命令与数据交互,返回JSON格式的数据。
curl https://<your-account>.cloudant.com/<database>/<document-id>
数据索引与处理

Cloudant提供了多种不同的方式来索引和处理数据。

- MapReduce:这是一种高效处理大型数据集的方式,非常适合进行实时分析。
- 全文搜索:搜索引擎功能非常受Web和移动应用开发者的欢迎。许多应用程序在底层进行异步调用,以对数据进行全文即席搜索。与其他需要集成第三方搜索引擎(如基于Lucene的Elasticsearch或Apache Solr)的数据库服务不同,Cloudant在数据库服务(包括本地部署版本)中完全内置了全文搜索功能。
- 地理空间(Geospatial):此功能非常适合涉及石油、天然气或运输(例如卫星和运输车辆)的应用程序。
复制与同步

Cloudant拥有完全集成的复制和同步功能。对于需要离线同步的Web和移动应用程序(例如离线填写费用报告或销售订单),Cloudant使用与浏览器中现有通用库或Cloudant提供的库兼容的复制协议。离线同步技术使开发人员能够构建iOS和Android应用程序,允许用户连接互联网并复制数据以供离线使用,在离线时更新数据,并在重新上线时同步数据。




安全性 🔒

在安全性方面,IBM Cloudant符合ISO 27001、SOC2 Type2标准,并支持HIPAA。所有数据都经过加密,无论是静态数据还是在网络中传输的数据。此外,还通过IBM Key Protect提供可选的用户自定义加密密钥管理服务。该服务与IBM身份和访问管理集成,可在API级别进行精细的访问控制。

部署模式


IBM Cloudant可以作为完全托管服务、本地部署版本或混合云部署提供。

管理仪表板

IBM Cloudant仪表板提供了一种简单的方法来监控、管理和开发您的数据库。


总结
本节课中,我们一起学习了IBM Cloudant的核心架构与关键技术。

我们了解到:
- IBM Cloudant通过全球超过55个数据中心提供分布式数据服务。
- 它支持多个云平台,其云架构提供了高可用性、灾难恢复和最优性能。
- Cloudant为Web和移动应用程序提供了离线同步能力。
- 它可以作为完全托管服务、本地部署或混合云部署提供。
- Cloudant包含多个关键技术组件,如定义良好的HTTP API、MapReduce、全文搜索和地理空间功能,以及一个用于监控、管理和开发NoSQL数据库的集成仪表板。
031:Cloudant 优势与解决方案



在本节课中,我们将学习IBM Cloudant的核心优势、它能解决的数据挑战以及典型的应用场景。学完本课后,你将能够描述IBM Cloudant的关键优势,解释它能应对的挑战,并了解其常见的用例。

🚀 IBM Cloudant的关键优势

IBM Cloudant作为一个托管的NoSQL数据库服务,提供了多项关键优势,使其成为现代应用开发的理想选择。


1. 卓越的可扩展性
Cloudant能够实现极高程度的扩展,无论是数据规模还是支持的并发用户数。它适用于初创公司处理1GB数据和10个并发用户的应用,也同样适用于拥有多个应用、存储PB级数据并支持2000万并发活跃用户的企业级组织。Cloudant允许根据需求灵活地向上或向下扩展。
2. 持续可用性
Cloudant是一个为在线应用设计的运营数据存储。构建一个旨在实现365天、24/7不间断可用的服务是必须的,而Cloudant正是为此而生。

3. 数据持久性与分区容错性
Cloudant致力于永不丢失数据。它通过在独立的物理节点上存储数据的多个副本来实现这一目标。为了满足最严格的高可用性和灾难恢复要求,Cloudant具备分区容错性,能够处理集群中的节点故障,甚至是整个数据中心的中断。
4. 在线升级与离线访问
Cloudant经过独特设计,可以在运行中进行补丁或升级,无需停机。集群可以在不使客户数据库离线的情况下完成升级。此外,它提供在线和离线访问功能,这对于在连接不稳定的场景(例如偏远地区或飞机上)中尤为理想。





🛠️ Cloudant解决的数据挑战
许多客户依赖Cloudant来解决数据层的各种挑战。以下是它能够应对的几个核心问题:


- 关系型数据库扩展困难:如果你的关系型数据库无法按预期扩展,Cloudant可以轻松应对指数级增长的用户群。
- 自建数据库成本高昂:在预算、时间和运维技能有限的情况下,自行开发和托管数据库被证明是一项挑战。Cloudant有助于降低这些成本。
- 应用开发初期需求不明确:有时你可能在尚未完全明确容量需求的情况下从头开始构建应用。Cloudant为应用开发提供了一种简单快捷的方式。

🗃️ Cloudant的文档数据库架构

上一节我们了解了Cloudant能解决的挑战,本节中我们来看看它的核心数据模型。

Cloudant使用文档数据库。一个文档数据库是具有单一访问权限集的文档的逻辑集合。在Cloudant中,文档以流行的JSON格式存储,并采用灵活的Schema。
文档被组织到数据库中,主要有两个原因:
- 安全访问控制:你可以在数据库级别应用访问角色(如读、写、管理、复制)。
- 查询效率:你无法通过单个API调用跨数据库进行索引或查询。
你的集群可以容纳任意数量的数据库。
⚙️ Cloudant的集群与高可用性机制
了解了数据模型后,我们进一步探讨Cloudant如何通过集群架构实现高可用性。
当你注册Cloudant账户时,会有实际的物理服务器为你工作。Cloudant运行在由负载均衡器和数据库节点组成的服务器集群上。

以下是其核心工作机制:





- 水平可扩展与自动分片:Cloudant是水平可扩展的,意味着你可以将数据库分布在集群中。它会自动将数据分片(
autoshards)并均匀分布在集群节点上,无需像关系型数据存储那样手动分发数据。 - 灵活的容量规划:你可以从少量节点开始,随着数据增长,让Cloudant运行脚本来管理数据以保持其可用性。这意味着你无需提前进行大量容量规划,因为Cloudant可以轻松适应你不断增长的数据需求并保持性能。
- 数据复制与仲裁集群:数据在集群内的服务器之间复制以保持同步,无需管理干预。Cloudant采用仲裁式集群,将每个JSON文档存储三份副本,分别放在三个独立的物理节点上。
- 负载均衡与故障恢复:当你的应用读写数据时,Cloudant使用负载均衡器将读写请求均匀分布在集群中。因此,如果一个节点发生故障,数据仍然可以在另一个节点上可用。




💡 Cloudant的典型用例



基于上述优势与架构,Cloudant在多个领域都有广泛应用。


以下是几个典型的应用场景:

- 构建Web和移动应用:例如,可以使用分析功能构建销售点移动应用,以个性化购物体验。
- 创建强大的认知AI应用:通过将IBM Watson机器学习连接到存储在Cloudant中的数据来实现。
- 分析物联网传感器数据:利用Cloudant灵活的Schema来存储物联网传感器数据,以追踪端到端的货物运输并检测异常。


📝 课程总结
本节课中,我们一起学习了IBM Cloudant的核心知识。


我们了解到IBM Cloudant的关键优势在于其可扩展性、可用性、持久性、分区容错性以及在线升级和打补丁的能力。它能解决指数级用户增长、成本上升以及内部开发、托管和管理数据库所需的时间和技能等数据挑战。Cloudant使用文档数据库来提升安全性和查询效率,并运行在云端的集群服务器上。其典型用例包括构建Web和移动应用、AI解决方案以及分析物联网传感器数据。
032:IBM Cloudant 部署选项详解

在本节课中,我们将学习IBM Cloudant数据库服务的不同部署方案。我们将详细介绍免费版、标准版和专用硬件版三种计划,帮助你根据不同的应用场景和需求,选择最合适的部署方式。


🆓 免费版计划
上一节我们了解了Cloudant的三种主要部署计划,本节中我们首先来看看免费版计划。


免费版计划,也称为“轻量版”计划,适用于评估、原型设计和开发阶段。注册此计划无需信用卡,且没有时间限制。
以下是免费版计划的核心特点:
- 功能完整:提供IBM Cloudant的全部功能,用于评估和开发。
- 固定资源限制:
- 吞吐量容量固定为:每秒20次读取、每秒10次写入、每秒5次全局查询。
- 单个JSON文档的最大尺寸限制为1 MB。
- 服务保留策略:如果您的轻量版环境连续30天处于非活动状态,相关服务将被删除。
💼 标准版计划
了解了适用于开发测试的免费版后,我们来看看面向生产环境的部署选项。如果您的组织需要一个完全托管且可配置的数据库即服务生产部署,可以选择Cloudant标准版计划。
标准版计划提供无服务器扩展的吞吐量和数据存储能力,您可以根据应用程序需求的变化进行配置。
以下是标准版计划的核心特点:
- 弹性扩展:您可以按需增加吞吐量块。每个块包含:
- 每秒100次读取
- 每秒50次写入
- 每秒5次全局查询
- 按小时计费:
- 费用基于分配的吞吐量容量(
provisioned_throughput_capacity)计算,而非实际处理的读写请求量。 - 包含20 GB的免费数据存储空间,超出部分按定义的每GB每小时费率计费(
additional_storage_cost_per_gb_per_hour)。
- 费用基于分配的吞吐量容量(

🔒 专用硬件版计划

标准版计划提供了灵活的云上生产部署,但如果您的组织需求需要为完全托管的数据库即服务生产部署提供裸机专用环境,则应选择Cloudant专用硬件版计划。
专用硬件版计划是标准版计划的一个可选附加项,用于在其上运行一个或多个标准版实例。
以下是专用硬件版计划的核心特点:
- 专属环境:IBM在您选择的IBM Cloud、Rackspace、Amazon或Azure数据中心内,于专用的单租户集群上设置您的Cloudant账户。
- 优势:受益于硬件隔离、更高的安全性和更好的合规性。
- 网络与安全:
- 除公共端点外,还包含私有端点。
- 提供IP白名单功能。
- 计费方式:
- 作为周期性月费收取,费用基于集群中的服务器数量(
monthly_fee_per_server)。 - 此固定费用附加于部署在其上的标准版实例的消费定价。
- 采用每日按比例计费,并有一个月的最低时长收费。
- 作为周期性月费收取,费用基于集群中的服务器数量(
- 合规性:该计划在所有IBM Cloud位置可用。位于美国的客户还可以选择符合HIPAA标准的配置,以提升合规性。

📝 课程总结
本节课中,我们一起学习了IBM Cloudant的三种主要云部署方案。
- 免费版计划适用于评估和开发环境,但提供的吞吐量容量和数据存储有限。
- 标准版计划在按小时计费的基础上,提供无服务器扩展的吞吐量和数据存储。定价基于分配的吞吐量容量和存储的数据量。
- 专用硬件版计划建立在专用的单租户集群上,是一个可选附加项,用于运行您的一个或多个标准版实例,提供一个隔离且安全的专用环境。


通过理解这些选项,您可以根据项目的具体阶段(开发、测试、生产)以及对性能、安全性和成本的要求,做出明智的部署决策。
033:Cloudant中的仪表板 📊



在本节课中,我们将学习如何访问和使用Cloudant的仪表板。这是一个集中式的管理界面,用于创建和管理数据库、配置复制、查看活动任务以及监控实例的运行状况和资源消耗。
访问Cloudant仪表板





上一节我们介绍了Cloudant的基本概念,本节中我们来看看如何进入其管理界面。

注册并登录免费的Cloudant账户后,系统会将您引导至IBM Cloud仪表板中的资源列表。在资源列表中,展开服务列表并选择您的Cloudant服务实例名称。在管理选项卡中,选择“启动仪表板”以打开您的Cloudant仪表板。


仪表板功能概述
Cloudant仪表板是一个集中式的管理界面,它使您能够执行以下核心操作:
- 创建和管理数据库。
- 配置复制。
- 查看活动任务。
- 监控当前操作、被拒绝的请求和存储消耗。

数据库管理



以下是您可以在仪表板的“数据库”选项卡中执行的主要操作:
- 创建数据库:建立新的数据库。
- 添加文档:向数据库中插入JSON文档。
- 复制数据库:配置数据库的复制任务。
- 配置权限:设置数据库的访问控制。
- 删除数据库:移除不再需要的数据库。
- 运行查询:对数据库中的文档执行查询操作。
配置复制






您可以使用仪表板的“复制”选项卡来配置源数据库和目标数据库之间的复制。执行复制操作时,它会将源数据库的所有更改复制到目标数据库。例如,如果在复制完成后向源数据库添加或删除了一个文档,该文档也会在目标数据库中被添加或删除。
配置复制时,需要指定几个关键元素,例如源数据库和目标数据库、连接使用的身份验证以及复制类型。
复制类型分为两种:
- 一次性复制:复制在配置完成后立即发生一次,之后不会持续复制。这是默认的复制设置。
- 连续复制:源数据库中的更改会持续复制到目标数据库,直到您明确决定取消复制。
公式表示复制关系: Target_Database(t+1) = Source_Database(t) + Δ,其中Δ代表在时间t内发生的更改。
复制可能对Cloudant实例的性能产生巨大影响,因此建议进行某种形式的性能测试,以识别对环境的潜在影响。此外,如果配置了连续复制,这种潜在影响将是持续存在的。执行连续复制所需的额外系统调用可能会增加运行IBM Cloudant多租户实例的组织的成本。这就是默认不启用连续复制的原因。

复制开始后,您可以使用“刷新”来更新状态,以识别复制何时完成。返回“数据库”选项卡时,您将在列表中看到任何已复制的数据库。




监控活动与性能
您可以使用Cloudant仪表板的“活动任务”选项卡来显示当前正在运行的任何任务的列表,这可能有助于您确定系统性能可能存在的问题。活动任务列表包括复制、压缩和索引过程。




仪表板的“监控”选项卡用于查看Cloudant实例中应用程序当前消耗的预配置吞吐容量和数据存储。


在监控部分可用的三个选项卡中,您可以监控以下内容:
当前操作
这些图表以分钟为单位显示您预配置吞吐容量的消耗情况。该吞吐容量分为:
- 每秒读取次数
- 每秒写入次数
- 每秒全局查询次数

虚线表示您的Cloudant实例允许的峰值容量限制。

在动手实验中使用轻量计划时,您在此页面的图表中将看不到任何数据。

被拒绝的请求
这些图表以分钟为单位监控收到的“被拒绝的请求”响应。这些响应以429 Too Many Requests消息的形式生成,当超过Cloudant实例的预配置吞吐容量限制时会发生。



与“当前操作”选项卡类似,这些被拒绝的请求也分为每秒读取、每秒写入和每秒全局查询。


存储
存储图表以颜色编码的每日记录形式,显示Cloudant实例四个元素当前使用的存储容量,即地理空间索引、搜索索引、视图和数据库。


您可以选择图表上方的每个彩色条来切换每个元素的显示。您可以使用这些图表中显示的信息来确定实例中某个元素的容量何时即将达到上限,以便在需要时修改容量设置。

课程总结
本节课中我们一起学习了如何使用Cloudant仪表板来创建和管理数据库、配置复制、查看活动任务以及监控Cloudant实例。

- 您使用仪表板的数据库部分来创建数据库、向数据库添加文档、复制数据库、配置数据库权限、删除数据库以及对数据库中的文档运行查询。
- 您使用仪表板的复制部分来配置源数据库和目标数据库之间的复制。
- 您使用仪表板的查看活动任务部分来查看当前正在运行的任务列表,以帮助您确定系统性能方面的问题。
- 最后,您使用仪表板的监控部分来查看Cloudant实例中当前正在使用的预配置吞吐容量和数据存储的消耗情况。
034:在Cloudant中使用数据库



在本节课中,我们将学习如何在IBM Cloudant中创建和使用数据库。我们将了解分区数据库与非分区数据库的区别,掌握创建数据库的方法,并学习如何对Cloudant数据库中的文档进行插入、查看、查询、更新和删除操作。
🗂️ 数据库类型:分区与非分区
在IBM Cloudant中,您可以创建和使用两种类型的数据库:非分区数据库和分区数据库。
上一节我们介绍了课程概述,本节中我们来看看这两种数据库的核心区别。



非分区数据库
非分区数据库是一种较早期的Cloudant数据库类型,也用于早期版本的IBM Cloudant和CouchDB。在这种数据库中,无需定义分区方案,因此使用起来相对简单。
然而,非分区数据库只支持全局查询。
在非分区数据库中,文档会根据其文档ID的转换结果,随机分布到不同的分片上。因此,文档ID与其最终所在的分片之间没有实际关联。实际上,具有相似文档ID的文档不太可能位于同一个分片上。

分区数据库


分区数据库则同时支持分区查询和全局查询,并能提供显著的性能和成本优势。


分区查询利用了数据库集群内的数据布局,从而提供更好、更具扩展性的查询性能。分区查询通常也比全局查询成本更低。

分区数据库是Cloudant中较新的数据库类型,但它要求您为数据指定逻辑分区。分区数据库中的每个文档都需要一个分区键。分区是文档的逻辑分组,所有文档都被分配到一个分区中,通常多个文档会共享相同的分区键。
如果您的数据模型允许对文档进行逻辑分区,强烈建议您使用分区数据库,以获得最佳的长期性能。
需要注意的是,无法更改现有数据库的分区类型。
🛠️ 创建数据库


您可以在Cloudant仪表板的“数据库”选项卡中创建新数据库。
以下是创建数据库的步骤:
- 选择创建新数据库。
- 必须选择数据库是分区还是非分区。
- 这是创建数据库前唯一需要配置的选项。

已创建的数据库会显示在数据库仪表板选项卡上。列表会显示名称信息、每个数据库的大小、每个数据库包含的文档数量以及数据库是否为分区数据库。
📄 Cloudant文档的特性

许多其他数据库系统将数据存储在表中,数据包含在行中,每行都有相同的固定列,并且每个表的模式是预定义的。需要仔细定义列名、数据类型、值约束以及与其他表的关系的列表。
但在Cloudant中,情况则大不相同。我们已经讨论过,Cloudant是一种使用JSON文档存储的文档数据库。因此,您的Cloudant实例拥有称为“数据库”的集合,而不是“表”,每个数据库将包含许多文档。
一个Cloudant文档必须是一个JSON对象,它必须以花括号 {} 开始和结束,并包含许多键值对属性。

JSON对象必须小于1MB,并且可以包含任意数量的字符串、数字、布尔值、数组和嵌套对象。



📝 文档的基本操作
上一节我们介绍了Cloudant文档的结构,本节中我们来看看如何对文档进行增删改查。
插入文档


您可以在Cloudant仪表板中选定数据库的详细信息页面上,将文档插入数据库。
插入文档时,需要使用起始和结束花括号 {},并且需要使用系统提供的 _id 或提供您自己的自定义 _id。Cloudant使用 _id 键来唯一标识一个文档,它相当于关系数据库中的主键。
然后,您可以通过在花括号之间手动输入或从其他来源粘贴来填充文档详细信息,最后创建文档以将其插入数据库。
查看文档
当您选择一个数据库时,可以通过三种不同的视图查看其中包含的文档。

元数据视图:这是将文档插入数据库后的默认视图,此视图显示每个文档的ID、键和值信息。


表格视图:显示数据库中每个文档的数据表信息。例如,在此示例中,我们可以看到ID、卧室数量、价格和平方英尺的表格数据。


JSON视图:以JSON格式显示文档的内容。您也可以从这里编辑JSON文档。


查询文档
您可以对数据库中的文档运行查询。在查询窗口中输入查询语句,然后运行查询即可。


更新文档

您可以更新数据库中文档的数据。只需选择一个文档,进行所需的更改,然后保存更改。

删除文档
您也可以使用Cloudant仪表板从数据库中删除文档。只需选择文档,将其删除,并确认删除操作即可。


🎯 课程总结
本节课中,我们一起学习了在IBM Cloudant中使用数据库的核心知识。
我们了解到,在IBM Cloudant中可以创建和使用两种类型的数据库:非分区数据库和分区数据库。非分区数据库无需定义分区方案,但只提供全局查询。分区数据库则同时提供分区查询和全局查询,并能提供显著的性能和成本优势。数据库的分区类型在创建时设定。
Cloudant是一个使用JSON文档存储的文档数据库系统。您可以使用Cloudant仪表板创建数据库,并利用它来对数据库中的文档进行插入、查看、查询、更新和删除操作。
035:HTTP API基础知识 🌐





在本节课中,我们将学习HTTP API的基础知识,了解什么是cURL工具,并学习如何使用简单的cURL命令与Cloudant数据库进行交互。


概述
在前面的视频和实验中,你学习了如何使用Cloudant仪表板执行基本的CRUD操作,即如何在Cloudant数据库中创建、读取、更新和删除数据。


Cloudant仪表板本身是一个基于Web的应用程序,它通过超文本传输协议(HTTP)调用Cloudant的应用编程接口(API)。由于Cloudant数据库拥有HTTP API,它们具备一个显著优势:任何想要从中读取或写入数据的互联网设备都可以通过使用标准HTTP库的请求来访问它们。
什么是cURL? 💻
cURL是一个免费的开源命令行工具,可用于向你的Cloudant API发出HTTP请求。它是客户端URL(cURL)计算机软件项目的一部分,该项目最初于1997年发布。


cURL可以从命令行直接使用标准URL语法获取和发送数据(包括文件)。对于更重复的任务,你也可以在脚本中使用它。它还通过使用安全套接字层(SSL)证书验证来支持安全的HTTP(HTTPS)请求。
你可以在 github.com/curl/curl 访问最新的cURL源代码。



基本cURL命令

如果你只想从cURL命令行提示符检索一个网页,只需输入单词 curl,然后输入网页的URL。



以下示例将检索IBM Cloud主页:
curl https://cloud.ibm.com

但为了避免每次连接时都输入你的Cloudant服务URL,你可以创建一个变量。


设置变量和别名




以下示例使用 export 命令将我们的Cloudant URL保存为一个名为 URL 的变量。你需要将用户名、密码和主机部分替换为你自己的Cloudant服务凭据信息。你将在本课结束时的动手实验中进行此操作。
export URL="https://username:password@hostname.cloudant.com"


你也可以创建一个别名,作为cURL的快捷方式。以下示例将创建一个名为 acurl 的别名,并指定了JSON内容类型头。它还使用了一些有用的命令行开关:
-s使你的请求静默(即,你不会看到任何进度或错误消息返回)。-g禁用URL全局解析器。-H允许你指定内容类型头。
alias acurl='curl -sg -H "Content-Type: application/json"'


测试连接与操作数据库


要测试与Cloudant中数据库的连接,你可以使用 acurl 别名和 URL 变量(变量前必须加美元符号 $)。如果成功,你将收到一些包含欢迎消息、版本号、供应商名称和关于你的Cloudant实例功能信息的JSON代码。
acurl $URL




要检索所有数据库的列表,再次使用 acurl 别名和美元符号 URL 变量,但要加上 _all_dbs 端点。
acurl $URL/_all_dbs


作为一个附加选项,如果你的操作系统上安装了Python,你可以在这行命令的末尾添加管道命令 | python -m json.tool。这将把你的命令输出发送给Python,以便在终端中获得改进的JSON格式,将JSON数据转换为更易读的格式。
acurl $URL/_all_dbs | python -m json.tool


还有另一个名为 jq 的JSON格式化程序,你可以免费下载和安装,它也能将JSON数据格式化成更易读的形式。指定此格式化程序的管道命令是 | jq。
acurl $URL/_all_dbs | jq



如果你想查看单个数据库的详细信息,只需在斜杠后指定数据库的名称。以下示例将检索名为 training 的数据库的详细信息。同样,你可以使用两个可选的管道命令之一,将命令输出发送到Python或 jq,以提高cURL终端的可读性。
acurl $URL/training
acurl $URL/training | python -m json.tool
acurl $URL/training | jq
要查看数据库中包含的文档,只需在斜杠后指定数据库名称,然后是 _all_docs 端点。这将仅检索所有文档的 _id 和 _rev 值。
acurl $URL/training/_all_docs


要同时检索文档的正文,你需要在命令末尾指定 ?include_docs=true,如以下屏幕示例所示。
acurl $URL/training/_all_docs?include_docs=true
要从数据库中检索单个文档,你需要在包含它的数据库名称后指定文档的文档ID。
acurl $URL/training/document_id
总结


本节课中,我们一起学习了以下内容:
- Cloudant数据库拥有HTTP API,因此可以通过使用标准HTTP库的请求来访问。
- HTTP被Web浏览器、移动设备、常见编程语言以及像cURL这样的命令行脚本工具使用。
- cURL是一个免费的开源命令行工具,可以向Cloudant API发出HTTP请求。
- cURL可以从命令行或脚本中使用标准URL语法获取和发送数据(包括文件)。
- 你应该创建一个变量来访问你的Cloudant服务。
- 你可以使用别名作为cURL的快捷方式。
- 你可以将cURL命令的输出通过管道传递给Python或jq,以在终端中获得改进的JSON格式。
036:使用HTTP API 🚀




概述



在本节课中,我们将学习如何在Cloudant中使用HTTP API。你将掌握使用cURL工具执行不同HTTP方法,从而对数据库、文档进行创建、读取、更新、删除(CRUD)操作,并运行查询。




HTTP方法与cURL

上一节我们介绍了使用cURL执行一些基本命令。你可能注意到,在运行最后几个cURL命令时,我们并未指定HTTP方法。这是因为当cURL命令未明确指定方法时,默认使用GET方法。
Cloudant的API通常使用动词作为其HTTP方法。例如,GET用于检索数据。


但是,如果我们想创建数据库、添加文档或删除文档,这些任务就需要使用其他HTTP方法。例如:
- PUT:用于创建数据库、创建文档或修改现有文档。
- POST:用于运行查询、创建索引或创建文档(需配合
-d参数)。 - DELETE:用于删除数据库、文档和索引。
要使用GET以外的HTTP方法,你需要使用-X命令行开关,然后指定你想在cURL中使用的具体方法。例如:curl -X PUT。
数据库操作
创建数据库
要在Cloudant中创建数据库,需要使用-X开关配合PUT HTTP请求,然后指定服务连接变量和要创建的数据库名称。



命令格式:
curl -X PUT $SERVICE/coursedb


删除数据库


要删除(或称为“删除”)Cloudant中的数据库,同样使用-X开关,但这次配合DELETE HTTP请求,然后指定服务连接变量和要删除的数据库名称。

命令格式:
curl -X DELETE $SERVICE/coursedb

要验证这些HTTP请求是否成功,请查看响应中是否包含 {"ok": true}。

文档操作



插入文档
要在Cloudant中插入文档,如前所述,使用-X开关配合PUT HTTP请求,然后指定服务连接变量和要插入文档的数据库名称。



接着,你需要提供文档的ID(本例中手动指定为212),然后使用-d命令行开关来输入构成文档主体的JSON数据。
命令示例:
curl -X PUT $SERVICE/coursedb/212 -d '{"course_name": "Introduction to NoSQL", "level": "Beginner"}'

要验证此PUT请求是否成功,请查看响应是否包含 {"ok": true},后面跟着你提供的文档ID和一个修订令牌值(rev)。修订令牌是数据库在写入文档时生成的一个标识值。



更新文档
为了更新数据库中的文档,你需要知道该文档的修订令牌值。这个值可以通过在创建文档时记录响应来获得,或者使用_all_docs端点(如上一视频所示)来检索数据库中的所有文档列表。
在Cloudant中更新文档时,同样使用-X开关配合PUT HTTP请求,然后指定服务连接变量以及要更新文档的路径(即数据库名后跟文档ID)。




接着,使用-d命令行开关,并提供更新后文档的新主体。在本例中,我们为文档添加了一个额外的值。


重要提示:你必须提供整个更新后的文档主体。不能只更新文档的一部分,必须用更新后的版本完全替换它。


最后,你必须提供文档的修订令牌值。如果不提供此修订令牌值,将会看到类似示例所示的错误信息。
要验证此更新请求是否成功,请查看响应是否包含 {"ok": true},后面跟着文档ID和新的修订令牌值。
删除文档
要从数据库中删除文档,使用-X开关配合DELETE HTTP请求,然后指定服务连接变量、要删除文档的路径,最后是文档当前的修订令牌值。



命令格式:
curl -X DELETE $SERVICE/coursedb/212?rev=2-9c652960f5f5ec7c0e6f5e8d5a6b7c8d


如果不提供正确的修订令牌值,将会看到错误信息。


要验证此删除请求是否成功,请查看响应中是否包含 {"ok": true}。
查询数据
到目前为止,你看到的所有操作都是CRUD操作,即创建、读取、更新和删除。但如果你想查找数据库中文档包含的信息,例如哪些课程适合初学者,哪些课程涉及特定技术或软件应用程序,或者哪些课程列出Jane Doe为讲师,这时就需要进行查询。



Cloudant查询语言基于MongoDB查询语言,使用JSON格式的对象来表达查询。这些查询使用selector属性来定义查询要返回的数据子集,这相当于SQL中的WHERE子句。
JSON查询对象通过POST HTTP请求发送到数据库的_find端点来执行查询。这些JSON查询可以从cURL命令行或Cloudant仪表板触发。
以下是一个使用cURL查找文档ID为212的文档的示例。注意selector属性的使用。-H开关允许你指定JSON内容类型头。
命令示例:
curl -X POST $SERVICE/coursedb/_find -H "Content-Type: application/json" -d '{"selector": {"_id": "212"}}'
以下是查找所有级别为“Beginner”的课程,以及所有列出“Jane Doe”为讲师的课程的示例。

你还可以在查询中使用逻辑运算符,例如大于($gt)和小于($lt)。因此,本幻灯片上的示例是查找包含超过4个模块的课程。


命令示例:
curl -X POST $SERVICE/coursedb/_find -H "Content-Type: application/json" -d '{"selector": {"modules": {"$gt": 4}}}'

使用JSON文件进行查询
如果你有一个需要定期重用的查询,或者JSON查询本身很大,与其像我们在这里和动手实验室中那样直接在cURL命令行中输入JSON查询,你很可能希望将JSON查询存储在一个.json文件中。



如果你这样做,可以使用-d @后跟JSON文件名来指定JSON文件,如本屏幕示例所示。

命令示例:
curl -X POST $SERVICE/coursedb/_find -H "Content-Type: application/json" -d @query.json

总结
本节课中,我们一起学习了以下内容:

- cURL默认使用GET HTTP方法,除非你使用
-X命令行开关指定其他方法。 - 可以在cURL中使用的其他HTTP方法包括:PUT、POST和DELETE。
- 使用PUT请求来创建数据库、创建文档和更新文档。
- 使用POST请求来运行查询、创建文档和创建索引。
- 使用DELETE请求来删除(或删除)数据库、文档和索引。
- Cloudant Query是一种基于MongoDB查询语言的查询语言,用于运行以JSON对象形式表达的查询。

浙公网安备 33010602011771号