生成分佈式有序且惟一id的方法有不少種,使用zookeeper是比較簡單的一種方法,只是生成的速度不高,這裏只是一個藉助zk的版本號生成分佈式惟一且有序id的例子。html
ZkIdGenerator.java:java
package cc11001100.zookeeper.uniqId; import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.ZooDefs; import org.apache.zookeeper.ZooKeeper; import org.apache.zookeeper.data.Stat; import java.io.IOException; /** * 使用zk生成分佈式惟一id,自增有序 * * @author CC11001100 */ public class ZkIdGenerator { private ZooKeeper zk; private String path; public ZkIdGenerator(String serverAddress, String path) { try { this.path = path; zk = new ZooKeeper(serverAddress, 3000, event -> { System.out.println(event.toString()); }); if (zk.exists(path, false) == null) { zk.create(path, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); } } catch (IOException | InterruptedException | KeeperException e) { e.printStackTrace(); } } public long next() { try { Stat stat = zk.setData(path, new byte[0], -1); return stat.getVersion(); } catch (KeeperException | InterruptedException e) { e.printStackTrace(); } return -1; } }
ZkIdGeneratorTest.java:apache
package cc11001100.zookeeper.uniqId; /** * @author CC11001100 */ public class ZkIdGeneratorTest { public static void main(String[] args) { ZkIdGenerator zkIdGenerator = new ZkIdGenerator("xx.xx.xx.xx:2181", "/id-gen"); for(int i=0; i<100; i++){ System.out.println(zkIdGenerator.next()); } } }
輸出:服務器
WatchedEvent state:SyncConnected type:None path:null 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
注意由於版本號是保存在zk服務器上的,因此客戶端重啓無所謂,只要這個節點不被刪除就不會出現生成的id回退的狀況。分佈式
.this