Session是Zookeeper中的会话实体,代表了一个客户端会话。SessionID用来唯一标识一个会话,因此Zookeeper必须保证sessionID的全局唯一性,在每次客户端向服务端发起"会话创建"请求时,服务端都会为其分配一个sessionID。那么Zookeeper是如何实现的呢?
在SessionTracker初始化的时候,会调用initializeNextSession方法来生成一个初始化的sessionID,之后在Zookeeper的正常运行过程中,会在该sessionID的基础上为每个会话进行分配。
/** * Generates an initial sessionId. High order byte is serverId, next 5 * 5 bytes are from timestamp, and low order 2 bytes are 0s. */ public static long initializeNextSession(long id) { long nextSid = 0; nextSid = (System.currentTimeMillis() << 24) >>> 8; //这里的版本是3.4.6 nextSid = nextSid | (id <<56); return nextSid; }
上面这个方法就是Zookeeper初始化的算法。可以看出sessionID的生成可以分为以下5个步骤:
- 获取当前时间的毫秒表示。我们假设System.currentTimeMillis()取出的值是1380895182327,其64位二进制表示是:0000000000000000000000010100000110000011110001000100110111110111 其中红色部分表示高24位,下划线部分表示低40位。
- 左移24位。将步骤1中的数值左移24位,得到如下二进制表示的数值:0100000110000011110001000100110111110111000000000000000000000000
- 无符号右移8位。再将步骤2中的数值无符号右移8位,得到如下二进制表示的数值:0000000001000001100000111100010001001101111101110000000000000000
- 添加机器标识SID.在initializeNextSession方法中,出现了一个id变量,该变量就是当前Zookeeper服务器的SID值.SID就是当时配置在myid文件中的值,该值通常是一个整数。我们以2为例子。2的64位表示如下:0000000000000000000000000000000000000000000000000000000000000010。高56位都是0,将其左移56位,可以得到如下二进制表示的数值:0000001000000000000000000000000000000000000000000000000000000000
- 将步骤3和步骤4得到的64位数值进行“|”操作:0000001001000001100000111100010001001101111101110000000000000000。这样就完成了一个sessioID的初始化。我们就可以得到一个单机唯一的序列号。算法概括为:高8位确定了所在机器,后56位使用当前时间的毫秒表示进行随机。
上面的算法就算完美吗?
答案是否定的,在zookeeper3.5.0以上的版本中对这个方法进行的修改。3.5.0版本的方法如下:
/**
* Generates an initial sessionId. High order byte is serverId, next 5
* 5 bytes are from timestamp, and low order 2 bytes are 0s.
*/
public static long initializeNextSession(long id) {
long nextSid;
nextSid = (Time.currentElapsedTime() << 24) >>> 8;
nextSid = nextSid | (id <<56);
return nextSid;
}
currentTimeMillis方法换成了另外一个方法。那么这个方法是什么呢?
/** * Returns time in milliseconds as does System.currentTimeMillis(), * but uses elapsed time from an arbitrary epoch more like System.nanoTime(). * The difference is that if somebody changes the system clock, * Time.currentElapsedTime will change but nanoTime won't. On the other hand, * all of ZK assumes that time is measured in milliseconds. * @return The time in milliseconds from some arbitrary point in time. */ public static long currentElapsedTime() { return System.nanoTime() / 1000000; }
使用了System.nanoTime()方法。原因是如果一些人去主动修改系统的时间,这样可能会出现问题。
Zookeeper使用了2行代码完成了生成全局唯一值的方法。然而我们直接使用jdk1.5以上自带的UUID不是也能生成全局唯一的值吗?
下面我们看看UUID和Zookeeper自己实现方法的一些比较:
- 根据UUID类的注释,A UUID represents a 128-bit value.一个UUID代表一个128位的值。然而Zookeeper使用64就产生了一个全局唯一的值。从资源占用上节省了一半。
- 从代码复杂程度上看,UUID的生成是严格按照国际标准实现的。算法的核心思想是结合机器的网卡、当地时间、一个随即数来生成。代码的复杂程度要比Zookeeper自身实现的高。复杂度高意味着在执行过程中需要消耗的资源就会增多。
- UUID的生成不需要外界因素的参与。直观的将就是不需要传递任何参数就可以完成。而Zookeeper自身实现的方法需要一个id,这个id就是我们在Zookeeper中配置的myid值。它的生成时需要条件的。
总结:
- 没有最好只有适合。适合自身的需要并且能够考虑到性能、资源的使用等方面才能设计出好的策略。
- 底层的运算使用位运算比较理想。很多地方都是这样运用的。毕竟位运算的速度是最快的。
相关推荐
4. **命名服务**:提供分布式环境下的全局唯一ID生成,或者为分布式服务提供可读易记的名称。 5. **分组服务**:ZooKeeper可以实现节点的分组,例如选举Master节点,或进行故障切换。 **英文原版与中文详解** ...
分布式系统中的ID生成是一个至关重要的任务,特别是在大型的复杂分布式环境中,如美团点评的金融、支付、餐饮等产品。随着数据量的不断增长,数据库的分库分表策略需要一个全局唯一的ID来标识每条记录,传统的数据库...
在分布式架构中,生成全局唯一序列号是一个关键挑战,尤其在数据库进行分库分表时。随着携程账号数据库从MySQL的迁移,这个问题变得更加紧迫,需要设计一个能够支持高并发、体现一定属性、高可靠并能容错单点故障的...
分布式ID是现代大规模分布式系统中不可或缺的一个组成部分,它主要用于为分布式环境中的每个实体生成全局唯一且具有特定属性的标识符。以下将详细讲解分布式ID的相关知识点: 1. **UUID(Universally Unique ...
5. **顺序编号**:在分布式环境中,Zookeeper可以生成全局唯一的序列号,如分布式ID生成器。 6. **分布式事件通知**:Zookeeper可以通过Watcher机制,实现实时的事件通知服务。 在**开发技术文档**中,你可能找到...
分布式ID组件是指在分布式系统中生成唯一标识符的组件,用于标识不同的数据记录、业务流程等。在分布式系统中,生成唯一标识符是一件非常重要的事情,因为它可以确保数据的唯一性和安全性。 在本文中,我们将介绍...
- 分布式系统中需要生成全局唯一的 ID,以标识各种实体或事件。 - **实现原理**: 利用 Zookeeper 的顺序节点特性。 - **过程**: - 创建一个特殊的节点,用于生成唯一 ID。 - 每次需要生成新的 ID 时,创建一个...
在分布式系统中,每个实体通常需要一个全局唯一的标识符(ID)。ID生成器的任务就是为新创建的实体提供这样的唯一标识。常见的ID生成策略有雪花算法(Snowflake)、UUID、MongoDB的ObjectID等。雪花算法是一种高效的...
- **AT模式**:Seata采用两阶段提交的变种,通过Seata Server在开始事务时生成全局事务ID,并在每个参与的服务中记录本地事务日志。当所有服务都成功执行后,Seata Server会尝试提交全局事务,如果某个服务失败,...
12. **分布式ID生成器**: 如Twitter的Snowflake算法,生成全局唯一且递增的ID。Python实现将关注时间戳、机器标识和序列号的组合。 项目中的实用工具类可能包括哈希函数、网络通信模块、并发控制、日志记录、配置...
首先,分布式ID(分布式唯一标识符)是分布式系统中的核心组件。在大规模系统中,保证每个实体具有全局唯一的ID至关重要。常见的分布式ID生成器有Twitter的Snowflake、百度的ULID和阿里云的Sequlid等。它们通常通过...
1. **命名服务**:Zookeeper可以作为分布式系统中的全局唯一ID生成器,为服务提供唯一的名称。 2. **配置管理**:在分布式环境中,配置的统一管理和更新是个挑战。Zookeeper提供了一种集中式的配置管理方案,服务...
分布式ID生成器是大型互联网系统中不可或缺的一部分,其主要任务是为系统中的各种实体生成全局唯一的标识符(ID)。在复杂分布式环境下,选择合适的ID生成策略对于系统的性能、可用性和可扩展性至关重要。以下是几种...
3. **全局唯一值**:ZooKeeper 提供了原子性的事务操作,可以用于生成全局唯一的序列号。在 BoatMQ 中,这可能被用于生成消息的唯一ID,确保在分布式环境中消息的唯一性,防止重复消费。 4. **配置中心**:BoatMQ ...
`04_多线程生成订单号.docx`虽然名字中没有明确提到ZooKeeper,但考虑到上下文,可能是使用ZooKeeper实现多线程环境下的订单号唯一性,通过分布式锁保证在高并发场景下不会生成重复订单号。 综上所述,Java中的...
Zookeeper 是一个分布式协调服务,广泛应用于分布式系统中的命名服务、配置管理、集群管理等领域。它提供了高可用、高性能的数据一致性保障,是Apache Hadoop项目的一部分。 1、Zookeeper 数据结构 Zookeeper 的...
Zookeeper,作为Apache的一个顶级项目,是分布式系统中的关键组件,尤其在大型分布式环境中的服务协调、配置管理、集群状态管理等方面发挥着重要作用。本文将深入探讨Zookeeper 3.4.6这一版本的主要特性和使用场景,...
传统的自增ID在单库单表中能够很好地工作,但在分布式系统中,由于数据分散在多个数据库或表中,简单的自增策略无法满足全局唯一性的需求。在这种情况下,我们可以采用如Snowflake算法等方法来生成全局唯一的ID。 ...
在IT行业中,尤其是在数据库管理和分布式系统设计中,生成全局唯一标识符(ID)是一项至关重要的任务。本话题将深入探讨“应用级自增ID的生成”,这是一个确保每个新记录都有独特标识符的策略,这对于数据的正确性和...
5. **命名服务**:为分布式组件提供全局唯一的 ID,例如分布式序列号生成。 总结来说,Zookeeper 3.5.1 在原有的基础上强化了性能和稳定性,提供了更丰富的功能和更友好的开发接口,使其在分布式系统中扮演着越来越...