DynamoDB 是一个 AWS全托管的NoSQL 数据库,K-V lookup store。其中K-V 是基于 primary key 来做快速查找的,V一般是JSON 串。
特性
High performance, availability, durability,老生常谈
Use replicas to get redundancy。副本保证数据不会丢。如果没有设置全局副本,那么在当前选定的区域中,副本数固定为3
使用场景
Ideal for applications with known access patterns。已知的数据访问模式,是指对数据库的访问是固定的,在设计初期就已经知道的。比如就是通过studentId来查询。
而不会突然通过其他字段查找。对于这种对数据的访问形式固定且可预测的,DynamoDB是舒适区。
访问方式
AWS 管理的,那么可以通过 API/ORMs and authorised through IAM 访问
核心概念
- Table 表,就是数据的存储集合
- Partition Key PK,分区键,用于数据分区。某一属性作为分区键的时候,DynamoDB会根据属性值哈希,然后根据哈希值把数据分布到不同的分区上,从而实现数据的分布式存储和高效访问。
- Sort Key SK,排序键,用于在分区内排序。可以和partition key一起组成primary key。注意,sort key不是全分区内优先排序的字段,而是还是按照PK的哈希值排序,只有PK的哈希值相同的时候,才按照sort key排序。
- Primary Key 主键,由 partition key 和 sort key 组成。primary key 用于唯一标识表中的每一项数据。如果只使用 partition key 作为主键,那么该属性的值必须是唯一。
Attribute 属性,除了partition key, sort key, 剩下的列叫Attribute,就是K-V中的V,一般是JSON - Item 记录,一行数据一个Item
Indexes 索引,用于加速查询的非主键索引,例如GSI global secondary index,这个secondary就是对应primary说的。 全局第二索引,partition key, sort key, 之外的基于其他column的索引
因为是NoSQL,所以不要考虑数据的组织形式是架构化的,业务数据应该都在JSON串,也就是Attribute里,而这个JSON 串是没有schema的,可以随意变更。即使有Schema,一般也是讨论Key的设置。
问题
-
如果primary key 重复,插入会报异常吗?
DynamoDB 的默认行为是 覆盖(Overwrite)。它会直接用新数据替换掉旧数据,而不会报错。如果需要报错,需要手动设置:条件表达式(Condition Expression)。在调用 PutItem 时,加上一个判断主键是否存在的条件: 只有当 attribute_not_exists(主键名) 为真时,才执行插入。
此时如果主键已存在,DynamoDB 会抛出一个 ConditionalCheckFailedException 异常。
特殊情况:BatchWriteItem 为了性能考虑,不支持条件检查。这意味着如果在批量写入时发生了主键冲突,它一定会静默覆盖。如果你必须要求冲突报错,只能循环使用单个 PutItem。
-
primary key 的组成是在创建表的时候确定的吗?
Primary Key 的结构必须在创建表时(Create Table)明确定义,一旦表创建完成,无法更改该表的主键组成。如果后续发现主键设计不合理,唯一的办法是新建一张表,然后进行数据迁移。
一般二选一:
简单主键 (Simple Primary Key):仅由 Partition Key (PK) 组成。 适用于简单的键值对查询(如:根据 UserID 找用户信息)。
复合主键 (Composite Primary Key):由 Partition Key (PK) + Sort Key (SK) 组成。根据业务,如果partition key 有多条记录,就用这种方式。 PK 决定数据分布在哪个分区,SK 决定在该分区内如何排序。
-
读写都是O(1)O(1)O(1)吗?
是的,读写(PutItem/GetItem)在逻辑上都是 O(1)O(1)O(1)。 这种极速查询确实依靠 Partition Key 的哈希值实现第一步定位找到分区,分区内部的查找也是通过高效的数据结构(如 B 树)实现的。B树的特点是层数低,虽然B树的查找是O(nlogn)O(nlogn)O(nlogn),但是一般B树只有3、4层,这样固定层数的查找(磁盘IO+内存比较),所以认为是O(1)O(1)O(1)。
具体来说:
如果只有 Partition Key(Simple Primary Key),这种数据结构中的(DynamoDB 主要使用类似于 B-Tree 的结构)。DynamoDB会把Partition Key的哈希值(前面用来做过分区索引的)存下来,并把数据按照这个哈希值排序。然后用这个哈希值作为索引组织成B树的形式。
如果有 Sort Key(Composite Primary Key)定位 PK: 先找到该 PK 对应的所有数据的物理起始位置。定位 SK: 同一个 PK 下的数据在物理上是按 Sort Key 顺序连续存放的。Index Key = Hash(Partition Key) + Sort Key (Original Value),用这个索引组织称B树。
-
是否会有分区过热?
会有分区过热,AWS 会自动分裂(Split),并且会自动完成数据迁移,用户无感。保证数据如果更换了分区,也不会出现找不到的情况。
-
副本数是如何确定的?
首先一般区域选择用户最多的AWS区域,DynamoDB 会在每个区域内自动维护至少 3 个副本,以确保高可用性和数据持久性。用户无法直接配置副本数量,但可以通过启用全局表(Global Tables)来实现跨区域的数据复制,从而提高数据的冗余度和访问速度。
-
支持事务吗?
支持ACID事务操作。DynamoDB 的事务是 "全有或全无"(All-or-Nothing) 的: 原子性: 一个事务中包含的所有操作(最多 100 个),要么全部执行成功,要么全部回滚。范围: 事务可以跨越同一个 AWS 账户和区域内的 多张表,只要这些表都在同一个区域。
同步执行: 写入操作是强一致性的,且在返回成功之前,数据已经持久化。