MongoDB---使用TTL索引自动删除过期数据
目录一、前序二、TTL索引介绍三、TTL索引生效机制四、创建TTL索引五、修改TTL索引的expireAfterSeconds属性值六、动态指定TTL索引的过期时间七、TTL索引使用限制条件八、验证TTL索引功能一、前序由于公司业务需求,对于1个月前的过期数据需要进行删除,以释放空间和方便维护。本来想使用crontab写个脚本定时执行删除操作,但是看到Mongo本身就有自动删除过期数据的功能,就是
目录
五、修改TTL索引的expireAfterSeconds属性值
一、前序
由于公司业务需求,对于1个月前的过期数据需要进行删除,以释放空间和方便维护。
本来想使用crontab写个脚本定时执行删除操作,但是看到Mongo本身就有自动删除过期数据的功能,就是使用TTL索引。决定使用TTL自动索引,这样就不用再写一个脚本以完成定时删除的任务。
二、TTL索引介绍
TTL索引是MongoDB中一种特殊的索引, 可以支持文档在一定时间之后自动过期删除。目前,TTL索引只能在单字段上建立,并且字段类型必须是date类型或者包含有date类型的数组(如果数组中包含多个date类型字段,则取最早时间为过期时间)。
官网介绍链接:https://docs.mongodb.com/v3.2/core/index-ttl/
三、TTL索引生效机制
当你在集合中某一个字段建立TTL索引后,后台会有一个单线程,通过不断查询(默认60s一次)索引的值来判断document是否有过期,并且删除文档的动作还依据mongod实例的负载情况,如果负载很高,可能会稍微延后一段时间再删除。
还有一个需要注意的地方:在复制集成员中,TTL后台线程只删除primary实例的过期数据;如果此实例变为secondary角色,则后台线程闲置。
四、创建TTL索引
和普通索引的创建方法一样,只是会多加一个expireAfterSeconds属性而已。
例:在log_events的集合中,createTime 字段上建立“一小时后过期的TTL索引”。
>db.log_events.createIndex( { "createTime": 1 }, ---字段名称
{ expireAfterSeconds: 60*60 } ) ---过期时间(单位秒)
>db.log_events.getIndexes() ---查看索引
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "tt.t1"
},
{
"v" : 1,
"key" : {
"createTime" : 1
},
"name" : "createTime_1",
"ns" : "tt.t1",
"expireAfterSeconds" : 3600
}
]
五、修改TTL索引的expireAfterSeconds属性值
如果想更改过期时间expireAfterSeconds,可以使用collMod方法;否则,只能使用dropIndex()和createIndex()方法重建索引,这种方法在亿级数据量下可能会有性能问题。
db.runCommand( { collMod: "log_events", ---集合名
index: { keyPattern: { createTime: 1 }, ---createTime为具有TTL索引的字段名
expireAfterSeconds: 7200 ---修改后的过期时间(秒)
}})
虽然上面的方法可以实现自动过期删除,但是频繁删除数据势必会增加负载,所以必须在业务量少的时段,定时删除过期数据和修改超时属性值。
六、动态指定TTL索引的过期时间
增加一个expireTime字段(用于指定过期时间),expireAfterSeconds属性值设置为0。在插入文档时,需要指定expireTime的值。这样,上面的createTime字段就不需要再有TTL索引了。
>db.log_events.createIndex( { "expireTime": 1 }, ---字段名称
{ expireAfterSeconds: 0 } ) ---过期时间(单位秒)
>db.log_events.insert( {
"expireTime": new Date('Jan 22, 2016 23:00:00'), ---此文档将在2016-1-22的23点自动删除
"logEvent": 2,
"logMessage": "Success!"} )
如上,我们就实现了指定过期时间自动删除文档。
七、TTL索引使用限制条件
以下几种情况无法使用TTL索引:
① TTL索引是单字段索引,混合索引不支持TTL,并且也会忽略expireAfterSeconds属性。
② 在_id 主键上不能建立TTL索引。
③ 在capped collection中不能建立TTL索引,因为MongoDB不能从capped collection中删除文档。
④ 不能使用createIndex()去更改已经存在的TTL索引的expireAfterSeconds值。如果想更改expireAfterSeconds,可以使用collMod命令;否则,只能删除索引,然后重建。
⑤ 不能在已有索引的字段上再创建TTL索引了。如果想把非TTL索引改为TTL索引,那就只能先删除非TTL索引,然后新建TTL索引。
八、验证TTL索引功能
虽然已经实现了“动态指定过期时间自动删除数据”的功能,但是还是担心大量删除过期数据可能导致mongo服务器负荷问题。于是,进行了简单测试,查看TTL索引在亿级别集合中删除140万过期数据的消耗。
测试机器的配置:
OS:Vm虚拟机
CPU: 4
内存:8
集合数据量:
> db.t1.count()
共有104675629条文档记录。
在制造测试数据时指定_id是顺序增加的,验证步骤:
第1步,直接查看_id=1500000那条数据的createTime;
第2步,计算一下此createTime和当前时间的时间差;
第3步:根据这个时间差,更改expireAfterSeconds的值,以让这150万数据在5分钟后过期;
第4步:在修改完expireAfterSeconds后,等待“ vmstat 1 ” 命令的输出数据。
我的测试结果:
整个删除操作过程在90秒左右完成;
CPU最高占用90%,平均在50%;
内存占用3G。
这个不是特别准确的线上测试,只是粗略了解一下TTL索引的资源消耗,以决定是不是需要使用这种方式来实现删除过期数据
监控vmstat的截图:
更多推荐
所有评论(0)