分片(Sharding)的全局ID生成

转载 2016年08月29日 15:59:31

转自http://blog.csdn.net/hengyunabc/article/details/19025973

前言

数据在分片时,典型的是分库分表,就有一个全局ID生成的问题。单纯的生成全局ID并不是什么难题,但是生成的ID通常要满足分片的一些要求:

  • 不能有单点故障。
  • 以时间为序,或者ID里包含时间。这样一是可以少一个索引,二是冷热数据容易分离。
  • 可以控制ShardingId。比如某一个用户的文章要放在同一个分片内,这样查询效率高,修改也容易。
  • 不要太长,最好64bit。使用long比较好操作,如果是96bit,那就要各种移位相当的不方便,还有可能有些组件不能支持这么大的ID。

先来看看老外的做法,以时间顺序:

flickr

flickr巧妙地使用了mysql的自增ID,及replace into语法,十分简洁地实现了分片ID生成功能。

首先,创建一个表:

[sql] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. CREATE TABLE `Tickets64` (  
  2.   `id` bigint(20) unsigned NOT NULL auto_increment,  
  3.   `stub` char(1) NOT NULL default '',  
  4.   PRIMARY KEY  (`id`),  
  5.   UNIQUE KEY `stub` (`stub`)  
  6. ) ENGINE=MyISAM  

使用上面的sql可以得到一个ID:

[sql] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. REPLACE INTO Tickets64 (stub) VALUES ('a');  
  2. SELECT LAST_INSERT_ID();  
因为使用了replace into的语法,实际上,Tickets64这个表里的数据永远都是这样的:

[plain] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. +-------------------+------+  
  2. | id                | stub |  
  3. +-------------------+------+  
  4. | 72157623227190423 |    a |  
  5. +-------------------+------+  
那么如何解决单点故障呢?

很简单,利用mysql的自增ID即可。比如有两台ID生成服务器,设置成下面即可:

[plain] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. TicketServer1:  
  2. auto-increment-increment = 2  
  3. auto-increment-offset = 1  
  4.   
  5. TicketServer2:  
  6. auto-increment-increment = 2  
  7. auto-increment-offset = 2  
优点:

简单可靠。

缺点:

ID只是一个ID,没有带入时间,shardingId等信息。

twitter

twitter利用zookeeper实现了一个全局ID生成的服务snowflake,https://github.com/twitter/snowflake,可以生成全局唯一的64bit ID。

生成的ID的构成:

[plain] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. 时间--用前面41 bit来表示时间,精确到毫秒,可以表示69年的数据  
  2. 机器ID--用10 bit来表示,也就是说可以部署1024台机器  
  3. 序列数--用12 bit来表示,意味着每台机器,每毫秒最多可以生成4096个ID  
优点:

充分把信息保存到ID里。

缺点:

结构略复杂,要依赖zookeeper。

分片ID不能灵活生成。

instagram

instagram参考了flickr的方案,再结合twitter的经验,利用Postgres数据库的特性,实现了一个更简单可靠的ID生成服务。

instagram是这样设计它们的ID的:

[plain] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. 使用41 bit来存放时间,精确到毫秒,可以使用41年。  
  2. 使用13 bit来存放逻辑分片ID。  
  3. 使用10 bit来存放自增长ID,意味着每台机器,每毫秒最多可以生成1024个ID  
以instagram举的例子为说明:
假定时间是September 9th, 2011, at 5:00pm,则毫秒数是1387263000(直接使用系统得到的从1970年开始的毫秒数)。那么先把时间数据放到ID里:
id = 1387263000 << (64-41)
再把分片ID放到时间里,假定用户ID是31341,有2000个逻辑分片,则分片ID是31341 % 2000 -> 1341:
id |= 1341 << (64-41-13)
最后,把自增序列放ID里,假定前一个序列是5000,则新的序列是5001:
id |= (5001 % 1024)
这样就得到了一个全局的分片ID。

下面列出instagram使用的Postgres schema的sql:

[sql] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. REATE OR REPLACE FUNCTION insta5.next_id(OUT result bigintAS $$  
  2. DECLARE  
  3.     our_epoch bigint := 1314220021721;  
  4.     seq_id bigint;  
  5.     now_millis bigint;  
  6.     shard_id int := 5;  
  7. BEGIN  
  8.     SELECT nextval('insta5.table_id_seq') %% 1024 INTO seq_id;  
  9.   
  10.     SELECT FLOOR(EXTRACT(EPOCH FROM clock_timestamp()) * 1000) INTO now_millis;  
  11.     result := (now_millis - our_epoch) << 23;  
  12.     result := result | (shard_id << 10);  
  13.     result := result | (seq_id);  
  14. END;  
  15. $$ LANGUAGE PLPGSQL;  
则在插入新数据时,直接用类似下面的SQL即可(连请求生成ID的步骤都省略了!):

[sql] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. CREATE TABLE insta5.our_table (  
  2.     "id" bigint NOT NULL DEFAULT insta5.next_id(),  
  3.     ...rest of table schema...  
  4. )  
即使是不懂Postgres数据库,也能从上面的SQL看出个大概。把这个移植到mysql上应该也不是什么难事。

缺点:

貌似真的没啥缺点。

优点:

充分把信息保存到ID里。

充分利用数据库自身的机制,程序完全不用额外处理,直接插入到对应的分片的表即可。


Redis实现分片的分局ID

项目地址

https://github.com/hengyunabc/redis-id-generator

基于redis的分布式ID生成器。

准备

首先,要知道redis的EVAL,EVALSHA命令:

http://redis.readthedocs.org/en/latest/script/eval.html

http://redis.readthedocs.org/en/latest/script/evalsha.html

原理

利用redis的lua脚本执行功能,在每个节点上通过lua脚本生成唯一ID。 
生成的ID是64位的:

  • 使用41 bit来存放时间,精确到毫秒,可以使用41年。
  • 使用12 bit来存放逻辑分片ID,最大分片ID是4095
  • 使用10 bit来存放自增长ID,意味着每个节点,每毫秒最多可以生成1024个ID

比如GTM时间 Fri Mar 13 10:00:00 CST 2015 ,它的距1970年的毫秒数是 1426212000000,假定分片ID是53,自增长序列是4,则生成的ID是:

<code class="hljs fix has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-attribute" style="box-sizing: border-box;">5981966696448054276 </span>=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;"> 1426212000000 << 22 + 53 << 10 + 4</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

redis提供了TIME命令,可以取得redis服务器上的秒数和微秒数。因些lua脚本返回的是一个四元组。

<code class="hljs livecodeserver has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">second</span>, microSecond, partition, seq</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

客户端要自己处理,生成最终ID。

<code class="hljs lisp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-list" style="box-sizing: border-box;">(<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">second</span> <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">* 1000 + microSecond / 1000) << (12 + 10)) + (shardId << 10) + seq;</span></span></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

集群实现原理

假定集群里有3个节点,则节点1返回的seq是:

<code class="hljs r has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">9</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">12</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

节点2返回的seq是

<code class="hljs r has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">13</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

节点3返回的seq是

<code class="hljs r has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">11</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">14</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

这样每个节点返回的数据都是唯一的。

单个节点部署

下载redis-script-node1.lua,并把它load到redis上。

<code class="language-bash hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cd</span> redis-directory/
wget https://raw.githubusercontent.com/hengyunabc/redis-id-generator/master/redis-script-node1.lua
./redis-cli script load <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$(cat redis-script-node1.lua)</span>"</span> </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

获取lua脚本的sha1值,可能是:

<code class="hljs bash has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">fce3758b2e0af6cbf8fea4d42b379<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cd</span>0dc374418</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

在代码里,通过EVALSHA命令,传递这个sha1值,就可以得到生成的ID。

比如,通过命令行执行:

<code class="language-bash hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">./redis-cli EVALSHA fce3758b2e0af6cbf8fea4d42b379<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">cd</span>0dc374418 <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> test <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">123456789</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

结果可能是:

<code class="hljs livecodeserver has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>) (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">integer</span>) <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1426238286</span>
<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>) (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">integer</span>) <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">130532</span>
<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>) (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">integer</span>) <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">277</span>
<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>) (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">integer</span>) <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>

集群部署

假定集群是3个节点,则分别对三个节点执行:

<code class="language-bash hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">./redis-cli -host node1 -p <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6379</span> script load <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$(cat redis-script-node1.lua)</span>"</span> 
./redis-cli -host node2 -p <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7379</span> script load <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$(cat redis-script-node2.lua)</span>"</span> 
./redis-cli -host node3 -p <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8379</span> script load <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$(cat redis-script-node3.lua)</span>"</span> </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

性能

redis默认配置。

<code class="hljs css has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">单节点,单线程:
<span class="hljs-tag" style="color: rgb(0, 0, 0); box-sizing: border-box;">time</span><span class="hljs-pseudo" style="color: rgb(0, 0, 0); box-sizing: border-box;">:0</span><span class="hljs-pseudo" style="color: rgb(0, 0, 0); box-sizing: border-box;">:00</span><span class="hljs-pseudo" style="color: rgb(0, 0, 0); box-sizing: border-box;">:00</span><span class="hljs-class" style="box-sizing: border-box; color: rgb(155, 112, 63);">.959</span>
<span class="hljs-tag" style="color: rgb(0, 0, 0); box-sizing: border-box;">speed</span><span class="hljs-pseudo" style="color: rgb(0, 0, 0); box-sizing: border-box;">:10427</span><span class="hljs-class" style="box-sizing: border-box; color: rgb(155, 112, 63);">.52867570386</span>
单节点,20线程:
<span class="hljs-tag" style="color: rgb(0, 0, 0); box-sizing: border-box;">time</span><span class="hljs-pseudo" style="color: rgb(0, 0, 0); box-sizing: border-box;">:0</span><span class="hljs-pseudo" style="color: rgb(0, 0, 0); box-sizing: border-box;">:00</span><span class="hljs-pseudo" style="color: rgb(0, 0, 0); box-sizing: border-box;">:06</span><span class="hljs-class" style="box-sizing: border-box; color: rgb(155, 112, 63);">.710</span>
<span class="hljs-tag" style="color: rgb(0, 0, 0); box-sizing: border-box;">speed</span><span class="hljs-pseudo" style="color: rgb(0, 0, 0); box-sizing: border-box;">:29806</span><span class="hljs-class" style="box-sizing: border-box; color: rgb(155, 112, 63);">.259314456034</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>

结论: 
- 单节点,qps约3w 
- 可以线性扩展,3个结点足以满足绝大部分的应用

java客户端封装

在redis-id-generator-java目录下,有example和benchmark代码。

在调用时,要传入两个参数 
- tag,即为哪一类服务生成ID 
- shardId,即分片由哪个ID生成,比如一个用户的订单,则分片ID应该由userId来生成

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Example</span> {</span>

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">main</span>(String[] args) {
        String tab = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"order"</span>;
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> userId = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">123456789</span>;

        IdGenerator idGenerator = IdGenerator.builder()
                .addHost(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"127.0.0.1"</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6379</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"fce3758b2e0af6cbf8fea4d42b379cd0dc374418"</span>)
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//              .addHost("127.0.0.1", 7379, "1abc55928f37176cb934fc7a65069bf32282d817")</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//              .addHost("127.0.0.1", 8379, "b056d20feb3f89483b10c81027440cbf6920f74f")</span>
                .build();

        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> id = idGenerator.next(tab, userId);

        System.out.println(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"id:"</span> + id);
        List<Long> result = IdGenerator.parseId(id);

        System.out.println(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"miliSeconds:"</span> + result.get(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">", partition:"</span>
                + result.get(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>) + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">", seq:"</span> + result.get(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>));
    }
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li></ul>

多语言客户端

只要支持redis evalsha命令就可以了。


分片(Sharding)的全局ID生成

数据在分片时,典型的是分库分表,就有一个全局ID生成的问题。单纯的生成全局ID并不是什么难题,但是生成的ID通常要满足分片的一些要求: 不能有单点故障。 以时间为序,或者ID里包含时间。这样一是可以少...
  • hengyunabc
  • hengyunabc
  • 2014年02月16日 18:37
  • 15139

分片(Sharding)的全局ID生成

数据在分片时,典型的是分库分表,就有一个全局ID生成的问题。单纯的生成全局ID并不是什么难题,但是生成的ID通常要满足分片的一些要求: 不能有单点故障。 以时间为序,或者ID里包含时间。这样一是可以少...
  • hengyunabc
  • hengyunabc
  • 2014年02月16日 18:37
  • 15139

分布式存储中,生成全局唯一ID的几种方案

1.自定义生成规则 eg: 3位服务器编码+15位年月日时分秒毫秒+3位表编码+4位随机码 (这样就完全单机完成编码任务)---共25位 3位服务器编码+15位年月日...
  • he90227
  • he90227
  • 2016年09月26日 11:27
  • 5367

分布式系统如何生成全局唯一的ID

原文出处:http://darktea.github.io/notes/2013/12/08/Unique-ID?utm_source=tuicool&utm_medium=referral ...
  • firstblood1
  • firstblood1
  • 2016年07月16日 15:57
  • 1449

高并发分布式系统中生成全局唯一Id汇总

数据在分片时,典型的是分库分表,就有一个全局ID生成的问题。 单纯的生成全局ID并不是什么难题,但是生成的ID通常要满足分片的一些要求:    1 不能有单点故障。    2 以时间为序,或者I...
  • younger_z
  • younger_z
  • 2016年12月06日 09:04
  • 746

生成全局唯一Id

生成全局唯一Id 参考了: http://www.cnblogs.com/heyuquan/p/global-guid-identity-maxId.html GUID import uuid...
  • largetalk
  • largetalk
  • 2013年09月29日 00:38
  • 5596

分布式系统中生成全局唯一ID的3个思路

分布式系统中生成全局唯一ID的3个思路       本文根据http://chuansong.me/n/950274251672总结而来! 1.  基于数据库的生成       ...
  • chenglinhust
  • chenglinhust
  • 2016年10月12日 22:41
  • 1730

全局唯一ID生成方案对比

全局唯一ID生成方案对比 GUID的基本需求 业界成熟方案列举 各个方案优劣的对比 汇总了各大公司的全局唯一ID生成方案,并做了一个简单的优劣比较 背景:在实现大型分布式程序时,通常会...
  • havarduniv
  • havarduniv
  • 2015年03月26日 10:22
  • 2073

游戏服务器生成全局唯一ID的几种方法

比如手机游戏,可以使用简单的redis方式,简单不容易出错,由于这种游戏单服并发新建id量并不太大,完全可以满足需要。而对于大型的世界游戏服务器,它本身就是以分布式为主的,所以可以使用snowflak...
  • wgslucky
  • wgslucky
  • 2016年10月26日 22:37
  • 1723

如何在高并发分布式系统中生成全局唯一Id

又一个多月没冒泡了,其实最近学了些东西,但是没有安排时间整理成博文,后续再奉上。最近还写了一个发邮件的组件以及性能测试请看《NET开发邮件发送功能的全面教程(含邮件组件源码)》 ,还弄了个MSSQL参...
  • chenleixing
  • chenleixing
  • 2015年09月01日 09:00
  • 13582
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:分片(Sharding)的全局ID生成
举报原因:
原因补充:

(最多只允许输入30个字)