MongoDB分布式id生成策略
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; } |
- 点赞
- 收藏
- 关注作者
评论(0)