Redis集群实现的分布式ID是否适合做分布式ID?

首先是项目地址:

关于Redis集群生成分布式ID,这里要先了解redis使用lua脚本的时候的EVAL,EVALSHA命令:

讲解一下Redis实现分布式ID的原理,这里用java语言来讲解:

这里的分布式id我们分成3部分组成:毫秒级时间,redis集群的第多少个节点,每一个redis节点在每一毫秒的自增序列值

然后因为window是64位的,然后整数的时候第一位必须是0,所以最大的数值就是63位的111111111111111111111111111111111111111111111111111111111111111,这里呢,我们分出来41位作为毫秒,然后12位作为redis节点的数量,然后10位做成redis节点在每一毫秒的自增序列值

41位的二进制11111111111111111111111111111111111111111转换成10进制的毫秒就是2199023255551,然后我们把2199023255551转换成时间就是2039-09-07,也就是说可以用20年的

然后12位作为redis节点,所以最多就是12位的111111111111,也就是最多可以支持4095个redis节点,

然后10位的redis每一个节点自增序列值,,这里最多就是10位的1111111111,也就是说每一个redis节点可以每一毫秒可以最多生成1023个不重复id值

然后我们使用java代码来讲解这个原理,下面的40L是一个毫秒值,然后我们的的redis节点设置成53,然后我们设置了两个不同的自增序列值,分别是1和1023,下面的结果展示的就是在40L这一毫秒里面,53号redis节点生成了两个不同的分布式id值

;;;publicclassTest{publicstaticvoidmain(String[]args){longbuildId=buildId(40L,53,1);("分布式id是:"+buildId);longbuildIdLast=buildId(40L,53,1023);("分布式id是:"+buildIdLast);}publicstaticlongbuildId(longmiliSecond,longshardId,longseq){return(miliSecond(12+10))+(shardId10)+seq;}}publicclassTest{publicstaticvoidmain(String[]args){longbuildId=buildId(40L,53,1);("分布式id是:"+buildId);longbuildIdLast=buildId(40L,53,1023);("分布式id是:"+buildIdLast);}publicstaticlongbuildId(longmiliSecond,longshardId,longseq){return(miliSecond(12+10))+(shardId10)+seq;}}

结果如下所示

分布式id是:656472833分布式id是:656473855

那么有人要说了,你这也不符合分布式id的设置啊,完全没有可读性啊,这里我们可以使用下面的方式来获取这个分布式id的生成毫秒时间值,

;;;publicclassTest{publicstaticvoidmain(String[]args){longbuildId=buildId(40L,53,1);parseId(buildId);longbuildIdLast=buildId(40L,53,1023);parseId(buildIdLast);}publicstaticlongbuildId(longmiliSecond,longshardId,longseq){return(miliSecond(12+10))+(shardId10)+seq;}publicstaticvoidparseId(longid){longmiliSecond=id22;longshardId=(id(0xFFF10))10;("分布式id-"+id+"生成的时间是:"+newSimpleDateFormat("yyyy-MM-dd").format(newDate(miliSecond)));("分布式id-"+id+"在第"+shardId+"号redis节点生成");}}

这样不就ok了,哈哈。

分布式id-656472833生成的时间是:2019-08-07分布式id-656472833在第53号redis节点生成分布式id-656473855生成的时间是:2019-08-07分布式id-656473855在第53号redis节点生成

实现集群版的redis的分布式id创建

此时我的分布式redis集群的端口分别是6380,6381

首先是生成Evalsha命令安全sha1校验码,生成过程如下,

首先是生成6380端口对应的安全sha1校验码,首先进入到redis的bin目录里面,然后执行下面的命令下载lua脚本

wget


然后执行下面的命令,生成6380端口对应的安全sha1校验码,此时看到是be6d4e21e9113bf8af47ce72f3da18e00580d402

./redis-cli-p6380scriptload"$()"


首先是生成6381端口对应的安全sha1校验码,首先进入到redis的bin目录里面,然后执行下面的命令下载lua脚本

wget


然后执行下面的命令,生成6381端口对应的安全sha1校验码,此时看到是97f65601d0aaf1a0574da69b1ff3092969c4310e

./redis-cli-p6381scriptload"$()"


然后我们就使用上面的sha1校验码和下面的代码来生成分布式id


IdGenerator类的代码如下所示

;;;;;;;publicclassIdGenerator{/***JedisPool,luaSha*/ListPairJedisPool,StringjedisPoolList;intretryTimes;intindex=0;privateIdGenerator(ListPairJedisPool,StringjedisPoolList,intretryTimes){=jedisPoolList;=retryTimes;}staticpublicIdGeneratorBuilderbuilder(){returnnewIdGeneratorBuilder();}staticclassIdGeneratorBuilder{ListPairJedisPool,StringjedisPoolList=newArrayList();intretryTimes=5;publicIdGeneratorBuilderaddHost(Stringhost,intport,StringluaSha){((newJedisPool(host,port),luaSha));returnthis;}publicIdGeneratorbuild(){returnnewIdGenerator(jedisPoolList,retryTimes);}}publiclongnext(Stringtab){for(inti=0;iretryTimes;++i){Longid=innerNext(tab);if(id!=null){returnid;}}thrownewRuntimeException("Cannotgenerateid!");}LonginnerNext(Stringtab){index++;inti=index%();PairJedisPool,Stringpair=(i);JedisPooljedisPool=();StringluaSha=();Jedisjedis=null;try{jedis=();ListLongresult=(ListLong)(luaSha,2,tab,""+i);longid=buildId((0),(1),(2),(3));returnid;}catch(JedisConnectionExceptione){if(jedis!=null){(jedis);}}finally{if(jedis!=null){(jedis);}}returnnull;}publicstaticlongbuildId(longsecond,longmicroSecond,longshardId,longseq){longmiliSecond=(second*1000+microSecond/1000);return(miliSecond(12+10))+(shardId10)+seq;}publicstaticListLongparseId(longid){longmiliSecond=id22;longshardId=(id(0xFFF10))10;ListLongre=newArrayListLong(4);(miliSecond);(shardId);returnre;}}

Example的代码如下所示,下面的while循环的目的就是为了打印多个分布式id,下面的tab变量就是evalsha命令里面的参数,可以根据自己的需求来定义

;;;;publicclassExample{publicstaticvoidmain(String[]args){Stringtab="这个就是evalsha命令里面的参数,随便定义";IdGeneratoridGenerator=().addHost("47.91.248.236",6380,"be6d4e21e9113bf8af47ce72f3da18e00580d402").addHost("47.91.248.236",6381,"97f65601d0aaf1a0574da69b1ff3092969c4310e").build();inthello=0;while(hello3){longid=(tab);("分布式id值:"+id);ListLongresult=(id);("分布式id生成的时间是:"+newSimpleDateFormat("yyyy-MM-dd").format(newDate((0))));("redis节点:"+(1));hello++;}}}

此时打印结果如下所示

分布式id值:6564819854640022531分布式id生成的时间是:2019-08-07redis节点:1分布式id值:6564819855189475330分布式id生成的时间是:2019-08-07redis节点:0分布式id值:6564819855361442819分布式id生成的时间是:2019-08-07redis节点:1

到这里redis集群版的分布式id就算搞定了,完美؏؏☝ᖗ乛◡乛ᖘ☝؏؏

Redis集群实现的分布式id是否适合做分布式id呢?

我觉得Redis集群实现分布式ID是可以供我们开发中的基本使用的,但是我还是觉得它有下面的两个问题:

原文:

免责声明:本文章如果文章侵权,请联系我们处理,本站仅提供信息存储空间服务如因作品内容、版权和其他问题请于本站联系