欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

分布式自增id生成算法SnowFlake

程序员文章站 2022-05-03 19:14:08
...

分布式id生成算法的有很多种,Twitter的SnowFlake就是其中经典的一种。

概述

SnowFlake算法生成id的结果是一个64bit大小的整数,它的结构如下图:

分布式自增id生成算法SnowFlake

  • 1位,不用。二进制中最高位为1的都是负数,但是我们生成的id一般都使用整数,所以这个最高位固定是0
    41位,用来记录时间戳(毫秒)。
  • 41位可以表示241−1个数字,如果只用来表示正整数(计算机中正数包含0),可以表示的数值范围是:0 至 241−1,减1是因为可表示的数值范围是从0开始算的,而不是1。
    也就是说41位可以表示241−1个毫秒的值,转化成单位年则是(241−1)/(1000∗60∗60∗24∗365)=69年
  • 10位,用来记录工作机器id。可以部署在210=1024个节点,包括5位datacenterId和5位workerId
    5位(bit)可以表示的最大正整数是25−1=31,即可以用0、1、2、3、….31这32个数字,来表示不同的datecenterId或workerId
  • 12位,***,用来记录同毫秒内产生的不同id。12位(bit)可以表示的最大正整数是212−1=4095,即可以用0、1、2、3、….4094这4095个数字,来表示同一机器同一时间截(毫秒)内产生的4095个ID序号

由于在Java中64bit的整数是long类型,所以在Java中SnowFlake算法生成的id就是long来存储的。

SnowFlake可以保证:

1、所有生成的id按时间趋势递增
2、整个分布式系统内不会产生重复id(因为有datacenterId和workerId来做区分)

java实现如下(单例模式、线程安全):

package com.project.company.web;

import com.project.company.entity.Company;
import com.project.company.service.ICompanyService;
import com.project.company.util.IdGenter;
import com.project.company.util.Response;
import com.project.company.util.Result;
import org.apache.catalina.ssi.ResponseIncludeWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/company")
public class CompanyController {

    @Autowired
    private ICompanyService companyService;

    @RequestMapping(value = "/list", method = RequestMethod.GET)
    public Result getCompanys()
    {
        List<Company> list = companyService.findCompanyList();
        return Response.success(list);
    }

    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    public Result getCompanyById(@PathVariable("id") long id)
    {
        Company company = companyService.findCompanyById(id);
        return Response.success(company);
    }

    @RequestMapping(value = "", method = RequestMethod.POST)
    public Result postCompany(@RequestParam(value = "name", required = true) String name,
                              @RequestParam(value = "status", required = true) int status)
    {
        Company company = new Company();
        company.setName(name);
        company.setStatus(status);
        int res = companyService.add(company);
        if(res == 1)
        {
            return Response.success();
        }
        else
        {
            return Response.error(-1, "fail");
        }
    }

    @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
    public Result updateCompany(@PathVariable("id") long id,
                                @RequestParam(value = "name", required = true) String name,
                                @RequestParam(value = "status", required = true) int status)
    {
        Company company = new Company();
        company.setName(name);
        company.setStatus(status);
        company.setId(id);
        int res = companyService.update(company);
        if(res == 1)
        {
            return Response.success();
        }
        else
        {
            return Response.error(-1, "fail");
        }
    }

    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
    public Result deleteCompany(@PathVariable("id") long id)
    {
        int res = companyService.delete(id);
        if(res == 1)
        {
            return Response.success();
        }
        else
        {
            return Response.error(-1, "fail");
        }
    }

    @RequestMapping(value = "/idgenter", method = RequestMethod.GET)
    public Result getId()
    {
        long id = IdGenter.getInstance().nextId();
        return Response.success(id);
    }
}

调用:

long id = IdGenter.getInstance().nextId();

本篇文章参考自《理解分布式id生成算法SnowFlake》,更详细信息请移步至该文章。