DynamoDB 的 TimeToLive(TTL)是一种后台自动删除机制。设置后,表会按照每行写入的过期时间戳判断数据是否已过期,并在条件满足后由服务端异步清理。它特别适合保存登录会话、短期缓存、验证码、临时日志等有明确生命周期的数据。与手动删除相比,TTL 不需要额外编写定时扫描任务,也不会占用预置写容量,可以在低维护成本下控制表体积。要使用这项能力,关键是选对一个属性,并让它的值满足 DynamoDB 的时间格式要求。

一、TTL 的工作原理与前置条件
DynamoDB 的 TTL 机制并不像 Redis 的键过期那样具备实时性。它依赖后台任务扫描表,将已满足过期条件的项目标记为删除。官方没有承诺删除在到期后立即发生,实际体验中通常会延迟几分钟到几小时,在数据量较大时甚至可能超过一天。因此,如果业务流程要求用户在某一时刻后绝对无法读到记录,TTL 只能作为最终清理手段,不能替代应用层的条件过滤。
配置 TTL 前需要确认两件事。第一,用于存储过期时间的属性必须是 Number 或 String 类型,其他类型会被忽略。第二,属性值必须是 Unix 时间戳,精度为秒。下面这条数据中的 ttl 属性就是一个合法的过期时间示例:
{
"userId": "u123",
"sessionId": "sess-456",
"ttl": 1717200000
}
如果业务系统使用 Java 或 JavaScript 生成时间戳,要特别小心毫秒和秒的区别。Java 的 System.currentTimeMillis() 返回毫秒,直接写入会导致过期时间被推后约 50 万年。DynamoDB 将 String 类型的时间戳做数字解析,所以可以写入 "1717200000",但不能写入 "2024-06-01T00:00:00Z" 这类带格式的日期文本。
二、通过控制台与 AWS CLI 启用 TTL
在 AWS 管理控制台中,进入目标表的 Overview 页面,找到 Time to live 设置,点击 Manage TTL 或 Enable,输入属性名,例如 ttl,然后保存。控制台会显示当前状态为 Enabled。如果表位于某个 CloudFormation 栈中,手动修改后可能产生配置漂移,建议同时更新基础设施代码。
使用 AWS CLI 时,update-time-to-live 命令可以完成相同操作。以下示例给 Sessions 表启用 TTL,并指定属性名为 ttl:
aws dynamodb update-time-to-live \
--table-name Sessions \
--time-to-live-specification "Enabled=true, AttributeName=ttl"
执行后可以通过 describe-time-to-live 查看配置和状态:
aws dynamodb describe-time-to-live --table-name Sessions
返回结果中的 TimeToLiveStatus 会变为 ENABLED。注意配置下发需要短暂时间,但通常几分钟内就会开始对新的写入生效。对于已经存在的过期数据,后台任务并不会一次性全部删除,而是根据表的分区分布逐步处理。
三、用 SDK 和 CloudFormation 统一管理 TTL
在自动化脚本中,使用 AWS SDK 可以避免手工维护属性名和执行命令。Python 的 boto3 示例如下:
import boto3
dynamodb = boto3.client('dynamodb')
response = dynamodb.update_time_to_live(
TableName='Sessions',
TimeToLiveSpecification={
'Enabled': True,
'AttributeName': 'ttl'
}
)
print(response['TimeToLiveSpecification'])
这段代码的核心参数与 CLI 相同,只是结构换成了字典。对多环境部署来说,建议把表名和 TTL 属性名抽到配置文件中,避免测试环境与生产环境使用不同字段。若应用需要切换 TTL 属性名,例如从 expires_at 改为 ttl,需要先调用 update_time_to_live 传入新的属性名并保持 Enabled 为 True,系统会覆盖原有配置。
如果使用 CloudFormation 管理 DynamoDB,可以在表资源里直接声明 TimeToLiveSpecification:
Resources:
SessionsTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: Sessions
BillingMode: PAY_PER_REQUEST
AttributeDefinitions:
- AttributeName: userId
AttributeType: S
KeySchema:
- AttributeName: userId
KeyType: HASH
TimeToLiveSpecification:
AttributeName: ttl
Enabled: true
这样可以保证新建表时 TTL 直接启用,不需要部署后再执行脚本。对于全局表,每个副本区域都需要应用相同的 TTL 配置。CloudFormation 的 AWS::DynamoDB::GlobalTable 资源支持在 Replicas 中逐个副本设置 TimeToLiveSpecification,必须确保属性名在各区域保持一致。
四、验证删除效果与排查常见问题
验证 TTL 是否真正生效,最简单的方法是写入一条已经过期的数据。以下命令向表里插入一条过期时间为过去的数据:
aws dynamodb put-item \
--table-name Sessions \
--item '{"userId": {"S": "u-expired"}, "ttl": {"N": "1716990000"}}'
插入成功后可以等待几分钟,再用 scan 查看该 userId 是否还存在。需要注意的是,DynamoDB 的 Scan 默认是最终一致读取,TTL 删除又是异步任务,所以即使数据已经被后台删除,短时间内仍可能读取到。建议在业务代码中同时加上条件判断,例如读取时比较当前时间与 ttl,不要把 TTL 当作强一致边界。
如果等待数小时后仍能稳定读到过期数据,可以从几个方向排查。先用 describe-time-to-live 确认状态和属性名;再检查实际写入的数据类型和时间戳单位,毫秒值、ISO 日期、空字符串都会导致无法过期。还可以观察 CloudWatch 中的 TimeToLiveDeletedItemCount 指标,确认后台是否正在产生删除。若表数据量特别大,删除速度会受分区吞吐和后台任务调度影响,需要更长时间完成。
五、TTL 设计建议与常见误区
TTL 最适合存放生命周期明确的临时数据,例如登录会话、验证码、设备心跳、短期购物车和日志归档。这些数据即使晚删除几分钟也不会影响业务。对于订单、支付流水、审计日志等需要长期保留或精确清理的数据,不要依赖 TTL。因为一旦后台任务开始删除,数据无法恢复,而且删除记录可能通过 DynamoDB Streams 被下游消费,容易与用户主动删除混淆。
写入过期时间时应尽量由服务端或写入端计算绝对时间戳,而不是把基础时间字段直接当作 TTL。比如业务想保留 30 天,应在写入时计算 now + 30 * 24 * 60 * 60 并写成一个新属性。这样 TTL 属性只表达一件事:这条数据何时过期。避免把 lastUpdated 这类业务字段同时用于删除判断,否则后续调整保留策略会非常困难。
另一个容易忽略的问题是 DynamoDB Streams。TTL 删除会生成 REMOVE 事件,Lambda 消费者需要根据 eventName 区分删除来源。对于使用全局二级索引的表,TTL 删除通常会同步移除索引项,但读取全局二级索引时仍可能遇到最终一致导致的数据残留。最后,如果表启用了 PITR 备份,备份中可能保留过期但尚未被后台删除的数据,恢复时这些数据会再次出现并触发新的 TTL 删除流程。
DynamoDB TTL数据自动过期属性设置修改时间:2026-09-23 16:54:59