概述

前一篇文章讲述了最流行的分布式ID生成算法snowflake,本篇文章根据美团点评分布式ID生成系统文章,介绍另一种相对更容易理解和编写的分布式ID生成方式。

实现原理

Leaf这个名字是来自德国哲学家、数学家莱布尼茨的一句话:

There are no two identical leaves in the world

"世界上没有两片相同的树叶"

设置数据表主键自增是最简单的方案,缺点也很明显:

  • 强依赖数据库,无法提供高可用

  • ID生成强依赖单台服务,无法横向扩展

很容易想到,如果我的应用每次申请一批id,插入数据时顺序取一个使用,即将耗尽时再去获取一批新的id,如此即可在一定程度上减弱与数据库的关系,同时将单台扩展延伸为获取id的步长。

负责发放ID的服务既可以使用MySQL服务,也可以使用Redis等服务。

基于MySQL实现

首先我们建立一张数据库表

DROP TABLE IF EXISTS `leafsegment`;
CREATE TABLE `leafsegment`  (
  `biz_tag` varchar(255) NULL DEFAULT NULL,
  `max_id` bigint(20) NULL DEFAULT 0,
  `step` int(11) NULL DEFAULT 5000,
  `desc` varchar(255)  NULL DEFAULT NULL,
  `update_time` datetime(0) NULL DEFAULT now()
); -- 添加一条初始化数据
INSERT INTO `leafsegment` VALUES ('test', 0, 5000, '测试', '2018-12-06 23:32:11');

数据库表如下图

biz_tag:业务标记,不同业务使用不同的值,可以最大限度地利用ID

max_id:当前已经被申请走的最大Id

step:每次申请Id的步长

desc:业务内容描述

update_time:最新一次申请时间

应用如何获取一批有效ID呢?

Begin
UPDATE leafsegment SET max_id=max_id+step,update_time=now() WHERE biz_tag='test'
SELECT biz_tag, max_id, step FROM leafsegment WHERE biz_tag='test'
Commit

在一个事务周期内完成max_id的更新,和最新数据的获取,天然解决了资源竞争问题。

而后,我们就可以在应用中将[max_id-step+1,max_id]闭区间的所有值作为ID来使用了。

基于Redis实现

Redis的实现更为简单,基本原理是利用了Redis的IncrBy命令实现原子加N,具体实现流程无须赘述。

代码实现

首先我们定义一个传递Step(步长)和MaxId(最大值)的DTO

    /// <summary>
    /// 数据单元
    /// </summary>
    public class DataVal
    {
        /// <summary>
        /// 当前最大Id
        /// </summary>
        public long MaxId { get; set; } = 1;
        /// <summary>
        /// 当前步长
        /// </summary>
        public int Step { get; set; } = 1000;
    }

这个类仅负责将ID生发器的数据传入核心类LeafSegment中。核心类的具体实现如下代码:

    /// <summary>
    /// 美团的Leaf Segment 方案
    /// </summary>
    public class LeafSegment
    {
        private long _currentStep = long.MaxValue >> 1;
        private readonly Func<DataVal> _idGetAction;
        private readonly ConcurrentQueue<long> _data = new ConcurrentQueue<long>();
        private readonly AutoResetEvent _autoReset = new AutoResetEvent(false);         /// <summary>
        /// 美团的Leaf Segment 方案
        /// </summary>
        /// <param name="idGetAction">Id生成策略</param>
        /// <param name="prefill">是否立即初始化数据</param>
        public LeafSegment(Func<DataVal> idGetAction,bool prefill=false)
        {
            _idGetAction = idGetAction;
            if (prefill)
            {
                FillData();
            }
            Loop();
        }         /// <summary>
        /// 获取下一个Id
        /// </summary>
        /// <returns></returns>
        public long NextId()
        {
            _autoReset.Set();
            if (_data.TryDequeue(out var result))
            {
                return result;
            }             throw new Exception("Resource not enough");
        }         private void Loop()
        {
            (new Thread(_ =>
            {
                while (true)
                {
                    _autoReset.WaitOne();
                    FillData();
                }
            }) {IsBackground = true}).Start();         }         private void FillData()
        {
            //数量小于步长一半时触发拉新
            while (_data.Count < (_currentStep >> 1))
            {
                var tmp = _idGetAction.Invoke();
                _currentStep = tmp.Step;
                for (var i = tmp.MaxId - tmp.Step + 1; i <= tmp.MaxId; i++)
                {
                    _data.Enqueue(i);
                }
            }
        }
    }

此处需要注意的是LeafSegment构造函数的第一个入参IdGetAction是一个返回DataVal的回调函数,因此外部实现中可以在该回调函数中返回所需ID序列;

第二个参数prefill,该参数控制实例化LeafSegment对象时,是否同步调用获取ID区段,如该值为false,将会由启动的线程稍后补充数据。

完整实现、使用Demo以及benchmark测试请参见源代码:https://github.com/sampsonye/nice

基于.NET Standard的分布式自增ID算法--美团点评LeafSegment的更多相关文章

  1. 基于.NET Standard的分布式自增ID算法--Snowflake

    概述 本篇文章主要讲述分布式ID生成算法中最出名的Snowflake算法.搞.NET开发的,数据库主键最常见的就是int类型的自增主键和GUID类型的uniqueidentifier. 那么为何还要引 ...

  2. 基于.NET Standard的分布式自增ID算法--Snowflake代码实现

    概述 上篇文章介绍了3种常见的Id生成算法,本篇主要介绍如何使用C#实现Snowflake. 基础字段 /// <summary> /// 工作节点Id(长度为5位) /// </s ...

  3. 详解Twitter开源分布式自增ID算法snowflake(附演算验证过程)

    详解Twitter开源分布式自增ID算法snowflake,附演算验证过程 2017年01月22日 14:44:40 url: http://blog.csdn.net/li396864285/art ...

  4. Twitter分布式自增ID算法snowflake原理解析

    以JAVA为例 Twitter分布式自增ID算法snowflake,生成的是Long类型的id,一个Long类型占8个字节,每个字节占8比特,也就是说一个Long类型占64个比特(0和1). 那么一个 ...

  5. Twitter分布式自增ID算法snowflake原理解析(Long类型)

    Twitter分布式自增ID算法snowflake,生成的是Long类型的id,一个Long类型占8个字节,每个字节占8比特,也就是说一个Long类型占64个比特(0和1). 那么一个Long类型的6 ...

  6. 分布式自增ID算法-Snowflake详解

    1.Snowflake简介 互联网快速发展的今天,分布式应用系统已经见怪不怪,在分布式系统中,我们需要各种各样的ID,既然是ID那么必然是要保证全局唯一,除此之外,不同当业务还需要不同的特性,比如像并 ...

  7. Twitter的分布式自增ID算法snowflake

    snowflake 分布式场景下获取自增id git:https://github.com/twitter/snowflake 解读: http://www.cnblogs.com/relucent/ ...

  8. 一秒可生成500万ID的分布式自增ID算法—雪花算法 (Snowflake,Delphi 版)

    概述 分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的. 有些时候我们希望能使用一种 ...

  9. Twitter的分布式自增ID算法snowflake (Java版)

    概述 分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的. 有些时候我们希望能使用一种 ...

随机推荐

  1. 使用MyEclipse建立working set

    1.用eclipse或者MyEclipse开发久了后,会有很多的项目,就算关闭了还会有很多,这是需要建立一个working set,相当在工作区中建立项目文件夹分类放自己做过的一些项目. 如下图:   ...

  2. CSS| 颜色名

    CSS 颜色名 所有浏览器都支持的颜色名. HTML 和 CSS 颜色规范中定义了 147 中颜色名(17 种标准颜色加 130 种其他颜色).下面的表格中列出了所有这些颜色,以及它们的十六进制值. ...

  3. MySQL索引背后的数据结构及算法原理(employees实例)

    摘要 http://blog.codinglabs.org/articles/theory-of-mysql-index.html 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特 ...

  4. python的学习之路day7-socket网络编程

    python基础部分学习完了,时间也已经过了两个月左右,感觉没学到什么,可能是我学习之后忘记的太多了. 由于没钱买书,要是去培训就更没钱了,所以在网上找了一本书,感觉还不错,讲的比较好,比较详细. P ...

  5. CF558E A Simple Task

    题目大意: 给定一个长度不超过10^5的字符串(小写英文字母),和不超过5000个操作. 每个操作 L R K 表示给区间[L,R]的字符串排序,K=1为升序,K=0为降序. 最后输出最终的字符串 首 ...

  6. 如何为已有的类没有生成toString的方法增强生成toString方法

    1:只要提到增强,我的第一思路就是代理,动态代理.但是仅仅是一个toString其实没必要使用代理模式了,有点大材小用了(动态代理其实也是最后通过反射生成toString的方法). 2:简单粗暴,可以 ...

  7. 构造方法、 This关键字 、static、封装

    1.1 构造方法 构造方法是一种特殊的方法,专门用于构造/实例化对象,形式: [修饰符] 类名(){ } 构造方法根据是否有参数分为无参构造和有参构. 1.1.1 无参构造 无参构造方法就是构造方法没 ...

  8. 离线安装Cloudera Manager 5和CDH5(最新版5.9.3) 完全教程(二)基础环境安装

    一.安装CentOS 6.5 x64 具体安装过程自行百度 1.1 修改IP地址 [root@master ~]# vi /etc/sysconfig/network DEVICE=eth0 TYPE ...

  9. 【FRM123】Wrong Way Risk

    https://www.investopedia.com/articles/investing/102015/introduction-wrong-way-risk.asp https://www.r ...

  10. 搞死人的contextRoot;weblogic9.2

    默认情况下: 两个app-deployment同时部署到了一台weblogic服务器的同一个domain下面的时候 /mysite/www/www/WEB-INF/weblogic.xml /mysi ...