Zookeeper分布式命名服务实战

目录

分布式命名服务

分布式API目录

 分布式节点的命名

分布式的ID生成器 

分布式的ID生成器方案:

基于Zookeeper实现分布式ID生成器

基于Zookeeper实现SnowFlakeID算法


分布式命名服务

       命名服务是为系统中的资源提供标识能力。ZooKeeper的命名服务主要是利用ZooKeeper节点的树形分层结构和子节点的顺序维护能力,来为分布式系统中的资源命名。需要用到分布式命名服务的应用场景典型的有:分布式API目录、分布式节点命名、分布式ID生成器。

分布式API目录

       为分布式系统中各种API接口服务的名称、链接地址,提供类似JNDI(Java命名和目录接口)中的文件系统的功能。借助于ZooKeeper的树形分层结构就能提供分布式的API调用功能。著名的Dubbo分布式框架就是应用了ZooKeeper的分布式的JNDI功能。在Dubbo中,使用ZooKeeper维护的全局服务接口API的地址列表。大致的思路为:

服务提供者(Service Provider)
       在启动的时候,向ZooKeeper上的指定节点/dubbo/${serviceName}/providers写入自己的API地址,这个操作就相当于服务的公开。
服务消费者(Consumer)
       启动的时候,订阅节点/dubbo/{serviceName}/providers下的服务提供者的URL地址,获得所有服务提供者的API。 

              


 分布式节点的命名

       一个分布式系统通常会由很多的节点组成,节点的数量不是固定的,而是不断动态变化的。比如说, 当业务不断膨胀和流量洪峰到来时,大量的节点可能会动态加入到集群中。而一旦流量洪峰过去了, 就需要下线大量的节点。这就需要用到分布式节点的命名服务。

可用于生成集群节点的编号的方案: 

1. 使用数据库的自增ID特性,用数据表存储机器的MAC地址或者IP来维护。

2. 使用ZooKeeper持久顺序节点的顺序特性来维护节点的NodeId编号。

在第2种方案中,集群节点命名服务的基本流程是:

       启动节点服务,连接ZooKeeper,检查命名服务根节点是否存在,如果不存在,就创建系统的根节点。 在根节点下创建一个临时顺序ZNode节点,取回ZNode的编号把它作为分布式系统中节点的NODEID。 如果临时节点太多,可以根据需要删除临时顺序ZNode节点。


分布式的ID生成器 

        分布式系统中,分布式ID生成器的使用场景非常多,比如大量的数据记录、大量的系统消息 、大量的请求日志、分布式节点的命名服务等

        传统的数据库自增主键已经不能满足需求。在分布式系统环境中,需要一种全新的唯一ID系统, 这种系统需要满足以下需求:

全局唯一:不能出现重复ID。

高可用:ID生成系统是基础系统,被许多关键系统调用,一旦宕机,就会造成严重影响。


分布式的ID生成器方案:

1. Java的UUID。
2. 分布式缓存Redis生成ID:利用Redis的原子操作INCR和INCRBY,生成全局唯一的ID。
3. Twitter的SnowFlake算法。
4. ZooKeeper生成ID:利用ZooKeeper的顺序节点,生成全局唯一的ID。
5. MongoDB的ObjectId:MongoDB是一个分布式的非结构化NoSQL数据库,每插入一条记录会自动生成全局唯 一的一个“_id”字段值,它是一个12字节的字符串,可以作为分布式系统中全局唯一的ID。


基于Zookeeper实现分布式ID生成器

在ZooKeeper节点的四种类型中,其中有以下两种类型具备自动编号的能力:

PERSISTENT_SEQUENTIAL持久化顺序节点。

EPHEMERAL_SEQUENTIAL临时顺序节点。

       ZooKeeper的每一个节点都会为它的第一级子节点维护一份顺序编号,会记录每个子节点创建的先后 顺序,这个顺序编号是分布式同步的,也是全局唯一的。可以通过创建ZooKeeper的临时顺序节点的方法,生成全局唯一的ID

@Slf4j
public class IDMaker extends CuratorBaseOperations {private String createSeqNode(String pathPefix) throws Exception {CuratorFramework curatorFramework = getCuratorFramework();//创建一个临时顺序节点String destPath = curatorFramework.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath(pathPefix);return destPath;}public String  makeId(String path) throws Exception {String str = createSeqNode(path);if(null != str){//获取末尾的序号int index = str.lastIndexOf(path);if(index>=0){index+=path.length();return index<=str.length() ? str.substring(index):"";}}return str;}
}
@Slf4j
public class IDMakerTest {@Testpublic void testMarkId() throws Exception {IDMaker idMaker = new IDMaker();idMaker.init();String pathPrefix = "/idmarker/id-";//模拟5个线程创建idfor(int i=0;i<5;i++){new Thread(()->{for (int j=0;j<10;j++){String id = null;try {id = idMaker.makeId(pathPrefix);log.info("线程{}第{}次创建id为{}",Thread.currentThread().getName(),j,id);} catch (Exception e) {e.printStackTrace();}}},"thread"+i).start();}}
}

执行结果如下 :

 如果是每秒钟要几万、几十万的id,这种方案是不行的,受限于zookeeper的顺序节点写操作。


基于Zookeeper实现SnowFlakeID算法

       Twitter(推特)的SnowFlake算法是一种著名的分布式服务器用户ID生成算法。SnowFlake算法所生成的ID是一个64bit的长整型数字。这个64bit被划分成四个部分,其中后面三个部分分别表示时间戳、工作机器ID、序列号。

SnowFlakeID的四个部分,具体介绍如下:

1. 第一位 占用1 bit,其值始终是0,没有实际作用。 

2. 时间戳 占用41 bit,精确到毫秒,总共可以容纳约69年的时间。 

3. 工作机器id占用10 bit,最多可以容纳1024个节点。

4. 序列号占用12 bit。这个值在同一毫秒同一节点上从0开始不断累加,最多可以累加到4095。 在工作节点达到1024顶配的场景下,SnowFlake算法在同一毫秒最多可以生成的ID数量为: 1024 * 4096 =4194304,在绝大多数并发场景下都是够用的。 

SnowFlake算法的优点:
1. 生成ID时不依赖于数据库,完全在内存生成,高性能和高可用性。
2. 容量大,每秒可生成几百万个ID。
3. ID呈趋势递增,后续插入数据库的索引树时,性能较高。

SnowFlake算法的缺点:

1. 依赖于系统时钟的一致性,如果某台机器的系统时钟回拨了,有可能造成ID冲突,或者ID乱序。 2. 在启动之前,如果这台机器的系统时间回拨过,那么有可能出现ID重复的危险。

基于zookeeper实现雪花算法:

public class SnowflakeIdGenerator {/*** 单例*/public static SnowflakeIdGenerator instance =new SnowflakeIdGenerator();/*** 初始化单例** @param workerId 节点Id,最大8091* @return the 单例*/public synchronized void init(long workerId) {if (workerId > MAX_WORKER_ID) {// zk分配的workerId过大throw new IllegalArgumentException("woker Id wrong: " + workerId);}instance.workerId = workerId;}private SnowflakeIdGenerator() {}/*** 开始使用该算法的时间为: 2017-01-01 00:00:00*/private static final long START_TIME = 1483200000000L;/*** worker id 的bit数,最多支持8192个节点*/private static final int WORKER_ID_BITS = 13;/*** 序列号,支持单节点最高每毫秒的最大ID数1024*/private final static int SEQUENCE_BITS = 10;/*** 最大的 worker id ,8091* -1 的补码(二进制全1)右移13位, 然后取反*/private final static long MAX_WORKER_ID = ~(-1L << WORKER_ID_BITS);/*** 最大的序列号,1023* -1 的补码(二进制全1)右移10位, 然后取反*/private final static long MAX_SEQUENCE = ~(-1L << SEQUENCE_BITS);/*** worker 节点编号的移位*/private final static long WORKER_ID_SHIFT = SEQUENCE_BITS;/*** 时间戳的移位*/private final static long TIMESTAMP_LEFT_SHIFT = WORKER_ID_BITS + SEQUENCE_BITS;/*** 该项目的worker 节点 id*/private long workerId;/*** 上次生成ID的时间戳*/private long lastTimestamp = -1L;/*** 当前毫秒生成的序列*/private long sequence = 0L;/*** Next id long.** @return the nextId*/public Long nextId() {return generateId();}/*** 生成唯一id的具体实现*/private synchronized long generateId() {long current = System.currentTimeMillis();if (current < lastTimestamp) {// 如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过,出现问题返回-1return -1;}if (current == lastTimestamp) {// 如果当前生成id的时间还是上次的时间,那么对sequence序列号进行+1sequence = (sequence + 1) & MAX_SEQUENCE;if (sequence == MAX_SEQUENCE) {// 当前毫秒生成的序列数已经大于最大值,那么阻塞到下一个毫秒再获取新的时间戳current = this.nextMs(lastTimestamp);}} else {// 当前的时间戳已经是下一个毫秒sequence = 0L;}// 更新上次生成id的时间戳lastTimestamp = current;// 进行移位操作生成int64的唯一ID//时间戳右移动23位long time = (current - START_TIME) << TIMESTAMP_LEFT_SHIFT;//workerId 右移动10位long workerId = this.workerId << WORKER_ID_SHIFT;return time | workerId | sequence;}/*** 阻塞到下一个毫秒*/private long nextMs(long timeStamp) {long current = System.currentTimeMillis();while (current <= timeStamp) {current = System.currentTimeMillis();}return current;}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/657695.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

QT自制软键盘 最完美、最简单、支持中文输入(二)

目录 一、前言 二、本自制虚拟键盘特点 三、中文输入原理 四、组合键输入 五、键盘事件模拟 六、界面 七、代码 7.1 frmKeyBoard 头文件代码 7.2 frmKeyBoard 源文件代码 八、使用示例 九、效果 十、结语 一、前言 由于系统自带虚拟键盘不一定好用&#xff0c;也不一…

牛客网-----------[NOIP2006]数列

题目描述 给定一个正整数k(3≤k≤15),把所有k的方幂及所有有限个互不相等的k的方幂之和构成一个递增的序列&#xff0c;例如&#xff0c;当k3时&#xff0c;这个序列是&#xff1a; 1&#xff0c;3&#xff0c;4&#xff0c;9&#xff0c;10&#xff0c;12&#xff0c;13&…

2024年重庆市公务员考试报名明天开始,招聘4530人!

2024年重庆公务员招录公告已出&#xff0c;招聘人数&#xff1a;4530人 ✅重庆市考重要时间节点 报名时间&#xff1a;2月1日9:00-2月6日9:00 缴费时间&#xff1a;2月8日 笔试时间&#xff1a;3月16日-17日 笔试查成绩时间&#xff1a;4月15日 面试时间&#xff1a;4月27日-2…

C++文件操作(1)

C文件操作 1.文本的写入及读取文本文件写入文本文件读取 2.二进制文件的写入及读取二进制文件写入二进制文件读取 3.小结 C也有处理文件的能力&#xff0c;其功能实现依赖文件流。文件流是C中用来处理文件输入输出的一种流类。文件流可以用于从文件中读取数据或将数据写入到文件…

《游戏-03_2D-开发》

基于《游戏-02_2D-开发》&#xff0c; 继续制作游戏&#xff1a; 首先要做的时切割人物Idle空闲状态下的动画&#xff0c; 在切割之前我们需要创建一个文件夹&#xff0c;用来存放动画控制器AnimatorContoller&#xff0c; 再创建一个人物控制器文件夹用来存放人物控制器&…

【Ubuntu 22.04.3 LTS】apt-get下载安装有关问题可能原因及解决方法

ubuntu 22.04.3 LTS unaccountably error 装啥啥没依赖 可能是用了不合适的源&#xff0c;换个就好了 Now, let’s take a look at the lsb_release output, with a special focus on the Codename, which could be a crucial piece of information. The lsb_release comm…

认识BPMN2.0

&#x1f496;专栏简介 ✔️本专栏将从Camunda(卡蒙达) 7中的关键概念到实现中国式工作流相关功能。 ✔️文章中只包含演示核心代码及测试数据&#xff0c;完整代码可查看作者的开源项目snail-camunda ✔️请给snail-camunda 点颗星吧&#x1f618; &#x1f496;说在前面 …

STM32单片机基本原理与应用(四)

直流电机驱动控制原理 1、电机正反转控制 在STM32中&#xff0c;直流电机的正反转控制主要通过改变电机输入电源的极性来实现。当电机的电压极性发生变化时&#xff0c;电机的旋转方向也会相应改变。在硬件电路中&#xff0c;可以通过继电器或晶体管等电子开关来切换电机的电源…

【TCP】重传与超时机制

前言 在网络通信的世界里&#xff0c;传输控制协议&#xff08;TCP&#xff09;扮演着一个至关重要的角色。它确保了数据的可靠传输&#xff0c;就像邮差确保每一封信都能准确无误地送达收件人手中一样。但是&#xff0c;网络环境充满了不确定性&#xff0c;数据包可能会因为各…

新书速览|Docker与Kubernetes容器运维实战

帮助读者用最短的时间掌握Docker与K8s运维技能 内容简介 随着云计算和容器技术的发展&#xff0c;Docker与Kubernetes已经成为各个企业首选的部署工具&#xff0c;使用它们可以提高系统的部署效率和运维能力&#xff0c;降低运维成本。本书是一本为初学者量身定制的Docker与Kub…

STM32F407移植OpenHarmony笔记4

上一篇写到make menuconfig报错&#xff0c;继续开整。 make menuconfig需要/device/soc/*下面有对应的Kconfig文件。 直接去gitee下载stm32的配置文件拿来参考用。 先提取Kconfig文件&#xff0c;后面再添加其它文件。https://gitee.com/openharmony/device_soc_st/tree/Open…

arcgis 如何将线路转为路面

在出外业的时候&#xff0c;用手机软件测出来的路&#xff08;线要素&#xff09;&#xff0c;需要转换成路面。具体操作如下&#xff1a; 1.打开线图层 2.菜单-地理处理-缓冲区 在缓冲区中&#xff0c;输入要转换的线要素&#xff0c;在线性单位下方填写要转换的面的宽度&am…

《Numpy 简易速速上手小册》第10章:Numpy案例研究和实践技巧(2024 最新版)

文章目录 10.1 实际案例分析10.1.1 基础知识10.1.2 完整案例&#xff1a;天气数据分析10.1.3 拓展案例 1&#xff1a;股票价格分析10.1.4 拓展案例 2&#xff1a;信号处理 10.2 Numpy 最佳实践10.2.1 基础知识10.2.2 完整案例&#xff1a;高效数组操作10.2.3 拓展案例 1&#x…

vue-cli初始化项目很慢?

第一种情况 大部分是由于npm的镜像源不是淘宝的 cmd输入npm config get registry查看是不是淘宝的&#xff0c;是的话看第二种情况试试不是的话输入npm config set registry https://registry.npm.taobao.org 第二种情况 vue-cli配置文件不是使用淘宝镜像源的 找到文件.vue…

已实现:vue、h5项目如何使用echarts实现雷达图、六边形图表

说实话&#xff0c;要说图表里&#xff0c;最强的应该属于echarts了&#xff0c;不管是接入难度上&#xff0c;还是样式多样性上&#xff0c;还有社区庞大程度上&#xff0c;都是首屈一指的&#xff0c;反观有的人习惯用chart.js了&#xff0c;这个无可厚非&#xff0c;但是如果…

微信小程序如何实现实时显示输入内容

如下所示&#xff0c;在许多场景中需要实时显示用户输入&#xff0c;具体实现见下文。 .wxml <input type"text" placeholder"请输入{{item.value}}(必填)" style"width:80%;" bindinput"get_required_value" data-info"{{it…

科技云报道:新趋势下,国产数据库或“春山可望”

科技云报道原创。 从540亿元到1286亿元——这是中国通信标准化协会大数据技术标准推进委员会针对中国数据库行业给出的一份预测报告。 报告指出&#xff0c;未来五年&#xff0c;中国数据库行业将从百亿级市场跨越成为千亿级市场。 最近两年&#xff0c;中国的数据库行业似乎…

Ubuntu 22.04 中文乱码解决方案

sudo apkg-reconfigure locales 按空格键选中

Jenkins自动化打包

Jenkins自动化打包 下载安装 我们直接从官网https://www.jenkins.io/download/ 下载所需的Jenkins文件 如上图所示, 选择Windows版本,下面就是一路安装即可,需要注意的是,选择作为系统服务选项, 不要自己设置账号密码登录. Web配置 安装完根据提示在浏览器打开 http://lo…

iZotope RX 10.4.2 mac激活版 音频修复和增强工具

iZotope RX 10 for Mac是一款专业的音频修复软件&#xff0c;旨在提供强大、精确的工具&#xff0c;让用户能够清晰、纯净地处理音频。以下是其主要功能和特点&#xff1a; 软件下载&#xff1a;iZotope RX 10.4.2 mac激活版下载 强大的降噪功能&#xff1a;iZotope RX 10采用了…