Spring boot MongoDB实现自增序列

在某些特定的业务场景下,会需要使用自增的序列来维护数据,目前项目中因为使用MongoDB,顾记录一下如何使用MongoDB实现自增序列。

MongoDB自增序列原理

MongoDB本身不具有自增序列的功能,但是MongoDB的$inc操作是具有原子性的,因为操作的原子性,那么就可以通过$inc序列+1的值作用本次序列,实现自增序列。

实现自增序列

定义自增序列IdSequence.java

@Document(collection = "sequences")
@Data
public class IdSequence {
    @Id
    private String id;
    /**
     * 自增的序列
     */
    private long nextId;
}

定义自增序列类型枚举IdType.java

@Getter
@AllArgsConstructor
public enum IdType {
    /**
     * 图书
     */
    BOOK("book");
    private final String type;
}

定义获取自增序列辅助类IdHelper.java

@Component
public class IdHelper {
    private final MongoTemplate mongoTemplate;

    public IdHelper(MongoTemplate mongoTemplate) {
        this.mongoTemplate = mongoTemplate;
    }

    /**
     * 查询指定类型的自增序列
     *
     * @param idType 类型
     * @return 自增序列
     */
    public long nextId(IdType idType) {
        //构建查询对象
        Query query = Query.query(Criteria.where(LambdaUtil.getFieldName(IdSequence::getId)).is(idType.getType()));
        //构建自增条件
        Update update = new Update().inc(LambdaUtil.getFieldName(IdSequence::getNextId), 1L);
        //构建选项
        FindAndModifyOptions options = FindAndModifyOptions.options().upsert(true).returnNew(true);
        //查询自增序列
        IdSequence idSequence = mongoTemplate.findAndModify(query, update, options, IdSequence.class);
        //返回自增序列
        return Objects.requireNonNull(idSequence).getNextId();
    }
}

定义测试类

@RestController
@RequestMapping(value = "/id")
public class IdSequenceController {
    @Resource
    private IdHelper idHelper;

    @GetMapping(value = "/nextId")
    public long nextId() {
        return idHelper.nextId(IdType.BOOK);
    }

}

总结

使用MongoDB实现自增序列是基于MongoDB的$inc操作指令,经过测试100个并发下没有发现重复id的产生,但是还是建议使用MongoDB自己的Id生成策略,毕竟MongoDB作为非关系型数据库,如果维护一个自增序列,性能上肯定没有ObjectId好,而且分片情况下需要自己校验自增序列的唯一性,当然在某些特殊的业务场景下必须要使用自增序列的,也属于正常,如果大家有更好的方案,欢迎讨论。

你可能感兴趣的:(系统架构,Mongodb,开发总结,spring,boot,mongodb,python)