Coder Social home page Coder Social logo

donkeyid's Introduction

DonkeyID---php扩展-64位自增ID生成器

0.7版本请访问

原理

参考Twitter-Snowflake 算法,扩展了其中的细节。具体组成如下图:

bits.jpg

如图所示,64bits 咱们分成了4个部分。

  1. 毫秒级的时间戳,有42个bit.能够使用139年,从1970年开始计算,能使用到2109年,当然这些是可以扩展的,可以通知指定起始时间来延长这个日期长度。
  2. 自定义节点id,防止多进程运行产生重复id,占位12个bit,能够支持4096个节点。部署的时候可以配置好服务器id;
  3. 进程workerid,占位5bit,能够生成32个进程id。根据pid运算获得。(已经取消)
  4. 进程内毫秒时间自增序号。占位10bit,一毫秒能产生1024个id。也就是说并发1秒能产生1024000个id。

唯一性保证

100%唯一性保证,根据nodeid的不一样保证多服务器的唯一性,使用共享内存+自旋锁保证单节点多进程的唯一性 同一毫秒内自增变量保证并发的唯一性。

使用

安装

下载代码到本地,进入项目文件夹,执行

cd ./donkeyid
/path/to/phpize
./configure --with-php-config=/path/to/php-config
make
make install
echo "extension=donkeyid.so" >> /path/to/php.ini

模式介绍

DonkeyId 有三种id生成模式:

  1. 默认模式,以上的介绍都是基于默认模式,(mysql字段请使用bigint(20)). dk_get_next_id()。
  2. 第二种模式是10进制模式 生成最多20位数字,(mysql字段请使用varchar(20)).从右开始算第十位以后的数字是时间戳的秒, 第7位到第9位 是节点id。三位数字,最多到999.从第2位到第6位是秒内的自增id, 最后一位是留给业务方的自定义位数。2016053010150316300120001.dk_get_ts_id().
  3. 第三种模式是字符串模式,生成一个25位的字符串,前17位是年月日时分秒毫秒,第18位到21位是节点id,第22-25位是毫秒内自增id,(mysql字段请使用varchar(25))。dk_get_dt_id().

运行

  • 注意,该扩展不支持php的线程安全模式,请在非线程安全模式下使用。

配置

在php.ini 中配置节点id

[DonkeyId]
;0-4095
donkeyid.node_id=0
;0-当前时间戳
donkeyid.epoch=0

api接口

  • dk_get_next_id()

获取基于Snowflake算法的id

  • dk_get_next_ids($num,$time=0)

获取基于Snowflake算法的id列表.$num:生成id的数量,$time:需要生成指定时间的id.$time 默认为0 生成当前时间指定数量的id

  • dk_parse_id($id)

解析基于Snowflake算法的id元数据,返回值包括:time id生成时间,node_id 节点id,sequence 自增数

  • dk_get_ts_id()

获取10进制的时间戳类型的id

  • dk_get_ts_ids($num,$time=0)

获取10进制的时间戳类型的id列表.$num:生成id的数量,$time:需要生成指定时间的id.$time 默认为0 生成当前时间指定数量的id

  • dk_parse_ts_id($tsid)

解析10进制的时间戳类型的id元数据,返回值包括:time id生成时间,node_id 节点id,sequence 自增数

  • dk_get_dt_id()

获取字符串类型的id,显式包含日期时间属性

测试代码

    $nextid =  dk_get_next_id();
    echo "nextid:".$nextid."\n";
    print_r(dk_parse_id($nextid));
    
    $tsid =  dk_get_ts_id();
    echo "tsid:".$tsid."\n";
    print_r(dk_parse_ts_id($tsid));
    
    $dtid = dk_get_dt_id();
    echo "dtid:".$dtid."\n";
    
    echo "nextids:\n";
    print_r(dk_get_next_ids(100,1470298401));
    echo "nextids2:\n";
    print_r(dk_get_next_ids(100));
    
    echo "tsids:\n";
    print_r(dk_get_ts_ids(100,1470298401));
    echo "tsids2:\n";
    print_r(dk_get_ts_ids(100));
   

支持版本

支持 php5.3+ ,支持php 7 - 7.4 支持php 8

donkeyid's People

Contributors

osgochina avatar shijunjun avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

donkeyid's Issues

通过ini_set方法设置node_id无效

测试了下 donkeyid 发现 ini_set 设置 node_id 无效啊,帮忙看看,这块因为现在要用到微服务中,希望提供下能动态修改node_id 的方法,这样更方便于使用。

public function http_donkeyid() {
ini_set('donkeyid.node_id',3);
$donkeyid = dk_get_ts_id();
$multi = $this->http_input->get('multi');
if(!empty($multi) && intval($multi) > 0) {
$donkeyid = dk_get_ts_ids($multi);
}
$tsid = dk_get_ts_id();
$donkeyid['tsid'] = $tsid;
$dtid = dk_get_dt_id();
$donkeyid['dtid'] = $dtid;
$donkeyid['dk_parse_ts_id'] = dk_parse_ts_id($tsid);
$donkeyid['iniget'] = ini_get('donkeyid.node_id');
$this->http_output->end($donkeyid);
}

返回结果

{
"0": "149408895300000070",
"1": "149408895300000080",
"2": "149408895300000090",
"3": "149408895300000100",
"4": "149408895300000110",
"5": "149408895300000120",
"6": "149408895300000130",
"7": "149408895300000140",
"8": "149408895300000150",
"9": "149408895300000160",
"tsid": "149408895300000170",
"dtid": "2017050616423334900000001",
"dk_parse_ts_id": {
"time\u0000": "1494088953",
"node_id\u0000": 0,
"sequence\u0000": 17
},
"iniget": "0"
}

Mac OS下编译报错

头文件malloc.h在MacOS的路径为sys/malloc.h,建议加上对系统的判定

1.0版本稳定了吗

嗨,您好。现在需要一个高性能的id生成器,碰巧看到了你的donkeyid。但是我在release里没有看到1.0版本,请问1.0版本稳定了吗?

have your system administrator add LIBDIR to `/etc/ld.so.conf'

`cp ./.libs/donkeyid.so /home/donkeyid-donkeyid-0.7/donkeyid/modules/donkeyid.so
cp ./.libs/donkeyid.lai /donkeyid-donkeyid-0.7/donkeyid/modules/donkeyid.la
; Local Variables:

PATH="$PATH:/sbin" ldconfig -n /home/donkeyid-donkeyid-0.7/donkeyid/modules

Libraries have been installed in:
; Local Variables:
/home/donkeyid-donkeyid-0.7/donkeyid/modules

If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the `-LLIBDIR'
flag during linking and do at least one of the following:

  • add LIBDIR to the `LD_LIBRARY_PATH' environment variable
    during execution
  • add LIBDIR to the `LD_RUN_PATH' environment variable
    during linking
  • use the `-Wl,--rpath -Wl,LIBDIR' linker flag
  • have your system administrator add LIBDIR to `/etc/ld.so.conf'

See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.`

我已经在/etc/ld.so.conf加上了路径,make clean之后,重新编译还是错误,但是可以生成so文件,加入到php.ini中,提示“段错误”

php7下报错

php版本 PHP 7.0.9
php -v
[1] 49550 segmentation fault php -v

ubuntu 编译成功添加扩展后出现错误

PHP Warning:  PHP Startup: donkeyid: Unable to initialize module
Module compiled with module API=20131226
PHP    compiled with module API=20151012
These options need to match
 in Unknown on line 0
Warning: PHP Startup: donkeyid: Unable to initialize module

编译成功后, 追加 extension 后, 出现上述错误信息.

望提供依据时间生成ID的接口.

在实际运用中.老系统想要迁移到此ID方案时,需要一个依据数据原有时间生成ID的接口.

因为我在设计数据库时,利用新ID的特点,我会省一个数据创建时间字段.因为ID中可以取到.
所以在老系统迁移时就需要一个这样的接口.从时间来获得唯一ID.这样以迁移后,我就能从ID中获得该数据的生成时间.

不支持php8

在make时出错
[root@DESKTOP-RN8D2NJ donkeyid]# make /bin/sh /root/donkeyid/libtool --mode=compile cc -I. -I/root/donkeyid -I/root/donkeyid/include -I/root/donkeyid/main -I/root/donkeyid -I/opt/remi/php80/root/usr/include/php -I/opt/remi/php80/root/usr/include/php/main -I/opt/remi/php80/root/usr/include/php/TSRM -I/opt/remi/php80/root/usr/include/php/Zend -I/opt/remi/php80/root/usr/include/php/ext -I/opt/remi/php80/root/usr/include/php/ext/date/lib -DHAVE_CONFIG_H -g -O2 -c /root/donkeyid/donkeyid.c -o donkeyid.lo libtool: compile: cc -I. -I/root/donkeyid -I/root/donkeyid/include -I/root/donkeyid/main -I/root/donkeyid -I/opt/remi/php80/root/usr/include/php -I/opt/remi/php80/root/usr/include/php/main -I/opt/remi/php80/root/usr/include/php/TSRM -I/opt/remi/php80/root/usr/include/php/Zend -I/opt/remi/php80/root/usr/include/php/ext -I/opt/remi/php80/root/usr/include/php/ext/date/lib -DHAVE_CONFIG_H -g -O2 -c /root/donkeyid/donkeyid.c -fPIC -DPIC -o .libs/donkeyid.o In file included from /root/donkeyid/donkeyid.c:29: /root/donkeyid/php_wrapper.h: In function ‘dk_zend_read_property’: /root/donkeyid/php_wrapper.h:28:37: warning: passing argument 2 of ‘zend_read_property’ from incompatible pointer type -Wincompatible-pointer-types] return zend_read_property(scope,object,name,name_length,silent,&rv); ^~~~~~ In file included from /opt/remi/php80/root/usr/include/php/main/php.h:35, from /root/donkeyid/donkeyid.c:25: /opt/remi/php80/root/usr/include/php/Zend/zend_API.h:404:16: note: expected ‘zend_object *’ {aka ‘struct _zend_object *’} but argument is of type ‘zval *’ {aka ‘struct _zval_struct *’} ZEND_API zval *zend_read_property(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zend_bool silent, zval *rv); ^~~~~~~~~~~~~~~~~~ /root/donkeyid/donkeyid.c: In function ‘zif_dk_get_next_ids’: /root/donkeyid/donkeyid.c:233:46: error: expected ‘)’ before ‘TSRMLS_CC’ if (zend_parse_parameters(ZEND_NUM_ARGS()TSRMLS_CC, "l|s",&num, &val, &val_len) == FAILURE) { ^~~~~~~~~ /root/donkeyid/donkeyid.c:233:9: error: too few arguments to function ‘zend_parse_parameters’ if (zend_parse_parameters(ZEND_NUM_ARGS()TSRMLS_CC, "l|s",&num, &val, &val_len) == FAILURE) { ^~~~~~~~~~~~~~~~~~~~~ In file included from /opt/remi/php80/root/usr/include/php/main/php.h:35, from /root/donkeyid/donkeyid.c:25: /opt/remi/php80/root/usr/include/php/Zend/zend_API.h:304:22: note: declared here ZEND_API zend_result zend_parse_parameters(uint32_t num_args, const char *type_spec, ...); ^~~~~~~~~~~~~~~~~~~~~ /root/donkeyid/donkeyid.c: In function ‘zif_dk_get_ts_ids’: /root/donkeyid/donkeyid.c:275:46: error: expected ‘)’ before ‘TSRMLS_CC’ if (zend_parse_parameters(ZEND_NUM_ARGS()TSRMLS_CC, "l|s",&num, &val, &val_len) == FAILURE) { ^~~~~~~~~ /root/donkeyid/donkeyid.c:275:9: error: too few arguments to function ‘zend_parse_parameters’ if (zend_parse_parameters(ZEND_NUM_ARGS()TSRMLS_CC, "l|s",&num, &val, &val_len) == FAILURE) { ^~~~~~~~~~~~~~~~~~~~~ In file included from /opt/remi/php80/root/usr/include/php/main/php.h:35, from /root/donkeyid/donkeyid.c:25: /opt/remi/php80/root/usr/include/php/Zend/zend_API.h:304:22: note: declared here ZEND_API zend_result zend_parse_parameters(uint32_t num_args, const char *type_spec, ...); ^~~~~~~~~~~~~~~~~~~~~ /root/donkeyid/donkeyid.c: In function ‘zif_dk_parse_ts_id’: /root/donkeyid/donkeyid.c:315:46: error: expected ‘)’ before ‘TSRMLS_CC’ if (zend_parse_parameters(ZEND_NUM_ARGS()TSRMLS_CC, "s", &val, &val_len) == FAILURE) { ^~~~~~~~~ /root/donkeyid/donkeyid.c:315:9: error: too few arguments to function ‘zend_parse_parameters’ if (zend_parse_parameters(ZEND_NUM_ARGS()TSRMLS_CC, "s", &val, &val_len) == FAILURE) { ^~~~~~~~~~~~~~~~~~~~~ In file included from /opt/remi/php80/root/usr/include/php/main/php.h:35, from /root/donkeyid/donkeyid.c:25: /opt/remi/php80/root/usr/include/php/Zend/zend_API.h:304:22: note: declared here ZEND_API zend_result zend_parse_parameters(uint32_t num_args, const char *type_spec, ...); ^~~~~~~~~~~~~~~~~~~~~ /root/donkeyid/donkeyid.c: In function ‘zif_dk_parse_id’: /root/donkeyid/donkeyid.c:343:46: error: expected ‘)’ before ‘TSRMLS_CC’ if (zend_parse_parameters(ZEND_NUM_ARGS()TSRMLS_CC, "s", &val, &val_len) == FAILURE) { ^~~~~~~~~ /root/donkeyid/donkeyid.c:343:9: error: too few arguments to function ‘zend_parse_parameters’ if (zend_parse_parameters(ZEND_NUM_ARGS()TSRMLS_CC, "s", &val, &val_len) == FAILURE) { ^~~~~~~~~~~~~~~~~~~~~ In file included from /opt/remi/php80/root/usr/include/php/main/php.h:35, from /root/donkeyid/donkeyid.c:25: /opt/remi/php80/root/usr/include/php/Zend/zend_API.h:304:22: note: declared here ZEND_API zend_result zend_parse_parameters(uint32_t num_args, const char *type_spec, ...); ^~~~~~~~~~~~~~~~~~~~~ make: *** [Makefile:208: donkeyid.lo] Error 1

感觉文档是不是错误了。

snowflake 算法最高位不用,所以毫秒计时器用了41个bit,所以最多是2^42 -1,就相当于139年,如果你是用了42个bit的话,那么应该是2^43 -1。就相当于278年了。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.