如何使用MongoDB+Springboot实现分布式ID?

一、背景

如何实现分布式id,搜索相关的资料,一般会给出这几种方案:

  • 使用数据库自增Id
  • 使用reids的incr命令
  • 使用UUID
  • Twitter的snowflake算法
  • 利用zookeeper生成唯一ID
  • MongoDB的ObjectId

另外,在我通过爬取知乎用户id发现,知乎的用户id是32位的,初步断定知乎采用的是md5加密,然后全部转换成小写。至于如何爬取知乎用户信息,见我之前分享的文章。本文采取的技术方案采取的是mogoodb的objectId。

二.mongodb如何实现分布式ID

MongoDB的ObjectId设计成轻量型的,不同的机器都能用全局唯一的同种方法方便地生成它。MongoDB 从一开始就设计用来作为分布式数据库,处理多个节点是一个核心要求。使其在分片环境中要容易生成得多。

它的格式:

  • 前4 个字节是从标准纪元开始的时间戳,单位为秒。时间戳,与随后的5 个字节组合起来,提供了秒级别的唯一性。由于时间戳在前,这意味着ObjectId 大致会按照插入的顺序排列。这对于某些方面很有用,如将其作为索引提高效率。这4 个字节也隐含了文档创建的时间。绝大多数客户端类库都会公开一个方法从ObjectId 获取这个信息。
  • 接下来的3 字节是所在主机的唯一标识符。通常是机器主机名的散列值。这样就可以确保不同主机生成不同的ObjectId,不产生冲突。 为了确保在同一台机器上并发的多个进程产生的ObjectId 是唯一的,接下来的两字节来自产生ObjectId 的进程标识符(PID)。
  • 前9 字节保证了同一秒钟不同机器不同进程产生的ObjectId 是唯一的。
  • 后3 字节就是一个自动增加的计数器,确保相同进程同一秒产生的ObjectId 也是不一样的。同一秒钟最多允许每个进程拥有2563(16 777 216)个不同的ObjectId。

三、编码

在springboot中引入mongodb:

       <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- 开启web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>


       <!--mongodb -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>

创建一个实体类:

public class Customer {

    @Id
    public String id;

    public String firstName;
    public String lastName;

    public Customer() {}

    public Customer(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    @Override
    public String toString() {
        return String.format(
                "Customer[id=%s, firstName='%s', lastName='%s']",
                id, firstName, lastName);
    }


    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}

创建mongodb 接口类:

/**
 * Created by fangzhipeng on 2017/4/1.
 */


public interface CustomerRepository extends MongoRepository<Customer, String> {

    public Customer findByFirstName(String firstName);
    public List<Customer> findByLastName(String lastName);

}

测试类:

 @Autowired
    CustomerRepository customerRepository;


@Test
public void mongodbIdTest(){
Customer customer=new Customer("lxdxil","dd");
        customer=customerRepository.save(customer);
        logger.info( "mongodbId:"+customer.getId());
}

四、参考资料

Accessing Data with MongoDB

MongoDB深究之ObjectId

MongoDB 教程

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏草根专栏

.NET Core/.NET之Stream简介

之前写了一篇C#装饰模式的文章提到了.NET Core的Stream, 所以这里尽量把Stream介绍全点. (都是书上的内容) .NET Core/.NET的...

3574
来自专栏大内老A

ASP.NET Core的配置(3): 将配置绑定为对象[上篇]

出于编程上的便利,我们通常不会直接利用ConfigurationBuilder创建的Configuration对象读取某个单一配置项的值,而是倾向于将一组相关的...

2016
来自专栏DOTNET

.Net多线程编程—Parallel LINQ、线程池

Parallel LINQ 1 System.Linq.ParallelEnumerable 重要方法概览: 1)public static ParallelQ...

2907
来自专栏iOS开发

iOS开发之 Method Swizzling 深入浅出

如果产品经理突然说:"在所有页面添加统计功能,也就是用户进入这个页面就统计一次"。我们会想到下面的一些方法:

4657
来自专栏大内老A

[ASP.NET MVC]通过对HtmlHelper扩展简化“列表控件”的绑定

在众多表单元素中,有一类<select>元素用于绑定一组预定义列表。传统的ASP.NET Web Form中,它对应着一组重要的控件类型,即ListContro...

1765
来自专栏恰同学骚年

.NET基础拾遗(4)委托、事件、反射与特性

  委托这个概念对C++程序员来说并不陌生,因为它和C++中的函数指针非常类似,很多码农也喜欢称委托为安全的函数指针。无论这一说法是否正确,委托的的确确实现了和...

802
来自专栏码农分享

LinqToExcel.Extend 源码分析

展开目录结构,我们能够更加请详细的分析出每个目录所完成的功能模块。 这里主要讲解工具集中最重要的一个模块Validate

1304
来自专栏Java与Android技术栈

用kotlin打印出漂亮的android日志(三)——基于责任链模式打印任意对象

SAF-Kotlin-log 是一个Android的日志框架,这几天我抽空重新更新了一下代码。

871
来自专栏mini188

java中的锁

java中有哪些锁 这个问题在我看了一遍<java并发编程>后尽然无法回答,说明自己对于锁的概念了解的不够。于是再次翻看了一下书里的内容,突然有点打开脑门的感觉...

2219
来自专栏QQ音乐技术团队的专栏

iOS 中的 Promise 设计模式

无论是代理模式,还是闭包,在处理单一任务的时候,都出色的完成了任务。可是当两种模式要相互配合,一起完成一系列任务,并且每个任务之间还要共享信息,相互衔接,雇主就...

1900

扫码关注云+社区