mongodb 设置自动删除过期数据

MongoDB的集合有衣蛾 TTL (即 time to live,即生存的时间) 的特性。TTL可以让mongodb自动移除过期了的数据,(咦,这岂不是正好符合日志类的数据诉求)。这种机制便比较适合一些 日志数据 机器产生的事件数据 甚至可以用来做 session会话

MongoDB 通过一个 TTL 索引来实现这种所谓的 TTL 集合。该特性的实现机制是: mongod 通过一个后台线程去不断的读取集合中某个日期类型的索引,并且移除掉满足过期条件的文档documents。

创建 TTL 索引

我们是通过 db.collection.createIndex() 命令配合 expireAfterSeconds 选项来对集合中某个字段做TTL索引。这个字段必须是 date 类型或者是一个包含 date 类型值的数组字段。

创建 TTL 过期规则的话,有 2 种模式:

  • 一种是类似于前端的maxAge模式,即设置一个时长,当mongodb发现当前时间与时间索引字段的时差超过了maxAge,则认为过期
  • 另一种是类似前端的 expireTime 模式。即设置一个过期时间点,当mongodb发现当前系统时间已经超过那个时间点,则认为记录过期

下面我们分别看下两种模式的设置方式。

在一个特定的时长之后删除文档

首先创建索引,设置过期时间,这里设置3600秒 createdAt为数据字段,这里意思为数据参见时间

db.logs.createIndex( { "createdAt": 1 }, { expireAfterSeconds: 3600 } )

其中 createdAt: 1 表示对 createdAt 字段建立正序的索引。选项 expireAfterSeconds 表示 3600秒(即1小时) 之后过期。其含义是,在createdAt字段的值的时刻基础上,再加上 3600秒 之后的那个时间过期。

在一个特定的时间点来删除文档

还有一是指定失效时间,与上面的设置类似,首先建立索引,设置 expireAfterSeconds 为 0

db.logs.createIndex( { "expireAt": 1 }, { expireAfterSeconds: 0 } )

然后存储数据,设置expireAt为过期时间即可,等时间到达expireAt的值时,这个文档就 失效了。


在Spring Boot中测试

新增如下配置

/**
 * 数据失效配置
 * <p>
 * 创建索引
 * db.gps.createIndex( { "expireAt": 1 }, { expireAfterSeconds: 0 } );
 * db.logs.createIndex( { "expireAt": 1 }, { expireAfterSeconds: 0 } );
 *
 * @author ruan
 */
@Data
@Configuration
@EnableConfigurationProperties
@ConfigurationProperties(prefix = DataExpireConfig.PREFIX)
public class DataExpireConfig {

    public static final String PREFIX = "record";

    /**
     * key :对应数据库中集合 名字; 目前只有 gps, logs
     */
    private Map<String, ExpireTimeConfig> expireConfig = Collections.emptyMap();

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    static class ExpireTimeConfig {
        public static final ExpireTimeConfig DEFAULT = new ExpireTimeConfig();
        /**
         * 凌晨 02:00:00
         */
        @DateTimeFormat(pattern = "HH:mm:ss")
        private LocalTime time = LocalTime.of(2, 0, 0);

        /**
         * 90 天
         */
        private Integer expirationDays = 90;
    }

    /**
     * 根据集合名字获取失效时间
     *
     * @param collectionName 对应数据集合名字
     * @return 具体失效时间
     */
    public LocalDateTime getExpireTime(String collectionName) {
        ExpireTimeConfig config = this.expireConfig.getOrDefault(collectionName, ExpireTimeConfig.DEFAULT);
        return LocalDate.now().plusDays(config.getExpirationDays()).atTime(config.getTime());
    }
}

然后在保存数据时设置失效时间即可

gps.setExpireAt(dataExpireConfig.getExpireTime("gps"));
//数据存储到mongoDB
mongoTemplate.save(gps);

参考:https://segmentfault.com/a/1190000023869743

文章目录