MongoDB分布式id生成策略

举报
tea_year 发表于 2024/02/28 22:21:07 2024/02/28
【摘要】 MongoDB的文档必须有一个_id键。目的是为了确认在集合里的每个文档都能被唯一标识。ObjectId 是 _id 的默认类型。ObjectId 采用12字节的存储空间,每个字节两位16进制数字,是一个24位的字符串。12位生成规则:[0,1,2,3] [4,5,6] [7,8] [9,10,11]时间戳 |机器码 |PID |计数器  前四字节是时间戳,可以提供秒级别的唯一性。  接下来...

MongoDB的文档必须有一个_id键。

目的是为了确认在集合里的每个文档都能被唯一标识。

ObjectId 是 _id 的默认类型。

ObjectId 采用12字节的存储空间,每个字节两位16进制数字,是一个24位的字符串。


12位生成规则:


[0,1,2,3] [4,5,6] [7,8] [9,10,11]


时间戳 |机器码 |PID |计数器


  前四字节是时间戳,可以提供秒级别的唯一性。

  接下来三字节是所在主机的唯一标识符,通常是机器主机名的散列值。

接下来两字节是产生ObjectId的PID,确保同一台机器上并发产生的ObjectId是唯一的。  最后三字节是自增计数器,确保相同进程同一秒钟产生的ObjectId是唯一的。前九字节保证了同一秒钟不同机器的不同进程产生的ObjectId时唯一的。


由此可得,在对数据库数据进行排序/查询时,可以直接根据_id来进行排序/查询(因为生成规则前四字节是时间戳,有秒级的唯一性)

 代码示例:

//举例说明:例如要查询 30天之前的一整天的mongo记录

public static void main(String[] args) throws ParseException {

LocalDateTime ltDate = LocalDateTime.now().plusDays(-30);

LocalDateTime gtDate = LocalDateTime.now().plusDays(-29);

System.out.println("ltDate:" + ltDate);

System.out.println("gtDate:" + gtDate);

String ltDateTimeStampHex = mongoIdHandler(getDate(ltDate));

System.out.println("$lt:" + ltDateTimeStampHex);

String gtDateTimeStampHex = mongoIdHandler(getDate(gtDate));

System.out.println("$gt:" + gtDateTimeStampHex);




BasicDBObject cond = new BasicDBObject();

//_id的查询条件是时间

BasicDBObject time = new BasicDBObject();

cond.put("_id", time);

time.put("$lt", new ObjectId(ltDateTimeStampHex));

time.put("$gt", new ObjectId(gtDateTimeStampHex));


}


private static Date getDate(LocalDateTime localDateTime){

ZoneId zone = ZoneId.systemDefault();

Instant instant = localDateTime.atZone(zone).toInstant();

java.util.Date date = Date.from(instant);

return date;

}



/**

* 根据时间获取秒,根据秒转化16进制,再补16个0 补齐24位

*

* @param date 日期

* @return {@link String}

*/

private static String mongoIdHandler(Date date) {

//获取秒

long secondTimstamp = date.getTime() / 1000;

//将秒转换为16进制

String strHex = Long.toHexString(secondTimstamp);

//将16进制后边补充16个0

String _id = strHex + "0000000000000000";

return _id;

}

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。