有时候,你只是想写个轻量小项目:
- 帮朋友做个投票系统
- 搞个微信公众号后端
- 做个每日提醒的打点记录服务
本来简简单单的一件小事,但一旦涉及数据库,画风就突然变了:
“这项目数据库用哪个?MySQL?Redis?PostgreSQL?要不要建索引?买云厂商的还是自己搭?”
对一个独立开发者来说,如果每次都需要重新搭建数据库,那还真是一件费时费力的事,花钱买吧,咱又嫌贵。
后来,我发现了 Amazon DynamoDB,这玩意轻便、省事、免费,用来做点简单项目真的太合适不过了🤣。
Amazon DynamoDB 是啥?
Amazon DynamoDB 是一种托管型 NoSQL 数据库,主打一个“你写代码就行,剩下我来搞定”。
特性 | 描述 |
---|---|
无服务器 | 不用配机器,点几下控制台就能用 |
自动扩缩容 | 从 1 用户到 10 万用户,一套系统撑住 |
毫秒级响应 | 性能媲美 Redis,读写快得飞起 |
免费额度 | 永久免费的 25GB 存储 |
不怕突发流量 | 写完放那里就行,突然爆火也能顶住 |
自带 TTL | 支持设置过期时间,不用自己跑脚本删数据 |
再来简单对比一下常用的数据库:
功能/体验 | MySQL | Redis | DynamoDB |
---|---|---|---|
启动成本 | 高(安装部署建库建表) | 中(装完就能用) | 低(控制台一键启动) |
是否需运维 | 是 | 是 | 否 |
适合副业项目 | 适合复杂项目 | 临时数据可以 | 适合简单项目 |
数据过期机制 | 自己写 SQL 删 | 有 TTL | 有 TTL |
并发应对能力 | 中等 | 高 | 自动扩容 |
免费额度 | 无 | 无 | 有 |
当然,需要先注册亚马逊云的账号,才能使用 DynamoDB 的免费额度,这里我提一下注册账号的关键流程供大家参考:
- 进入 亚马逊云官网 ,点击右上角创建账号
- 手机号、账单信息可以直接用国内资料填写;
- 选择基础支持计划(无需额外开支);
- 注册完成后等待身份验证通过,即可开始使用免费资源。
Amazon DynamoDB 怎么用?
和传统数据库不同,Amazon DynamoDB 的设计原则是:
不是先建表再写代码,而是先想好怎么查,再决定怎么建表。
比如:
- 某个用户的所有订单 →
Partition Key = user_id
,Sort Key = order_id
- 某一天的全部签到记录 →
Partition Key = date
,Sort Key = user_id
Partition Key | Sort Key | 说明 |
---|---|---|
user_id | order_id | 某用户所有订单 |
date | user_id | 某日所有签到记录 |
DynamoDB 的“主键 = 分区键 + 排序键”组合,是实现高效查询的关键。
如何建表
控制台一键建表
- 登录亚马逊控制台
- 打开 Amazon DynamoDB
- 创建表,填写表名、主键(分区键 / 排序键)
- 可选:配置 TTL(自动过期字段)、索引等
Java SDK 建表(适合自动化)
CreateTableRequest request = CreateTableRequest.builder()
.tableName("UserTable")
.keySchema(
KeySchemaElement.builder().attributeName("user_id").keyType(KeyType.HASH).build()
)
.attributeDefinitions(
AttributeDefinition.builder().attributeName("user_id").attributeType(ScalarAttributeType.S).build()
)
.billingMode(BillingMode.PAY_PER_REQUEST) // 推荐:按需计费
.build();
dynamoDbClient.createTable(request);
Spring Boot 集成 DynamoDB(Enhanced Client 版本)
添加依赖
在 pom.xml
中添加:
<dependencies>
<!-- DynamoDB Enhanced Client -->
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>dynamodb-enhanced</artifactId>
<version>2.30.38</version>
</dependency>
<!-- AWS SDK BOM 管理 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>bom</artifactId>
<version>2.30.38</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</dependencies>
配置 DynamoDbClient 和 Enhanced Client
@Configuration
public class DynamoDbConfig {
@Value("${aws.region}")
private String region;
@Bean
public DynamoDbClient dynamoDbClient() {
return DynamoDbClient.builder()
.region(Region.of(region))
.credentialsProvider(ProfileCredentialsProvider.create()) // 本地用 profile,部署时可用 IAM 角色
.build();
}
@Bean
public DynamoDbEnhancedClient dynamoDbEnhancedClient(DynamoDbClient dynamoDbClient) {
return DynamoDbEnhancedClient.builder()
.dynamoDbClient(dynamoDbClient)
.build();
}
}
application.yml 配置:
aws:
region: ap-east-1 # 香港区域
配置秘钥
本地开发可通过 ~/.aws/credentials
文件配置:
[default]
aws_access_key_id=xxx
aws_secret_access_key=yyy
部署在亚马逊云上(如 Lambda / ECS)时,推荐使用 IAM Role 自动授权,无需配置秘钥。
定义实体类
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.*;
import lombok.*;
@Data
@NoArgsConstructor
@AllArgsConstructor
@DynamoDbBean
public class User {
private String userId;
private String name;
private Integer age;
@DynamoDbPartitionKey
@DynamoDbAttribute("user_id")
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
}
注解说明
注解名 | 作用 |
---|---|
@DynamoDbBean |
标识该类为 DynamoDB 表映射实体 |
@DynamoDbPartitionKey |
表示该字段是主键(分区键) |
@DynamoDbAttribute |
指定字段映射到表中的哪个属性名(可选) |
创建 Repository 类(封装 CRUD)
import org.springframework.stereotype.Repository;
import software.amazon.awssdk.enhanced.dynamodb.*;
import software.amazon.awssdk.enhanced.dynamodb.model.*;
import java.util.Optional;
@Repository
public class UserRepository {
private final DynamoDbTable<User> userTable;
public UserRepository(DynamoDbEnhancedClient enhancedClient) {
this.userTable = enhancedClient.table("UserTable", TableSchema.fromBean(User.class));
}
public void save(User user) {
userTable.putItem(user);
}
public User findById(String userId) {
return userTable.getItem(Key.builder().partitionValue(userId).build());
}
public void delete(String userId) {
userTable.deleteItem(Key.builder().partitionValue(userId).build());
}
public void updateAge(String userId, int newAge) {
User user = findById(userId);
user.setAge(newAge);
save(user);
}
}
关键方法说明
-
putItem()
:自动插入或覆盖 -
getItem()
:按主键查询 -
deleteItem()
:按主键删除
使用示例
@RestController
@RequestMapping("/users")
@RequiredArgsConstructor
public class UserController {
private final UserRepository userRepository;
@PostMapping
public ResponseEntity<?> createUser(@RequestBody User user) {
userRepository.save(user);
return ResponseEntity.ok("User created");
}
@GetMapping("/{id}")
public ResponseEntity<?> getUser(@PathVariable String id) {
return userRepository.findById(id)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
@DeleteMapping("/{id}")
public ResponseEntity<?> deleteUser(@PathVariable String id) {
userRepository.delete(id);
return ResponseEntity.ok("Deleted");
}
@PatchMapping("/{id}/age")
public ResponseEntity<?> updateAge(@PathVariable String id, @RequestParam int age) {
userRepository.updateAge(id, age);
return ResponseEntity.ok("Updated");
}
}
注意事项
- DynamoDB 没有传统 SQL 的“唯一索引”概念,分区键 + 排序键就是数据的唯一标识。
- 没有 JOIN,没有聚合函数,不能随便 WHERE name LIKE '%abc%'。
- 全表扫描不推荐用于生产,最好使用 Query 按键查询
- 分页查询/索引查询 建议使用 GSI(Global Secondary Index)
- 单条记录最多 400KB ,注意字段大小限制
更详细的 DynamoDB 使用教程,可以参考 DynamoDB 开发人员指南。
总结
使用 DynamoDB 你只需要:
- 写 POJO + Repository
- 调用标准方法(putItem、getItem)
- 享受自动扩容 + 免费额度的快乐生活
哪些项目适合用 DynamoDB?
别的不好说,只要你项目具备以下特点,DynamoDB 都是非常棒的选择:
场景 | 适合程度 |
---|---|
简单 API 服务 | ✅✅✅ |
小程序 / H5 用户数据 | ✅✅✅ |
数据收集类项目(问卷、打点) | ✅✅✅ |
低频后台任务(定时记录) | ✅✅ |
数据需要复杂查询、关联表的 | ❌(慎用) |
总之就是一句话:“轻量、快速、便宜、省事”,那就选 DynamoDB 没跑了。
友情提示:如果用完了之后不再需要使用服务的话,记得要在控制台关闭服务,以防超过免费额度产生扣费