DynamoDB介绍

1. DynamoDB介绍及实践

DynamoDB特点:

  • AWS全面管理的NoSQL数据库服务
  • 全部基于solid-state drives(SSDS)
  • 没有存储空间上限
  • 可以支持任意数量的每秒并发吞吐量
  • 稳定的低延迟性能:单位数ms的响应延迟
  • 同时支持Key-Value和Document数据模型
  • 自动在三个AZ复制数据
  • 低成本
    DynamoDB的数据模型可以说是BigTable与Oracle NoSQL的融合。系统首先分成多张表(Table)。表中的记录拥有单属性简单哈希主键或两属性Hash Key+Range Key组合主键。记录内容可包含任意多个属性,属性分单值或多值两种。属性值可以是字符串或数值类型。表没有统一的模式,建表时只需要指定主键的定义,其余各记录都可以拥有自己不同的属性集合。记录由主键和多个属性组成这一点类似于BigTable,这比简单的KV模型更易用。主键可以由Hash Key+Range Key组合而成则类似于Oracle NoSQL,这主要为了提供相同Hash Key的记录集合操作。
    DynamoDB 可以从表中自动删除过期的项,从而帮助您降低存储用量,减少用于存储不相关数据的成本。

1.1. DynamoDB 核心组件

在 DynamoDB中,表、项目和属性是您使用的核心组件。表是项目的集合,而每个项目是属性的集合。DynamoDB 使用主键来唯一标识表中的每个项目,并且使用二级索引来提供更大的查询灵活性。您可以使用 DynamoDB 流 捕获 DynamoDB 表中的数据修改事件。

1.1.1. 表、项目和属性

基本 DynamoDB 组件包括:

  • 表 - 类似于其他数据库系统,DynamoDB 将数据存储在表中。表是数据的集合。
  • 项目 - 每个表包含多个项目。项目是一组属性,具有不同于所有其他项目的唯一标识。DynamoDB 中的项目在很多方面都类似于其他数据库系统中的行、记录或元组。
  • 属性 - 每个项目包含一个或多个属性。属性是基础的数据元素,无需进一步分解。DynamoDB 中的属性在很多方面都类似于其他数据库系统中的字段或列。

1.1.2. 主键

创建表时,除表名称外,您还必须指定表的主键。主键唯一标识表中的每个项目,因此,任意两个项目的主键都不相同。

DynamoDB 支持两种不同类型的主键:

  • 分区键 - 简单的主键,由一个称为分区键 的属性组成。
    DynamoDB 使用分区键的值作为内部散列函数的输入。来自散列函数的输出决定了项目将存储到的分区 (DynamoDB 内部的物理存储)。在只有分区键的表中,任何两个项目都不能有相同的分区键值。
  • 分区键和排序键 - 称为复合主键,此类型的键由两个属性组成。
    第一个属性是分区键,第二个属性是排序键。

DynamoDB 使用分区键值作为对内部散列函数的输入。来自散列函数的输出决定了项目将存储到的分区 (DynamoDB 内部的物理存储)。具有相同分区键的所有项目按排序键值的排序顺序存储在一起。
在具有分区键和排序键的表中,两个项目可以具有相同的分区键值,但是,这两个项目必须具有不同的排序键值。
DynamoDB介绍_第1张图片

1.2. DynamoDB API

1.2.1. 控制层面

控制层面操作可让您可以创建和管理 DynamoDB 表。它们还可让您可以使用依赖于表的索引、流和其他对象。

  • CreateTable - 创建新表。或者,您也可以创建一个或多个二级索引并为表启用 DynamoDB 流。
  • DescribeTable - 返回有关表的信息,例如,表的主键架构、吞吐量设置、索引信息等。
  • ListTables - 返回列表中您的所有表的名称。
  • UpdateTable - 修改表或其索引的设置、创建或删除表上的新索引或修改表的 DynamoDB 流 设置。
  • DeleteTable - 从 DynamoDB 中删除表及其所有依赖对象。

1.2.2. 数据层面

数据层面操作可让您对表中的数据执行创建、读取、更新和删除 (也称为 CRUD) 操作。某些数据层面操作还可让您可以从二级索引中读取数据。

创建数据:

  • PutItem - 将单个项目写入到表中。您必须指定主键属性,但不必指定其他属性。
  • BatchWriteItem - 将最多 25 个项目写入到表中。这比多次调用 PutItem 更有效,因为您的应用程序只需一个网络往返行程即可写入项目。请注意,您还可以使用 BatchWriteItem 来从一个或多个表中删除多个项目。

读取数据:

  • GetItem - 从表中检索单个项目。您必须为所需的项目指定主键。您可以检索整个项目,也可以仅检索其属性的子集。
  • BatchGetItem - 从一个或多个表中检索最多 100 个项目。这比多次调用 GetItem 更有效,因为您的应用程序只需一个网络往返行程即可读取项目。
  • Query - 检索具有特定分区键的所有项目。您必须指定分区键值。您可以检索整个项目,也可以仅检索其属性的子集。或者,您也可以对排序键值应用条件,以便只检索具有相同分区键的数据子集。您可以对表使用此操作,前提是该表同时具有分区键和排序键。您还可以对索引使用此操作,前提是该索引同时具有分区键和排序键。
  • Scan - 检索指定表或索引中的所有项目。您可以检索整个项目,也可以仅检索其属性的子集。或者,您也可以应用筛选条件以仅返回您感兴趣的值并放弃剩余的值。

更新数据:

  • UpdateItem - 修改项目中的一个或多个属性。您必须为要修改的项目指定主键。您可以添加新属性以及修改或删除现有属性。您还可以执行有条件更新,以便更新仅在满足用户定义的条件时成功。或者,您也可以实施一个原子计数器,该计数器可在不干预其他写入请求的情况下递增或递减数字属性。

删除数据:

  • DeleteItem - 从表中删除单个项目。您必须为要删除的项目指定主键。
  • BatchWriteItem - 从一个或多个表中删除最多 25 个项目。这比多次调用 DeleteItem 更有效,因为您的应用程序只需一个网络往返行程即可删除项目。请注意,您也可以使用 BatchWriteItem 来向一个或多个表添加多个项目。

2. 使用DyanmoDB中踩的坑

在实际的项目使用中我们配置了6W/s的写入速度,但是实际的写入速度被限制在2W/s, 有大量的写入受限,写入速度上不去。我们遇到了DynamoDB的一个坑。配置的读写速度并不是我们想象的总的速度,而是和DynamoDB分区数量有关。

2.1. DynamoDB的分区

我们可以将任意数据的数据添加到表中,当数据量超过10G后,DynamoDB会把一个分区拆分成2个分区,分区最大10G。 但是大小只是拆分区的一个因素, 另外一个因素是吞吐量。

  • 吞吐量
    我们可以给表配置任意数量的吞吐量。
    写入容量单位(WCU:write capacity units)以每秒1KB来测量,就是说一次写入100字节的数据算一次写入;一次写入1.2KB的数据算2次写入。
    读取容量单位(RCU:read capacity units)以每秒4KB来测量,一次读取的数据小于4KB算一次读; 一次读取得数据超过4KB,每4KB算一次读。

  • 每个分区最大的WCU是1000, 最大的RCU是3000
    就是说不管表的WCU, RCU设置多大,一个分区最大的WCU,RCU是固定的。

2.2. 分区数量的计算方法

大小超过10G会分区;RCU超过3000, WCU超过1000也会分区,通过增加分区数提供并发度,保证读写速度。
DynamoDB介绍_第2张图片
比如数据量大小8GB, RCU=5000, WCU=500, 那么分区数量为3个
DynamoDB介绍_第3张图片
每个分区大小为:
数据/分区=8/3=2.67GB

  • 一个容易忽略的点是RCU和WCU是在分区间均匀分布的
    分成3个区之后:
    每个分区的RCU=5000/3=1666.67
    每个分区的WCU=500/3=166.67
    而不是保证每个分区的RCU可以到5000, WCU可以达到500。

我们遇到的问题是我们的点击量太大了,每天超过20亿,持续写入一个表大概2周,每10G一个分区,我们的点击分成了大概250个分区, 6W的WCU平均到250个分区,每个分区只有240的WCU, 一旦数据的按分区键分配的不均匀,造成某个分区的写入超过了240 WCU,就会造成写入受限。

3. 改进方案

3.1. 冷数据,热数据分表

我们的数据特征是最频繁读写的是当天的数据,之后只有少量的读取。所有我们采用的策略的策略是按天建表。当天的表RCU和WCU配置的高,历史的表只配置少量的RCU。
经过分表以后,每个表的partition都不会太多,不会造成每个partition的WCU和RCU太小,满足不了读写性能。

3.2. 分区键做hash

之前分区键是直接用数据中的原始值的,调查后发现,这些key在DynamoDB里进行hash后还是发布的不均匀,存在数据倾斜现象。所有我们不再存储原始的值,而是把这些key转成md5再存到DynamoDB里,这样分区键经过DynamoDB的hash, 分布的就比较均匀,没有数据倾斜现象了。
经过这些处理,基本可以实现实际的WCU能达到配置的WCU数量。

你可能感兴趣的:(KV存储)