zoukankan      html  css  js  c++  java
  • 高性能高可用的分布式唯一ID服务——mooon-uniq-id

    目录

    目录 1

    1. 前言 1

    2. 名词 1

    3. 功能 1

    4. 唯一性原理 2

    5. 系统结构 2

    5.1. mooon-uniq-agent 2

    5.2. mooon-uniq-master 2

    6. 限制 3

    7. 核心思想 4

    8. 编译&安装 4

    9. 启动&运行 5

    10. 编程使用 5

    1. 前言

    源码位置:https://github.com/eyjian/mooon/tree/master/application/uniq_id

    mooon-uniq-id可单机运行,也可以由1~255台机器组成集群分布式运行。性能极高,单机批量取(每批限定最多100个),每秒可提供2000个唯一ID服务,单个取每秒可以提供20唯一ID服务。

    mooon-uniq-id还具极高的可用性,只要有一台机器正常即可正常提供服务。

    2. 名词

    Lable 机器标签

    3. 功能

    mooon-uniq-id提供64位无符号整数唯一ID和类似于订单号、流水号的字符串唯一ID

    4. 唯一性原理

    mooon-uniq-id生成的唯一ID通过以下公式保证:

    唯一ID = 机器唯一标签 本机递增序列号 系统时间

    机器唯一标签自动生成,取值从1~255,故最多支持255台机器组成集群。时间粒度为小时,单台机器一小时内的递增序列号值为536870911个,只要一小时内提供的唯一ID数不超过536870911个即是安全的。如果需求超过536870911,则可以扩展到分钟的粒度,mooon-uniq-id保留了6位供用户自由支配,这保留的6位可以用于存储分钟值。

    5. 系统结构

    mooon-uniq-id的实现为单进程无线程UDP实现简单高效。采用弱主架构,这种架构下,master在一段时间内不可用,完全不影响正常服务。租期为多长,即可允许多长时间内master不可用,比如租期为7天,则7天内master不可用都不影响正常服务,agentmaster的依赖非常低,因此叫弱主架构。

    mooon-uniq-idmooon-uniq-agentmooon-uniq-master组成弱主架构,为保证可用性mooon-uniq-agent至少1台以上,而且只要有一台可以用即整体可用。

    mooon-uniq-master一般可部署2台形成主备,实际上部署一台也完全无问题,因为mooon-uniq-master只要在租期内恢复正常即可。

    5.1. mooon-uniq-agent

    对外提供获取唯一ID服务的是mooon-uniq-agent,至少应当部署2台,以提供必要的可用性,部署的越多可用性越高,同时每秒提供的唯一ID个数也越多,支撑的并发数也越大。

    mooon-uniq-agent在能够对外服务之前,都必须先从mooon-uniq-master租约到机器标签,否则不能服务。

    5.2. mooon-uniq-master

    mooon-uniq-master负责租约的管理,包括租约的初始化、租约的分配和租约的过期管理和回收。

    默认情况下,mooon-uniq-agent每隔1分钟以心跳的形式向mooon-uniq-master续租机器标签,可以通过命令行参数“--interval”修改续租间隔,参数值的单位为秒,默认值为6001分钟。

    mooon-uniq-master将机器标签存储在MySQL表中,各机器标签的状态也存储在MySQL表中。mooon-uniq-masterMySQL有依赖,但也不是强依赖,因为只要在租期内可以成功续租或新租成功即可,而一旦集群上线后,99.999%的时间都只是续租。

    在启动mooon-uniq-master之前,需要先创建好如下3MySQL库和表:

    -- CREATE DATABASE IF NOT EXISTS uniq_id DEFAULT CHARSET utf8 COLLATE utf8_general_ci;

    -- Label资源池表

    -- mooon-uniq-master第一次启动时会初始化表t_label_pool

    DROP TABLE IF EXISTS t_label_pool;

    CREATE TABLE t_label_pool (

        f_label TINYINT UNSIGNED NOT NULL,

        PRIMARY KEY (f_label)

    );

    -- Label在线表

    -- f_label为主键,保证同一时间不可能有两个IP租赁同一个Label,

    -- 但一个IP可能同时持有一个或多个过期的Label,和一个当前有效的Label

    DROP TABLE IF EXISTS t_label_online;

    CREATE TABLE t_label_online (

        f_label TINYINT UNSIGNED NOT NULL,

        f_ip CHAR(16) NOT NULL,

        f_time DATETIME NOT NULL,

        PRIMARY KEY (f_label),

        KEY idx_ip(f_ip),

        KEY idx_time(f_time)

    );

    -- Label日志表

    -- 记录租约和续租情况

    DROP TABLE IF EXISTS t_label_log;

    CREATE TABLE t_label_log (

        f_id BIGINT NOT NULL AUTO_INCREMENT,

        f_label TINYINT UNSIGNED NOT NULL,

        f_ip CHAR(16) NOT NULL,

        f_event TINYINT NOT NULL,

        f_time DATETIME NOT NULL,

        PRIMARY KEY (f_id),

        KEY idx_label(f_label),

        KEY idx_ip(f_ip),

        KEY idx_event(f_event),

        KEY idx_time(f_time)

    );

    6. 限制

    ID具备唯一性,但不具备递增性。

    7. 核心思想

    要保证ID的唯一性,最关键是要保证同一个机器标签不能同时出现在多台机器上。mooon-uniq-id的实现引入租约,每台mooon-uniq-agent在服务之前需要先成功租约到机器标签,在租约期内独占标签,并且可以在租期内续租。

    在租期后,每个机器标签还有一段冻结期,处于冻结期的机器标签不会被租约。

    通过这样的一种机制保证了机器标签的安全性,只要每台mooon-uniq-agent保证序列号在该机器上唯一,那么两者相结合即保证了整体上的唯一性。

    序列号总是有限的,为保证永久的唯一性,在组成唯一ID时,加上了时间共同组成唯一性。

    8. 编译&安装

    mooon-uniq-id依赖mooon基础库,使用gitTortoiseGit下载mooon库源码:

    https://github.com/eyjian/mooon/tree/master/mooon

    同样,使用gitTortoiseGit下载mooon-uniq-id源码:

    https://github.com/eyjian/mooon/tree/master/application/uniq_id

    两者均采用CMake编译,且编译方法相同,先编译mooon基础库,编译和安装步骤:

    1) 进入源代码目录,执行cmake生成Makefile文件,安装目录指定为/usr/local/mooon:

    cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=/usr/local/mooon .

    2) 执行make编译源代码:

    make

    3) 在make成功后,执行“make install”完成安装:

    /usr/local/mooon

    ├── bin

    ├── CMake.common

    ├── include

    │     └── mooon

    │           ├── net

    │           ├── sys

    │           └── utils

    └── lib

           └── libmooon.a

    接着编译和安装mooon-uniq-id,方法相同,安装路径也请指定为/usr/local/mooon。

    9. 启动&运行

    简单点可以放到crontab中自动拉起,比如借助process_monitor.sh(下载:https://github.com/eyjian/mooon/blob/master/mooon/shell/process_monitor.sh)的监控和自动重启功能:

    * * * * * /usr/local/bin/process_monitor.sh "/usr/local/uniq_id/bin/uniq_master" "/usr/local/uniq_id/bin/uniq_master --db_host=127.0.0.1 --db_port=3306 --db_user=zhangsan --db_pass='zS2018' --db_name=uniq_id"

    * * * * * /usr/local/bin/process_monitor.sh "/usr/local/uniq_id/bin/uniq_agent" "/usr/local/uniq_id/bin/uniq_agent --master_nodes=192.168.31.33.225.168.251:16200,192.168.31.35:16200"

    10. 编程使用

    可以参考uniq_test.cppuniq_stress.cpp使用mooon-uniq-id,如:

    bool polling = false; // 轮询还是随机选择mooon-uniq-agent

    const uint32_t timeout_milliseconds = 200;

    const uint8_t retry_times = 5;

    // 注意:需要捕获CSyscallException和CException两种异常

    try

    {

        // agent_nodes为mooon-uniq-agent连接信息,多个间以逗号分隔,注意不要包含空格:

        // 如:192.168.1.31:6200,192.168.1.32:6200,192.168.1.33:6200

        mooon::CUniqId uniq_id(agent_nodes, timeout_milliseconds, retry_times, polling);

        // 取交易流水号

        //

        // %L 为取mooon-uniq-agent的机器标签,每个mooon-uniq-agent不会有相同的标签

        // %Y 为YYYY格式的年,如2017

        // %M 为MM格式的月,如:04或12等

        // %D 为DD格式的日,如:01或31等

        // %m 为mm格式的分钟,如:09或59等

        // %H 为hh格式的小时,24小时制,如:03或23等

        // %5S 表示取5位的序列号,不足时前补0

        std::string transaction_id = uniq_id.get_transaction_id("%L%Y%M%D%m%5S");

        fprintf(stdout, "%s ", transaction_id.c_str());

        // 取8字节无符号整数值

        const uint64_t uniq_id = uniq_id.get_uniq_id();

        union mooon::UniqID uid;

        uid.value = uniq_id;

        fprintf(stdout, "id: %" PRIu64" => %s ", uniq_id, uid.id.str().c_str());

    }

    catch (mooon::sys::CSyscallException& ex)

    {

        fprintf(stderr, "%s ", ex.str().c_str());

    }

    catch (mooon::utils::CException& ex)

    {

        fprintf(stderr, "%s ", ex.str().c_str());

    }

  • 相关阅读:
    允许使用root远程ssh登录(Ubuntu 16.04)
    Nginx反向代理,负载均衡,redis session共享,keepalived高可用
    Spring MVC框架:第十六章:细节了解
    Spring MVC框架:第十五章:多IOC容器整合
    Spring MVC框架:第十四章:数据校验
    Spring MVC框架:第十三章:类型转换
    Spring MVC框架:第十二章:运行原理
    Spring MVC框架:第十一章:Ajax
    Spring MVC框架:第九章:文件上传
    Spring MVC框架:第十章:拦截器
  • 原文地址:https://www.cnblogs.com/aquester/p/9891506.html
Copyright © 2011-2022 走看看