zookeepeer ID生成器 (一)
疯狂创客圈 Java 分布式聊天室【 亿级流量】实战系列之 -25【 博客园 总入口 】
写在前面
大家好,我是作者尼恩。目前和几个小伙伴一起,组织了一个高并发的实战社群【疯狂创客圈】。正在开始高并发、亿级流程的 IM 聊天程序 学习和实战
前面,已经完成一个高性能的 Java 聊天程序的四件大事:
接下来,需要进入到分布式开发的环节了。 分布式的中间件,疯狂创客圈的小伙伴们,一致的选择了zookeeper,不仅仅是由于其在大数据领域,太有名了。更重要的是,很多的著名框架,都使用了zk。
**本篇介绍 ZK 的分布式命名服务 ** 中的 分布式ID生成器。
1.1. ZK 的分布式命名服务
zookeeper的命名服务,主要是利用zookeepeer节点的树型分层结构和子节点的次序维护能力,为分布式系统中的资源命名与标识能力。
zookeeper的分布式命名服务,典型的应用场景有:
(1)提供分布式JNDI的API目录服务功能。
可以把系统中各种API接口服务的名称、链接地址放在zookeeper的树形分层结果中,提供分布式的API调用能力。著名的分布式框架,就是应用了zookeeper的分布式的JNDI能力。
开源的分布式服务框架Dubbo中使用ZooKeeper来作为其命名服务,维护全局的服务接口API地址列表。在Dubbo实现中,provider服务提供者在启动的时候,向ZK上的指定节点/dubbo/${serviceName}/providers文件夹下写入自己的API地址,这个操作就相当于服务的公开。
consumer服务消费者启动的时候,订阅节点/dubbo/{serviceName}/providers文件夹下的provider服务提供者URL地址,获得所有的访问提供者的API。
(2)制作分布式的ID生成器,为分布式系统中的每一个数据资源,提供的唯一的标识能力。
在单体服务环境下,我们唯一标识一个数据资源,通常利用数据库的主键自增功能。但是在大量服务器集群的场景下,依赖单体服务的数据库主键自增生成唯一ID,没有办法满足高并发和高负载的需求。
(3)分布式节点的命名服务
一个分布式系统会有很多的节点组成,而且,节点的数量是不断动态变化的。根据业务的膨胀需要和迎接流量洪峰,可能会加入大量的动态很多节点。流量洪峰过去,就需要下线大量的节点。或者说,由于机器或者网络的原因,一些节点主动的离开的集群。
如何为大量的动态节点命名呢?一种简单的办法是,可以通过配置文件,手动的进行每一个节点的命名。但是如果节点数据量太大,或者说变动频繁,手动命名是不现实的,这就需要用到分布式节点的命名服务。
疯狂创客圈的分布式IM实战项目,也会使用分布式命名服务,为每一个IM节点动态命名。
1.1.1. 分布式 ID 生成器的类型
在分布式系统中,ID生成器的使用场景,非常非常多:
(1)大量的数据记录,需要分布式ID
(2)大量的系统消息,需要分布式ID
(3)大量的请求日志,如http请求记录,需要唯一标识,以便进行后续的用户行为分析和调用链路分析,等等等等。
传统的数据库自增主键,或者单体的自增主键,已经不能满足需求。在分布式系统环境中,迫切需要一个全新的唯一ID的系统,这个系统需要满足以下需求:
(1)全局唯一:不能出现重复ID
(2)高可用:ID生成系统是基础系统,被许多关键系统调用,一旦宕机,会造成严重影响。
分布式唯一ID生成分案有很多种:
(1) java的UUID
(2) 利用分布式缓存Redis生成ID
利用Redis的原子操作INCR和INCRBY,生成全局唯一的ID。
(3) Twitter的snowflake算法
(4) ZooKeeper生成ID
利用ZooKeeper 的顺序节点,生成全局唯一的ID。
(5) MongoDb的ObjectId
利用分布式Nosql MongDB,生成全局唯一的ID。
首先分析一下java语言中的 UUID方案。
UUID方案
UUID是Universally Unique Identifier的缩写,它是在一定的范围内(从特定的名字空间到全球)唯一的机器生成的标识符。UUID在其他语言中也叫GUID,在java中,生成UUID的代码很简单:
String uuid = UUID.randomUUID().toString()
一个UUID是16字节长的数字,一共128位。通常以36字节的字符串表示,比如:3F2504E0-4F89-11D3-9A0C-0305E82C3301。 使用的时候,可以把中间的4个中划线去掉,剩下32位字符串。
UUID经由一定的算法机器生成,为了保证UUID的唯一性,规范定义了包括网卡MAC地址、时间戳、名字空间(Namespace)、随机或伪随机数、时序等元素,以及从这些元素生成UUID的算法。UUID的只能由计算机生成。
UUID的优点:本地生成ID,不需要进行远程调用,时延低,性能高。
UUID的缺点:UUID过长,16字节128位,通常以36长度的字符串表示,很多场景不适用,比如,由于UUID没有排序,无法保证趋势递增,用做数据库索引字段的效率就很低,新增记录存储入库时性能差
从高并发,高可用的角度出发,通过ZooKeeper实现分布式系统唯一ID的方案,是最为合适的解决方案之一。
1.1.2. ZK生成分布式ID
通过创建ZK的顺序模式的节点,可以生成全局唯一的ID。
代码如下:
private String createSeqNode(String pathPefix) {
try {
// 创建一个 ZNode 顺序节点
String destPath = client.create()
.creatingParentsIfNeeded()
.withMode(CreateMode.*EPHEMERAL_SEQUENTIAL*)
//避免zookeeper的顺序节点暴增,可以删除创建的顺序节点
.forPath(pathPefix);
return destPath;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
节点创建完成后,会返回节点的完整的层次路径,生成的序号,放置在路径的末尾。一般为10位数字字符。
通过截取路径末尾的数字,作为新生成的ID。截取数字的代码如下:
public String makeId(String nodeName) {
String str = createSeqNode(nodeName);
if (null == str) {
return null;
}
int index = str.lastIndexOf(nodeName);
if (index >= 0) {
index += nodeName.length();
return index <= str.length() ? str.substring(index) : "";
}
return str;
}
调用的代码如下:
*/\*** ** create by 尼恩 @ 疯狂创客圈* **\*/*@Slf4j
public class IDMakerTester {
@Test
public void testMakeId() {
IDMaker idMaker = new IDMaker();
idMaker.init();
String nodeName = "/test/IDMaker/ID-";
for (int i = 0; i < 10; i++) {
String id = idMaker.makeId(nodeName);
log.info("第"+ i + "个创建的id为:" + id);
}
idMaker.destroy();
}
}
下面是部分的运行输出:
第0个创建的id为:0000000010
第1个创建的id为:0000000011
写在最后
下一篇:基于 zookeeper 实现snowflake 算法 。
疯狂创客圈 亿级流量 高并发IM 实战 系列
- Java (Netty) 聊天程序【 亿级流量】实战 开源项目实战
- Netty 源码、原理、JAVA NIO 原理
- Java 面试题 一网打尽
- 疯狂创客圈 【 博客园 总入口 】
zookeepeer ID生成器 (一)的更多相关文章
- 分布式的Id生成器
项目中需要一个分布式的Id生成器,twitter的Snowflake中这个既简单又高效,网上找的Java版本 package com.cqfc.id; import org.slf4j.Logger; ...
- 分布式ID生成器 zz
简介 这个是根据twitter的snowflake来写的.这里有中文的介绍. 如上图所示,一个64位ID,除了最左边的符号位不用(固定为0,以保证生成的ID都是正数),还剩余63位可用. 下面的代码与 ...
- IOS ID生成器
// // IdGenerator.m // Copyright (c) 2014年 青岛拓宇网络科技有限公司. All rights reserved. // #import "IdGen ...
- 分布式ID生成器
最近会写一篇分布式的ID生成器的文章,先占位.借鉴Mongodb的ObjectId的生成: 4byte时间戳 + 3byte机器标识 + 2byte PID + 3byte自增id 简单代码: imp ...
- 游戏服务器ID生成器组件
游戏服务器程序中,经常需要生成全局的唯一ID号,这个功能很常用,本文将介绍一种通用ID生成组件.游戏服务器程序中使用此组件的场景有: 创建角色时,为其分配唯一ID 创建物品时,每个物品需要唯一ID 创 ...
- ID生成器的一种可扩展实现方案
ID生成器主要为了解决业务程序生成记录ID的场景,而一个好的ID生成器肯定要满足扩展性好.并发性好的特点,本文下面介绍一种满足上述特点的实现方案. 此方案的核心思想是:每次需要扩容机器时,将每个节点维 ...
- ID生成器详解
概述 ID 生成器也叫发号器,它的主要目的就是"为一个分布式系统的数据object产生一个唯一的标识",但其实在一个真实的系统里可能也可以承担更多的作用.概括起来主要有以下几点: ...
- 业务系统需要什么样的ID生成器
业务系统需要什么样的ID生成器 ID 生成器在微博我们一直叫发号器,微博就是用这样的号来存储,而我微博里讨论的时候也都是以发号器为标签.它的主要目的确如平常大家理解的“为一个分布式系统的数据objec ...
- twitter的ID生成器的snowFlake算法的自造版
snowFlake算法在生成ID时特别高效,可参考:https://segmentfault.com/a/1190000011282426 SnowFlake算法生成id的结果是一个64bit大小的整 ...
随机推荐
- 使用Spring的AbstractRoutingDataSource实现多数据源切换
https://www.cnblogs.com/softidea/p/7127874.html?utm_source=itdadao&utm_medium=referral https://b ...
- 【Zookeeper】分布式服务框架 Zookeeper -- 管理分布式环境中的数据
Zookeeper 分布式服务框架是 Apache Hadoop 的一个子项目,它主要是用来解决分布式应用中经常遇到的一些数据管理问题,如:统一命名服务.状态同步服务.集群管理.分布式应用配置项的管理 ...
- zabbix监控php-fpm
1.启用php-fpm的状态功能 [root@web01 ~]# vim /etc/php-fpm.d/www.conf 121 pm.status_path = /php_status [root@ ...
- 配置Linux系统实现dhcp功能
配置Linux系统实现dhcp功能 1.背景及原理 DHCP(Dynamic Host Configuration Protocol,动态主机配置协议)通常被应用在大型的局域网络环境中,主要作用 ...
- IOS 开发环境,证书和授权文件是什么?
一.成员介绍 1. Certification(证书) 证书是对电脑开发资格的认证,每个开发者帐号有一套,分为两种: 1) Developer Certification(开发证书) 安装 ...
- mysql_affected_rows的注意点
取得最近一次与 link_identifier 关联的 INSERT,UPDATE 或 DELETE 查询所影响的记录行数. 1.执行成功,则返回受影响的行的数目,如果最近一次查询失败的话,函数返回 ...
- UltraISO 9.6.5.3237
注册信息: 用户名:Guanjiu 注册码:A06C-83A7-701D-6CFC
- 訪问控制 protected, public, private 对照
OOP 3大特性:数据抽象,继承,动态绑定 3中訪问标号 protected, public, private 对照 用类进行数据抽象:用继承类继承基类的成员,实现继承.通过将基类对应函数声明为vir ...
- MySQL自增长主键探究
MySQL自己主动增长使用的keyword是 AUTO_INCREMENT; 由于属于 DDL.所以不区分大写和小写. 使用的列,必须被定义为 key, 比方主键,唯一键等. 本文中使用的数据库是 M ...
- c#利用委托传递函数参数(1)
本次旨在解决 同参不同名 的函数作为参数传递的情况 情景: 一下两个函数分别多次重复调用了两个同参不同名的函数(实际上总共有3个这样的函数),函数结构基本相同,只有调用的函数名不一样,显然可以整合在一 ...