【AWS系列】什么是DynamoDB

简介: 1. Truncate 操作:DynamoDB不支持 Truncate操作,最简单的办法是删表重建即可;如果需要删掉一部分数据,可以写脚本用scan 查出 PK 的列表逐个进行删除;还可以设置表的过期时间,让这批数据定期失效即可。2. JavaScript 有两个类库:一种使用了 DynamoDB Json其中包括了数据的类型,需要调用相关的marshal 和 unmarshal方法来转换成标准的 Json3.批量操作:DynamoDB 中批量操作有25 的数据量。



1 工作原理

Amazon DynamoDB 是一种完全托管式无服务器的 NoSQL 键值数据库,旨在运行任何规模的高性能应用程序。

DynamoDB 提供内置安全性、连续备份、自动多区域复制、内存缓存和数据导入和导出工具。

可以以非常低的延迟支持 任何级别的负载 ,同时有着较完善的权限管理系统

image.gif编辑

2 使用优势

    • 简化运维:全托管模式,减少创建、维护数据库的开销;跨区域的分区存储,数据更安全;
    • 自动扩容:数据量的增长对数据库性能没有太多影响
    • 灵活的表结构:只需要定义分区键即可正常使用,随时增加减少字段
    • 事件流:流结合 Lambda 可以非常方便的实现一些功能

    3 基本使用

    DynamoDB 的数据集合是一张表,表里的每一条数据就是一个文档

    文档中可以存储基本类型的数据(BOOLEAN, NUMBER, STRING)或者一些复杂的数据(MAP, LIST, SET),可以嵌套较为深的层级。

    在创建一张表的时候,

    需要指定一个基本类型的属性值作为 PK

    再指定一个基本类型的属性值作为 SK

    PK 的作用是将数据分散到不同的分区(Partition)里,构建无序的哈希索引

    SK的作用是将同一个分区中的数据按照一定的顺序排列起来,便于查找

    SK 中可以使用 ==, <, >=, <=, begins with, between, contains, in 等函数来进行较为丰富的查询操作

    PK 必须使用准备的值进行查询

    3.1 基本结构

      • 表(Table)
      • 文档(Document)
      • 属性(Attribute)
      • 分区键(Partition Key/Hash Key, 记为 PK,必需,数据类型必须是基本类型)
      • 排序键(Sort Key/Range Key, 记为 SK,可选)
      • 数据类型:
        • 基本类型: number, string, binary, Boolean, and null
        • 文档: list, map
        • 集合: set

          3.2 索引

          DynamoDB 共有两种索引:

          1 本地二级索引(Local Secondary Index,简称 LSI)

          2 全局二级索引(Global Secondary Index,简称 GSI)

          3.2.1 本地二级索引 (LSI)

          本地二级索引和原表共用一份 Partition, 使用同一个 PK, 共用这一个 PK 的存储空间,上限为 10GB

          LSI 提供了不同的筛选方式和排序方式,选用不同的属性作为 SK 可以提高查询的灵活性。

          3.2.2 全局二级索引 (GSI)

          全局二级索引相当于一个全新的表,除了与原表共用同一个表名之外,GSI 使用了新的 Partition Key 和 Sort Key, 有自己独立的 Partition, 计算读写数量时也与原表相互独立。

          GSI 会在原表发生改变的时候,通过流(Stream)将更新同步到 GSI 中。一个表可以建立 20 个全局二级索引。

          推荐使用全局二级索引,避免本地二级索引引起的读写容量的竞争,同时可以重新定义 PK 和 SK,支持更多的查询模式

          3.3  一致性

          DynamoDB 是数据库云服务,其在设计中着重考虑了数据的 可用性分区容忍性。从 CAP(Consistency, Availability, Partitioning)理论的角度来讲,DynamoDB 是一个 AP 的数据库。

          在 DynamoDB 中,共有两个部分会涉及到读一致性的问题:主表读和GSI读

          主表读过程会产生一致性问题的原因是 DynamoDB 的 Partition 是有 三个副本的(实际为可用区)

          默认情况下写入到两个副本中即认为写入成功,因此在高频读取时也有一定的概率读到未完成写入的数据

          可以通过配置 GetItem, Scan 等的操作一致性为 强一致性来避免这个问题,

          但可能会带来更高的延迟(10ms级别)和吞吐量开销(强一致性为最终一致性吞吐量开销的二倍)。

          GSI 读写会产生一致性的原因是 GSI 和主表实际是 两个不同的存储,写入到主表的数据会通过流同步到GSI,这个过程会存在一定的延时(10ms级别),因此在读取 GSI 中的数据时,不能设置为强一致性

          3.4 DynamoDB流

          DynamoDB流是一项可选功能,它用于捕获DynamoDB表中的数据修改事件。有关这些事件的数据将按事件发生的顺序近乎实时的出现在流中。

          每个事件由一条流记录表示,若对表启用了流,每当以下事件之一 发生时,DynamoDB流都会写入一条流记录:

            • 如果向表中添加了新项目,流将捕获整个项目的映像(包括其所有属性)
            • 如果更新了项目,流将捕获项目中任何已修改属性的"之前""之后"映像
            • 如果从表中删除了项目,流将在整个项目被删除前捕获其映像
            • 每条流记录还包含表名称、事件时间戳和其他元数据流记录的有效事件为24小时,过此事件后记录将被自动删除

            启用 DynamoDB Stream 之后,可以使用 Lambda 接收 Stream 并将数据填充到

              • ElasticSearch 中便于进行复杂的查询
              • 或者同步数据
              • 或者进行一些聚合计算

              均可以通过 DynamoDB Stream 方便的完成。

              3.5 表结构设计

              DynamoDB 是需要提前考虑好一些查询方式,才能更好的设计表结构,否则可能会在使用的过程中遇到一些不便。

              DynamoDB 限于底层结构设计,进行表扫描(Scan)的操作非常耗时,对于较大的表来说基本上是 不可接受的时间消耗,因此需要根据 DynamoDB 的特点对表结构进行巧妙的设计,以实现需要的查询组合。

              因此,设计 DynamoDB 时:

              第一步:列举出可能的查询方式。当有了一组查询方式之后,便可以开始进行表结构的设计。

              3.5.1 基本查询

              在设计出查询方式之后,便可以优先关注使用量最多,查询方式最简单的查询需要。以下为主表中几种常见的查询方式:

                1. 使用 PK 直接查询:可以查出该分区键下的所有数据,适合于 一对多关系。例如查询一个用户下的多个订单记录,这时 PK 为用户的 ID
                2. 使用 PK + 完整 SK 进行查询:如果一个 PK 下的数据比较多,可以结合 SK 来实现更为精确的查询。例如查询一个用户下的一个特定的订单,这时 PK 为用户的 ID,SK 为订单的ID。
                3. 使用 PK + SK (==, <, >=, <=, begins with, between, contains, in) 进行查询:如果一个 PK 下数据比较多,同时每一类 SK 上有通用的前缀,可以用 begins with 来进行查询。例如查询用户的订单使用用户 ID 和 SK 前缀 order: 进行查询。

                3.5.2 索引重载

                AWS 的 Principal Technologist, Rick Houlihan 曾说,一个设计良好的 DynamoDB 应该只有一张表。

                索引重载是使用 RDS 的用户最容易感到不适应的一部分

                这意味着属性名不一定是一个有实际含义的名称,其内容也可能包含多个种类。

                这显然与之前对 RDS 数据的认识完全不一样,RDS 倾向于细粒度的划分每个实体,为实体及实体之间的关系建立相关的表。

                如果一个应用只有一张表,那么用户、订单、商品、发票等数据会共用一个表定义,表的结构可能类似下面这个样子:

                image.gif编辑

                可以使用 #User#{ID} 和 #PRODUCT#{ID}这样的方式在 ID 中带上该条记录的类型

                SK 也可以采用类似的设计方式,这样可以更好的辨识一条数据的类型,另一方面当 PK 在 GSI 中作为 SK 时,可以使用 begins with 查出同一类的数据。

                因为 DynamoDB 可以自动扩容,所设计好这一个表之后,便可以方便的对该表创建 GSI,开启备份,使用同样的查询、数据插入的命令来完成各种各样的操作,同时因为使用同一个读写容量,所以会减少读写容量的浪费。

                新建不同的表来存储这些内容,其实新建的表与该表也不会太大的差异,使用同一张表反而更加方便。

                在使用 PK 和 SK 进行 Query 之后,还可以使用 Filter 进行数据的筛选,这些筛选只能使用在基础数据类型上面,

                因此如果存储 list, map, set 时可能会简化一些操作,但在筛选时遇到一些问题,可以利用 sk 的 begins with 查询功能,将数据拆分开来方便筛选。

                3.5.3 稀疏索引

                创建 GSI 时,会重新选择一个基础类型的字段作为主键,如果部分数据并不包含这个字段,那么这些数据就不会被添加到这个 GSI 索引中来。

                因此可以利用这个特性为不同的查询模式来创建不同 GSI,以减少 GSI 中数据的数量。

                3.5.4 组合键

                组合键是一个非常有用的方式

                如果有一些字段必须复合起来使用,并且会作出相对复杂的筛选条件,那么便可以考虑采用组合键来处理。如以下示例:

                image.gif编辑

                希望达成类似 SELECT * FROM Game WHERE Opponent = 'Bob' ORDER BY DATE DESC FILTER ON Status='PENDING' 的查询,

                如果 Bob 的数据有上千条,但 IN_PROGRESS 的数量只有一条,那使用 Query + Filter 的结果是需要查到这千条数据,再从中过滤出需要的数据来。

                但如果使用组合键 StatusDate = Status + Date, 如下示例:

                image.gif编辑

                可以直接查到需要的这两条数据,也可以继续使用 Filter 再进行过滤。

                同时会有一些特殊的要求,在不使用组合键时,如果进行查询会是一个相当大的挑战。

                3.5.5 分级数据

                与组合键类型,分级数据意味着该字段中的数据不是一个简单的数据,也会是一个拼起来的数据

                最简单的例子是地域信息:比如四川省成都市,可以存储为 #SICHUAN#CHENGDU,如果后面有多少级均可以继续接在后面。通过这种方式便把一个层级很深的数据转化成了一个简单的数据,

                同时使用 begins with便可以查某个区划下的所有信息。

                4 本地开发

                DynamoDB 是 AWS 的云服务,可以使用 AWS 提供的 aws-cli, 通过命令行来完成常见的表操作及数据操作。

                最为常用的功能是结合其它命令一起进行查询及数据分析,或者清除表中的数据。

                同时,如果在开发过程中需要使用 DynamoDB,依然需要付出相应的服务费用

                使用 DynamoDB Local 可以减少这部分开销

                DynamoDB Local

                如果在本地进行开发,可以使用 DynamoDB Local,

                  • 通过 DynamoDBLocal 的 jar 包直接运行
                  • 使用 Docker 运行 DynamoDB 的镜像

                  命令为

                  docker run -p 8000:8000 -v $(pwd)/data:/data/ amazon/dynamodb-local:1.11.477 -jar DynamoDBLocal.jar -sharedDb -dbPath /data
                  image.gif

                  可以使用 DynamoDB GUI 作为图形化的管理工具或者直接使用 aws-cli 加上参数,进行管理。

                  --endpoint-url http://localhost:8000
                  image.gif

                  CLI代码示例:

                  aws dynamodb create-table \
                      --table-name music \
                      --attribute-definitions \
                          AttributeName=artist,AttributeType=S \
                          AttributeName=song_title,AttributeType=S \
                      --key-schema \
                          AttributeName=artist,KeyType=HASH \
                          AttributeName=song_title,KeyType=RANGE \
                  --provisioned-throughput \
                          ReadCapacityUnits=10,WriteCapacityUnits=5
                  aws dynamodb describe-table --table-name music | grep TableStatus
                  aws dynamodb put-item \
                      --table-name music  \
                      --item \
                          '{"artist": {"S": "No One You Know"}, "song_title": {"S": "Call Me Today"}, "album_title": {"S": "Somewhat Famous"}, "awards": {"N": "1"}}'
                  aws dynamodb get-item --consistent-read \
                      --table-name music \
                      --key '{ "artist": {"S": "Acme Band"}, "song_title": {"S": "Happy Day"}}'
                  aws dynamodb update-item \
                      --table-name music \
                      --key '{ "artist": {"S": "Acme Band"}, "song_title": {"S": "Happy Day"}}' \
                      --update-expression "SET album_title = :newval" \
                      --expression-attribute-values '{":newval":{"S":"Updated Album Title"}}' \
                      --return-values ALL_NEW
                  aws dynamodb update-table \
                      --table-name music \
                      --attribute-definitions AttributeName=album_title,AttributeType=S \
                      --global-secondary-index-updates \
                      "[{\"Create\":{\"IndexName\": \"album_title-index\",\"KeySchema\":[{\"AttributeName\":\"album_title\",\"KeyType\":\"HASH\"}], \
                      \"ProvisionedThroughput\": {\"ReadCapacityUnits\": 10, \"WriteCapacityUnits\": 5      },\"Projection\":{\"ProjectionType\":\"ALL\"}}}]"
                  aws dynamodb query \
                      --table-name music \
                      --index-name album_title-index \
                      --key-condition-expression "album_title = :name" \
                      --expression-attribute-values  '{":name":{"S":"Somewhat Famous"}}'
                  aws dynamodb query \
                      --table-name music \
                      --key-condition-expression "artist = :name" \
                      --expression-attribute-values  '{":name":{"S":"Acme Band"}}'
                  aws dynamodb scan --table-name music --filter-expression 'attribute_exists(artist)'
                  aws dynamodb delete-table --table-name music
                  // 使用 jq 获取某个字段并取得不重复值
                  aws dynamodb scan \
                      --table-name music \
                      --index-name business-index \
                      --projection-expression some_data \
                      | jq '.Items[] | .data.S' | sort --unique
                  image.gif

                  5 总结

                  1. Truncate 操作:DynamoDB 不支持 Truncate 操作,

                  最简单的办法是删表重建即可;

                  如果需要删掉一部分数据,

                    • 可以写脚本用 scan 查出 PK 的列表逐个进行删除
                    • 还可以设置表的过期时间,让这批数据定期失效即可。

                    2. JavaScript 有两个类库:一种使用了 DynamoDB Json

                    其中包括了数据的类型,需要调用相关的 marshal 和 unmarshal 方法来转换成标准的 Json

                    3.批量操作:DynamoDB 中批量操作有 25 的数据量限制,部分情况下需要手动分批分成多个请求来处理,部分类库提供了自动分批的功能

                    4.空值操作:DynamoDB 无法写入空值、空字符串,会直接忽略相应字段

                    5.查询:非基本类型的数据可以当作 String 进行查询

                    相关文章
                    |
                    6月前
                    |
                    存储 安全 关系型数据库
                    AWS介绍
                    AWS介绍
                    139 0
                    |
                    6月前
                    |
                    存储 API 云计算
                    AWS基础
                    AWS基础
                    93 2
                    |
                    6月前
                    |
                    存储 人工智能 大数据
                    云计算平台:AWS、Azure和Google Cloud的比较与选择
                    在当今数字化时代,云计算平台成为了企业和个人的首选。本文将重点比较三大主流云计算平台:AWS、Azure和Google Cloud,从性能、功能、可用性以及定价等方面进行综合评估,帮助读者更好地选择适合自己需求的云计算平台。
                    |
                    20天前
                    |
                    NoSQL MongoDB 数据库
                    使用NimoShake将数据从AWS DynamoDB迁移至阿里云MongoDB
                    使用NimoShake将数据从AWS DynamoDB迁移至阿里云MongoDB
                    |
                    6月前
                    |
                    存储 运维 前端开发
                    Amazon S3
                    Amazon S3
                    110 0
                    |
                    12月前
                    |
                    存储 固态存储 数据安全/隐私保护
                    什么是 Amazon Lightsail
                    什么是 Amazon Lightsail
                    |
                    SQL Cloud Native Go
                    云服务部署:AWS、Azure和GCP比较
                    云服务部署:AWS、Azure和GCP比较
                    447 0
                    |
                    存储 大数据 测试技术
                    3.2.1存储服务 亚马逊 AWS|学习笔记
                    快速学习3.2.1存储服务 亚马逊 AWS
                    1028 0
                    3.2.1存储服务 亚马逊 AWS|学习笔记
                    |
                    存储 JSON 关系型数据库
                    【AWS系列】什么是DynamoDB
                    1. Truncate 操作:DynamoDB不支持 Truncate操作,最简单的办法是删表重建即可;如果需要删掉一部分数据,可以写脚本用scan 查出 PK 的列表逐个进行删除;还可以设置表的过期时间,让这批数据定期失效即可。2. JavaScript 有两个类库:一种使用了 DynamoDB Json其中包括了数据的类型,需要调用相关的marshal 和 unmarshal方法来转换成标准的 Json3.批量操作:DynamoDB 中批量操作有25 的数据量。
                    396 0
                    【AWS系列】什么是DynamoDB
                    |
                    智能硬件
                    Amazon Exclusives 会成为下一个 Kickstarter 吗?
                    随着创客运动的兴起,一大帮有梦青年开始投身智能硬件等新创领域,并随之出现了一大批新鲜创意产品。然而,极客发烧友抑或普通消费者想要购买到这些创意产品的渠道依然还是比较狭窄的,他们往往只能到一些众筹平台或直接去其官网进行采购。
                    125 0
                    Amazon Exclusives 会成为下一个 Kickstarter 吗?