Login
网站首页 > 文章中心 > 其它

redis分布式ID解决方法有哪些

作者:小编 更新时间:2023-08-07 10:37:26 浏览量:226人看过

这篇文章主要介绍"redis分布式ID解决方法有哪些"的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇"redis分布式ID解决方法有哪些"文章能让粉丝们变的更强解决问题.

常用的分布式ID解决方案

redis分布式ID解决方法有哪些-图1

在分布式系统中,生成全局唯一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??MAX_MACHINE_NUM?||?machineId?
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解决方法有哪些"的内容就介绍到这里了,感谢大家的阅读.如果想了解更多行业相关的知识,可以关注***行业资讯频道,小编每天都会为大家更新不同的知识点.

以上就是土嘎嘎小编大虾米为大家整理的相关主题介绍,如果您觉得小编更新的文章只要能对粉丝们有用,就是我们最大的鼓励和动力,不要忘记讲本站分享给您身边的朋友哦!!

版权声明:倡导尊重与保护知识产权。未经许可,任何人不得复制、转载、或以其他方式使用本站《原创》内容,违者将追究其法律责任。本站文章内容,部分图片来源于网络,如有侵权,请联系我们修改或者删除处理。

编辑推荐

热门文章