【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 进行查询

                    相关文章
                    |
                    1月前
                    |
                    存储 安全 关系型数据库
                    AWS介绍
                    AWS介绍
                    35 0
                    |
                    3月前
                    |
                    存储 人工智能 大数据
                    云计算平台:AWS、Azure和Google Cloud的比较与选择
                    在当今数字化时代,云计算平台成为了企业和个人的首选。本文将重点比较三大主流云计算平台:AWS、Azure和Google Cloud,从性能、功能、可用性以及定价等方面进行综合评估,帮助读者更好地选择适合自己需求的云计算平台。
                    |
                    1月前
                    |
                    存储 API 云计算
                    AWS基础
                    AWS基础
                    41 2
                    |
                    4月前
                    |
                    存储 运维 前端开发
                    |
                    5月前
                    |
                    存储 固态存储 数据安全/隐私保护
                    什么是 Amazon Lightsail
                    什么是 Amazon Lightsail
                    46 0
                    |
                    6月前
                    |
                    SQL Cloud Native Go
                    云服务部署:AWS、Azure和GCP比较
                    云服务部署:AWS、Azure和GCP比较
                    186 0
                    |
                    11月前
                    |
                    存储 数据库 开发工具
                    「技术选型」AWS 和 AZURE的全面比较
                    「技术选型」AWS 和 AZURE的全面比较
                    |
                    存储 大数据 测试技术
                    3.2.1存储服务 亚马逊 AWS|学习笔记
                    快速学习3.2.1存储服务 亚马逊 AWS
                    872 0
                    3.2.1存储服务 亚马逊 AWS|学习笔记
                    |
                    存储 JSON 关系型数据库
                    【AWS系列】什么是DynamoDB
                    1. Truncate 操作:DynamoDB不支持 Truncate操作,最简单的办法是删表重建即可;如果需要删掉一部分数据,可以写脚本用scan 查出 PK 的列表逐个进行删除;还可以设置表的过期时间,让这批数据定期失效即可。2. JavaScript 有两个类库:一种使用了 DynamoDB Json其中包括了数据的类型,需要调用相关的marshal 和 unmarshal方法来转换成标准的 Json3.批量操作:DynamoDB 中批量操作有25 的数据量。
                    318 0
                    【AWS系列】什么是DynamoDB
                    |
                    存储 新零售 弹性计算
                    心动《另一个伊甸》从Amazon DynamoDB迁移MongoDB
                    阿里云MongoDB提供了很好的保障和性能,使我们的业务成本有了明显的下降
                    心动《另一个伊甸》从Amazon DynamoDB迁移MongoDB