轉自http://blog.csdn.net/hengyunabc/article/details/19025973
前言
數據在分片時,典型的是分庫分表,就有一個全局ID生成的問題。單純的生成全局ID並不是什麼難題,但是生成的ID通常要滿足分片的一些要求:
- 不能有單點故障。
- 以時間爲序,或者ID裏包含時間。這樣一是可以少一個索引,二是冷熱數據容易分離。
- 可以控制ShardingId。比如某一個用戶的文章要放在同一個分片內,這樣查詢效率高,修改也容易。
- 不要太長,最好64bit。使用long比較好操作,如果是96bit,那就要各種移位相當的不方便,還有可能有些組件不能支持這麼大的ID。
先來看看老外的做法,以時間順序:
flickr
flickr巧妙地使用了mysql的自增ID,及replace into語法,十分簡潔地實現了分片ID生成功能。
首先,創建一個表:
- CREATE TABLE `Tickets64` (
- `id` bigint(20) unsigned NOT NULL auto_increment,
- `stub` char(1) NOT NULL default '',
- PRIMARY KEY (`id`),
- UNIQUE KEY `stub` (`stub`)
- ) ENGINE=MyISAM
使用上面的sql可以得到一個ID:
- REPLACE INTO Tickets64 (stub) VALUES ('a');
- SELECT LAST_INSERT_ID();
- +-------------------+------+
- | id | stub |
- +-------------------+------+
- | 72157623227190423 | a |
- +-------------------+------+
很簡單,利用mysql的自增ID即可。比如有兩臺ID生成服務器,設置成下面即可:
- TicketServer1:
- auto-increment-increment = 2
- auto-increment-offset = 1
- TicketServer2:
- auto-increment-increment = 2
- auto-increment-offset = 2
簡單可靠。
缺點:
ID只是一個ID,沒有帶入時間,shardingId等信息。
twitter利用zookeeper實現了一個全局ID生成的服務snowflake,https://github.com/twitter/snowflake,可以生成全局唯一的64bit ID。
生成的ID的構成:
- 時間--用前面41 bit來表示時間,精確到毫秒,可以表示69年的數據
- 機器ID--用10 bit來表示,也就是說可以部署1024臺機器
- 序列數--用12 bit來表示,意味着每臺機器,每毫秒最多可以生成4096個ID
充分把信息保存到ID裏。
缺點:
結構略複雜,要依賴zookeeper。
分片ID不能靈活生成。
instagram參考了flickr的方案,再結合twitter的經驗,利用Postgres數據庫的特性,實現了一個更簡單可靠的ID生成服務。
instagram是這樣設計它們的ID的:
- 使用41 bit來存放時間,精確到毫秒,可以使用41年。
- 使用13 bit來存放邏輯分片ID。
- 使用10 bit來存放自增長ID,意味着每臺機器,每毫秒最多可以生成1024個ID
假定時間是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:
- REATE OR REPLACE FUNCTION insta5.next_id(OUT result bigint) AS $$
- DECLARE
- our_epoch bigint := 1314220021721;
- seq_id bigint;
- now_millis bigint;
- shard_id int := 5;
- BEGIN
- SELECT nextval('insta5.table_id_seq') %% 1024 INTO seq_id;
- SELECT FLOOR(EXTRACT(EPOCH FROM clock_timestamp()) * 1000) INTO now_millis;
- result := (now_millis - our_epoch) << 23;
- result := result | (shard_id << 10);
- result := result | (seq_id);
- END;
- $$ LANGUAGE PLPGSQL;
- CREATE TABLE insta5.our_table (
- "id" bigint NOT NULL DEFAULT insta5.next_id(),
- ...rest of table schema...
- )
缺點:
貌似真的沒啥缺點。
優點:
充分把信息保存到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命令就可以了。