这篇文章主要介绍"redis分布式ID解决方法有哪些"的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇"redis分布式ID解决方法有哪些"文章能让粉丝们变的更强解决问题.
在分布式系统中,生成全局唯一ID是非常重要的,因为在分布式系统中,多个节点同时生成ID可能会导致ID冲突.
下面介绍几种常用的分布式ID解决方案.
javaCopy?code import?java.util.UUID; public?class?UuidGenerator?{ ?public?static?void?main(String[]?args)?{ ??UUID?uuid?=?UUID.randomUUID(); ??System.out.println(uuid.toString()); ?} }
javaCopy?code public?class?SnowflakeGenerator?{ ?private?final?static?long?START_STMP?=?1480166465631L; ?private?final?static?long?SEQUENCE_BIT?=?12; ?private?final?static?long?MACHINE_BIT?=?5; ?private?final?static?long?DATACENTER_BIT?=?5; ?private?final?static?long?MAX_DATACENTER_NUM?=?-1L?^?(-1L?<?MAX_DATACENTER_NUM?||?datacenterId?0)?{ ??throw?new?IllegalArgumentException("datacenterId?can't?be?greater?than?MAX_DATACENTER_NUM?or?less?than?0"); ??} ??if?(machineId?>?MAX_MACHINE_NUM?||?machineId?0)?{ ??throw?new?IllegalArgumentException("machineId?can't?be?greater?than?MAX_MACHINE_NUM?or?less?than?0"); ??} ??this.datacenterId?=?datacenterId; ??this.machineId?=?machineId; ?} ?public?synchronized?long?nextId()?{ ??long?currStmp?=?getNewstmp(); ??if?(currStmp?javaCopy?code public?class?LeafGenerator?{ ?private?static?final?Logger?logger?=?LoggerFactory.getLogger(LeafGenerator.class); ?private?static?final?String?WORKER_ID_KEY?=?"leaf.worker.id"; ?private?static?final?String?PORT_KEY?=?"leaf.port"; ?private?static?final?int?DEFAULT_PORT?=?8080; ?private?static?final?int?DEFAULT_WORKER_ID?=?0; ?private?static?final?int?WORKER_ID_BITS?=?10; ?private?static?final?int?SEQUENCE_BITS?=?12; ?private?static?final?int?MAX_WORKER_ID?=?(1?<?MAX_WORKER_ID)?{ ???throw?new?IllegalArgumentException(String.format("workerId?must?be?between?%d?and?%d",?0,?MAX_WORKER_ID)); ??} ??this.workerId?=?workerId; ??this.port?=?port; ??} ??synchronized?long?nextId()?{ ??long?timestamp?=?System.currentTimeMillis(); ??if?(timestamp?好了,全部的常见的分布式ID生成算法,当然还有其他的一些方案,如:MongoDB ID、UUID、Twitter Snowflake等.不同的方案适用于不同的业务场景,具体实现细节和性能表现也有所不同,需要根据实际情况选择合适的方案.
除了上述介绍的分布式ID生成算法,还有一些新的分布式ID生成方案不断涌现,例如Flicker的分布式ID生成算法,它使用了类似于Snowflake的思想,但是采用了不同的位数分配方式,相比Snowflake更加灵活,并且可以根据需要动态调整每个部分占用的位数.此外,Facebook还推出了ID Generation Service (IGS)方案,该方案将ID的生成和存储分离,提供了更加灵活和可扩展的方案,但是需要进行更加复杂的架构设计和实现.
针对不同的业务需求,可以设计多套分布式ID生成方案.下面是我个人的一些建议:
基于数据库自增ID生成:使用数据库自增ID作为全局唯一ID,可以很好的保证ID的唯一性,并且实现简单,但是并发量较高时可能会导致性能瓶颈.所以呢,在高并发场景下不建议使用.
基于Redis生成:使用Redis的原子性操作,可以保证ID的唯一性,并且生成ID的速度非常快,可以适用于高并发场景.但是需要注意,如果Redis宕机或者性能不足,可能会影响ID的生成效率和可用性.
基于ZooKeeper生成:使用ZooKeeper的序列号生成器,可以保证ID的唯一性,并且实现较为简单,但是需要引入额外的依赖和资源,并且可能会存在性能瓶颈.
选择适合自己业务场景的分布式ID生成方案,需要综合考虑ID的唯一性、生成速度、长度、存储成本、可扩展性、可用性等多个因素.同时需要注意,不同方案的实现细节和性能表现也有所不同,需要根据实际情况进行权衡和选择.
下面给出每种方案的详细代码demo:
基于数据库自增ID生成
javaCopy?code public?class?IdGenerator?{ ?private?static?final?String?JDBC_URL?=?"jdbc:mysql://localhost:3306/test"; ?private?static?final?String?JDBC_USER?=?"root"; ?private?static?final?String?JDBC_PASSWORD?=?"password"; ?public?long?generateId()?{ ??Connection?conn?=?null; ??PreparedStatement?pstmt?=?null; ??ResultSet?rs?=?null; ??try?{ ??Class.forName("com.mysql.jdbc.Driver"); ??conn?=?DriverManager.getConnection(JDBC_URL,?JDBC_USER,?JDBC_PASSWORD); ??pstmt?=?conn.prepareStatement("INSERT?INTO?id_generator?(stub)?VALUES?(null)",?Statement.RETURN_GENERATED_KEYS); ??pstmt.executeUpdate(); ??rs?=?pstmt.getGeneratedKeys(); ??if?(rs.next())?{ ???return?rs.getLong(1); ??} ??}?catch?(Exception?e)?{ ??e.printStackTrace(); ??}?finally?{ ??try?{ ???if?(rs?!=?null)?{ ????rs.close(); ???} ???if?(pstmt?!=?null)?{ ????pstmt.close(); ???} ???if?(conn?!=?null)?{ ????conn.close(); ???} ??}?catch?(Exception?e)?{ ???e.printStackTrace(); ??} ??} ??return?0L; ?} }基于UUID生成
javaCopy?code import?java.util.UUID; public?class?IdGenerator?{ ?public?String?generateId()?{ ??return?UUID.randomUUID().toString().replace("-",?""); ?} }基于Redis生成
javaCopy?code import?redis.clients.jedis.Jedis; public?class?IdGenerator?{ ?private?static?final?String?REDIS_HOST?=?"localhost"; ?private?static?final?int?REDIS_PORT?=?6379; ?private?static?final?String?REDIS_PASSWORD?=?"password"; ?private?static?final?int?ID_GENERATOR_EXPIRE_SECONDS?=?3600; ?private?static?final?String?ID_GENERATOR_KEY?=?"id_generator"; ?public?long?generateId()?{ ??Jedis?jedis?=?null; ??try?{ ??jedis?=?new?Jedis(REDIS_HOST,?REDIS_PORT); ??jedis.auth(REDIS_PASSWORD); ??long?id?=?jedis.incr(ID_GENERATOR_KEY); ??jedis.expire(ID_GENERATOR_KEY,?ID_GENERATOR_EXPIRE_SECONDS); ??return?id; ??}?catch?(Exception?e)?{ ??e.printStackTrace(); ??}?finally?{ ??if?(jedis?!=?null)?{ ???jedis.close(); ??} ??} ??return?0L; ?} }基于ZooKeeper生成
javaCopy?code import?java.util.concurrent.CountDownLatch; import?org.apache.zookeeper.CreateMode; import?org.apache.zookeeper.WatchedEvent; import?org.apache.zookeeper.Watcher; import?org.apache.zookeeper.ZooDefs.Ids; import?org.apache.zookeeper.ZooKeeper; public?class?IdGenerator?implements?Watcher?{ ?private?static?final?String?ZK_HOST?=?"localhost"; ?private?static?final?int?ZK_PORT?=?2181; ?private?static?final?int?SESSION_TIMEOUT?=?5000; ?private?static?final?String?ID_GENERATOR_NODE?=?"/id_generator"; ?private?static?final?int?ID_GENERATOR_EXPIRE_SECONDS?=?3600; ?private?long?workerId?=?0; ?public?IdGenerator()?{ ??try?{ ??ZooKeeper?zk?=?new?ZooKeeper(ZK_HOST?+?":"?+?ZK_PORT,?SESSION_TIMEOUT,?this); ??CountDownLatch?latch?=?new?CountDownLatch(1); ??latch.await(); ??if?(zk.exists(ID_GENERATOR_NODE,?false)?==?null)?{ ???zk.create(ID_GENERATOR_NODE,?null,?Ids.OPEN_ACL_UNSAFE,?CreateMode.PERSISTENT); ??} ??workerId?=?zk.getChildren(ID_GENERATOR_NODE,?false).size(); ??zk.create(ID_GENERATOR_NODE?+?"/worker_"?+?workerId,?null,?Ids.OPEN_ACL_UNSAFE,?CreateMode.EPHEMERAL); ??}?catch?(Exception?e)?{ ??e.printStackTrace(); ??} ?} ?public?long?generateId()?{ ??ZooKeeper?zk?=?null; ??try?{ ??zk?=?new?ZooKeeper(ZK_HOST?+?":"?+?ZK_PORT,?SESSION_TIMEOUT,?null); ??CountDownLatch?latch?=?new?CountDownLatch(1); ??latch.await(); ??zk.create(ID_GENERATOR_NODE?+?"/id_",?null,?Ids.OPEN_ACL_UNSAFE,?CreateMode.EPHEMERAL_SEQUENTIAL,?(rc,?path,?ctx,?name)?->?{},?null); ??byte[]?data?=?zk.getData(ID_GENERATOR_NODE?+?"/worker_"?+?workerId,?false,?null); ??long?id?=?Long.parseLong(new?String(data))?*?10000?+?zk.getChildren(ID_GENERATOR_NODE,?false).size(); ??return?id; ??}?catch?(Exception?e)?{ ??e.printStackTrace(); ??}?finally?{ ??if?(zk?!=?null)?{ ???try?{ ????zk.close(); ???}?catch?(Exception?e)?{ ????e.printStackTrace(); ???} ??} ??} ??return?0L; ?} ?@Override ?public?void?process(WatchedEvent?event)?{ ??if?(event.getState()?==?Event.KeeperState.SyncConnected)?{ ??System.out.println("Connected?to?ZooKeeper"); ??CountDownLatch?latch?=?new?CountDownLatch(1); ??latch.countDown(); ??} ?} }注意,这里使用了ZooKeeper的临时节点来协调各个工作节点,如果一个工作节点挂掉了,它的临时节点也会被删除,这样可以保证每个工作节点获得的ID是唯一的.
关于"redis分布式ID解决方法有哪些"的内容就介绍到这里了,感谢大家的阅读.如果想了解更多行业相关的知识,可以关注***行业资讯频道,小编每天都会为大家更新不同的知识点.
以上就是土嘎嘎小编大虾米为大家整理的相关主题介绍,如果您觉得小编更新的文章只要能对粉丝们有用,就是我们最大的鼓励和动力,不要忘记讲本站分享给您身边的朋友哦!!