过期数据的清理问题,一直是数据库界的一个问题,处理的方式很多,大部分都是通过存储过程,或者定期使用第三方工具来进行处理。MONGODB 处理过期数据的方面,可以使用类似REDIS expired key 的概念,创建TTL index 来通过时间的方式处理过期数据。
这样处理的方式的好处
1 简单方便
2 通过数据库系统本身的方式来处理,高效安全
3 数据库会根据自身的性能以及数据库状态来自动判断是否开始清理数据,而不是和存储过程,或其他的方式,到时间就去处理,不管数据库当前的情况野蛮操作。
TTL 索引本身是一种特殊的单字段索引,通过普通创建索引的方式辅助expiredAfterSecond 选项就可以创建一个字段,字段的值需要为日期型,或者带有日期类型的数组。
那我们先的理解什么是日期型数据,在MONGODB是怎么体现的
1 由于mongodb本身是分布式数据库,在设计之初时间的概念是UTC的概念所以mongodb的时间类型的 isodate ,以世界的0时区作为统一的时间的表达,并没有时区的概念,所以看到的时间应该在你自己的时区进行 增加或减少对应的时间。
2 MONGODB 中可以返回时间的函数(以目前最新的版本 4.2)有两个 Date(), new Date() , 前一个返回的是字符类型的值,后一个返回的是UTC的时间。具体如何调整new Date() 返回的时间值,可以参看文档。
下面是自动生成的测试数据
测试数据中只有creationDate是ISODATE类型,也只有这个字段可以作为判断数据是否过期的唯一标准字段。添加索引需要在保存BSON日期类型的值或者对象数组的字段上创建TTL 索引,并且在expireAfterSeconds指定一个非负的非零值。当字段中的秒数超过其索引指定的时间后,文档会过期,然后开始清理。
从测试来看,删除文档的速度比较快。
下面有几点是TTL 索引需要知道的
1 TTL 索引不保证在生成索引后,立即开始删除过期数据
2 不支持联合索引
3 删除文档的调度任务60秒运行一次
4 负载过重的系统,将跳过任务调度,以系统提供正常服务为优先
5 复制集成员的非主成员,不会自动删除数据,只接受主库发来的delete指令
6 TTL 索引本身支持查询使用,
7 在索引建立后,不能改变expireAfterSeconds 的值,需要删除索引,在重新建立,所以添加数值的时候,一定算好。
8 建立TTL的字段,不能是其他已有索引的字段,否则无法添加expired功能
通过 db.serverStatus() 可以查看删除文档的数量
当然也可以通过日志来监控删除日志的操作,
默认监控的方式是关闭的,需要使用下面的命令来打开
db.setLogLevel(1,"index")
或者不需要监控,可以通过下面的命令来将监控关掉
db.adminCommand({setParameter:1, ttlMonitorEnabled:false})