分布式唯一ID实战

目录

    • 一、UUID
    • 二、数据库方式
      • 1、数据库生成之简单方式
      • 2、数据库生成 - 多台机器和设置步长,解决性能问题
      • 3、Leaf-segment 方案实现
      • 4、双 buffer 优化
      • 5、Leaf高可用容灾
    • 三、基于Redis实现分布式ID
    • 四、雪花算法

一、UUID

UUID的标准形式包含32个16进制数字,以 “ - ” 进行分割,形式为 8-4-4-4-12的32个字符,实例
550e8400-e29b-41d4-a716-446655440000。

优点:
- 性能高,本地生成,没有网络消耗

缺点:
- 不易存储,长度太长,32个16进制数字,128位
- 不安全,会暴露MAC地址
- UUID作为MySQL主键,会导致索引页分页,插入慢;长度太长,导致每个索引页存放的索引变少,索引效率降低


二、数据库方式

1、数据库生成之简单方式

利用给字段设置auto_increment_increment和auto_increment_offset来保证ID自增,每次业务使用下列SQL读写MySQL得到ID号作为业务的唯一ID

begin;
// 如果表中存在相同的数据,则将表中的数据删除,然后重新插入一条数据
2 REPLACE INTO Tickets64 (stub) VALUES ('a');
3 SELECT LAST_INSERT_ID();
4 commit;

在这里插入图片描述

优点:

  • 非常简单,利用现有数据库系统的功能实现,成本小
  • ID单调递增,可以实现一些对ID有特殊要求的业务

缺点

  • 强依赖DB,当DB异常时,整个系统不可使用,属于致命问题。应该配置主从复制以尽可能增加可用性(但是主从切换时可能会导致重复发号)
  • ID发号,性能瓶颈限制在单台MySQL的读写性能

2、数据库生成 - 多台机器和设置步长,解决性能问题

在分布式系统中我们可以多部署几台机器,每台机器设置不同的初始值,且步长和机器数相等

比如有两台机器。设置步长step为2,TicketServer1的初始值为1(1,3,5,7,9,11…)、TicketServer2的初始值为2(2,4,6,8,10…)

假设我们要部署N台机器,步长需设置为N,每台的初始值依次为0,1,2…N-1那么整个架构就变成了如下图所示:
在这里插入图片描述

这种架构貌似能够满足性能的需求,但有以下几个缺点:

  • 系统水平扩展比较困难,比如定义好了步长和机器台数之后,如果要添加机器该怎么
    做?假设现在只有一台机器发号是1,2,3,4,5(步长是1),这个时候需要扩容机器一台。可
    以这样做:把第二台机器的初始值设置得比第一台超过很多,比如14(假设在扩容时间之
    内第一台不可能发到14),同时设置步长为2,那么这台机器下发的号码都是14以后的偶
    数。然后摘掉第一台,把ID值保留为奇数,比如7,然后修改第一台的步长为2。让它符合
    我们定义的号段标准,对于这个例子来说就是让第一台以后只能产生奇数。扩容方案看起来
    复杂吗?貌似还好,现在想象一下如果我们线上有100台机器,这个时候要扩容该怎么做?
    简直是噩梦。所以系统水平扩展方案复杂难以实现。

  • ID没有了单调递增的特性,只能趋势递增,这个缺点对于一般业务需求不是很重要,可以容忍

  • 数据库压力还是很大,每次获取ID都得读写一次数据库,只能靠堆机器来提高性能

3、Leaf-segment 方案实现

Leaf-segment方案,在使用数据库的方案上,做了如下改变:

  • 原方案每次获取ID都得读写一次数据库,造成数据库压力大
  • 改为利用批量获取,每次获取一个segment(step决定大小)号段的值。用完之后再去数据库获取新的号段,可以大大的减轻数据库的压力
  • 各个业务不同的发号需求用biz_tag字段来区分,每个biz-tag的ID获取相互隔离,互不影响。
    如果以后有性能需求需要对数据库扩容,不需要上述描述的复杂的扩容操作,只需要对biz_tag分库分表就行。

数据库表设计如下
在这里插入图片描述
重要字段说明:

  • biz_tag用来区分业务
  • max_id表示该biz_tag目前所被分配的ID号段的最大值
  • step表示每次分配的号段长度。原来获取ID每次都需要写数据库,现在只需要把step设置得足够大,比如1000。那么只有当1000个号被消耗完了之后才会去重新读写一次数据库。读写数据库的频率从1减小到了1/step

系统架构
在这里插入图片描述


优缺点:
优点:

  • 将分配ID的压力由数据库转移到web服务(Leaf), Leaf服务可以很方便的进行线程扩展,性能完全能够支撑大多数业务场景
  • 容灾性高:Leaf服务内部有号段缓存,即使DB宕机,短时间内Leaf仍能正常对外提供服务
  • 可以自定义max_id的大小,非常方便业务从原有的ID方式上迁移过来

缺点:

  • ID号码不够随机,能够泄露发号数量的信息,不太安全
  • TP999数据波动大(当一个号段的ID使用完全后,leaf服务去mysql取号段,在此过程中应用服务如果有很大的并发过来,就会导致没有ID进行分配,从而导致响应时间变长,出现尖刺)
  • DB宕机的话,整个系统不可使用

4、双 buffer 优化

对于第二个缺点(响应存在峰值),Leaf-segment做了一些优化,简单的说就是:

Leaf 取号段的时机是在号段消耗完的时候进行的,也就意味着号段临界点的ID下发时间取决于下一次从DB取回号段的时间,并且在这期间进来的请求也会因为DB号段没有取回来,导致线程阻塞。如果请求DB的网络和DB的性能稳定,这种情况对系统的影响是不大的,但是假如取DB的时候网络发生抖动,或者DB发生慢查询就会导致整个系统的响应时间变慢。

为此,我们希望DB取号段的过程能够做到无阻塞,不需要在DB取号段的时候阻塞请求线程,即当号段消费到某个点时就异步的把下一个号段加载到内存中。而不需要等到号段用尽的时候才去更新号段。这样做就可以很大程度上的降低系统的TP999指标。

在这里插入图片描述

采用双buffer的方式,Leaf服务内部有两个号段缓存区segment。当前号段已下发10%时,如果下一个号段未更新,则另启一个更新线程去更新下一个号段。当前号段全部下发完后,如果下个号段准备好了则切换到下个号段为当前segment接着下发,循环往复

每个biz-tag都有消费速度监控,通常推荐segment长度设置为服务高峰期发号QPS的600倍(10分钟),这样即使DB宕机,Leaf仍能持续发号10-20分钟不受影响



5、Leaf高可用容灾

对于第三点“DB可用性”问题,我们目前采用一主两从的方式,同时分机房部署,Master和Slave之间采用半同步方式同步数据

这里,我其实是没怎么听懂的 !即使使用了主从,在数据同步过程不是还会有ID重复吗

在这里插入图片描述



三、基于Redis实现分布式ID



四、雪花算法

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

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

相关文章

Word 2019打开.doc文档后图片和公式不显示(呈现为白框)的解决办法

Word 2019打开.doc文档后图片和公式不显示(呈现为白框)的解决办法 目录 Word 2019打开.doc文档后图片和公式不显示(呈现为白框)的解决办法一、问题描述二、解决方法1.打开 WORD 2019,点击菜单中的“文件”;…

微服务05-Sentinel流量防卫兵

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件,主要以 流量 为切入点,从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。 S…

FBB简介

FBB FBB简介FBB组网名词解释FBB组网(从下至上)小结 FBB简介 FBB:Fixed BroadBand,固定宽带网络,是一种依托线缆介质进行传输的地面有线网络,区分与MBB,MBB是移动网络。 MBB是天上一张网&#x…

学习Vue:简介和优势

什么是 Vue.js? Vue.js 是一个用于构建用户界面的渐进式 JavaScript 框架。它专注于视图层,并且可以轻松地集成到现有的项目中。Vue.js 的设计理念是渐进式,这意味着您可以根据项目的需要逐步引入 Vue.js,从而更好地控制应用的复…

专注于创意设计,为您的小程序和网站建设带来更多的可能性

随着移动互联网的快速发展,越来越多的企业开始关注小程序和网站建设,以此来拓展业务和提升品牌形象。 在这个领域中,创意设计扮演着关键的角色。它不仅可以帮助企业打造独特的形象和品牌,还能够提高用户体验和购买决策的效率。 因…

Openlayers 实战 - 地图视野(View)- 图层 -(layer)- 资源(source)显示等级设置。

Openlayers 实战 - 地图视野(View)- 图层 -(layer)- 资源(source)显示等级设置。 问题原因核心代码完整代码:在线示例 在以往的项目维护中,出现一个问题,使用最新高清底图…

已有公司将ChatGPT集成到客服中心以增强用户体验

Ozonetel正在利用ChatGPT来改善客户体验。该公司表示,他们通过使用ChatGPT收集与客户互动过程收集的“语料”能够更有针对性地提高服务效率,提供个性化的用户体验,并实现更高的客户满意度。[1] 通过这套解决方案,客服中心将拥有一…

javascript写一个简单的闭包例子

当你在JavaScript中创建一个闭包时,你可以将函数定义在另一个函数的内部,并从外部函数中返回该函数。以下是一个简单的闭包示例: function outerFunction() {var outerVariable "I am from the outer function";function innerFu…

vue 图片转pdf

尝试了集中图片转pdf的方式, (1)最终较为优秀的一种是使用jspdf将图片转为pdf,支持JPG/JPEG/PNG/BMP/TIF/TIFF图片格式转换,详见我的另一篇文章: https://blog.csdn.net/Ann_52547/article/details/1322149…

MybatisPlus查询结果返回值为null

1、问题描述 返回值为null&#xff0c;程序不报错&#xff0c;但是条数好像是正确的。我出现问题的代码如下&#xff1a; 1、自定义类StudentMapper继承了BaseMapper接口 public interface StudentMapper extends BaseMapper<Student> { } 2、使用StudentMapper中的s…

centos 定时脚本检测tomcat是否启动,未启动情况下重新启动

编写脚本 tomcatMonitor.sh #!/bin/sh. /etc/profile . ~/.bash_profile#首先用ps -ef | grep tomcat 获得了tomcat进程信息&#xff0c;这样出来的结果中会包含grep本身&#xff0c; #因此通过 | grep -v grep 来排除grep本身&#xff0c;然后通过 awk {print $2}来打印出要…

Struts2一次请求参数问题的记录

最近&#xff0c;一次前端正常请求&#xff0c;但后台出现请求参数值的变化&#xff0c;导致报错&#xff0c;问题如下&#xff1a; 从入参request中查看请求参数&#xff0c;是一个Json字符串&#xff0c;其中有个description的键值对&#xff1b; 但是&#xff0c;接下来调用…

【需求输出】用户故事方法

文章目录 1、初识用户故事2、用户故事是描述需求的最好方式3、创建用户故事4、用户故事的分层管理5、编写用户故事的工具 1、初识用户故事 2、用户故事是描述需求的最好方式 3、创建用户故事 4、用户故事的分层管理 5、编写用户故事的工具

软件测试基础之软件缺陷处理

一、什么是缺陷 不满足用户确定需求、影响软件功能实现的问题、故障 缺陷就是人们通常所说的bug。 ex.一下哪一种选项不属于软件缺陷___。 A.软件没有实现产品规格说明所要求的功能 B.软件中出现了产品规格说明不应该出现的功能 C.软件实现了产品规格说明没有提到的功能 D.软…

Python实现透明隧道爬虫ip:不影响现有网络结构

作为一名专业爬虫程序员&#xff0c;我们常常需要使用隧道代理来保护个人隐私和访问互联网资源。本文将分享如何使用Python实现透明隧道代理&#xff0c;以便在保护隐私的同时不影响现有网络结构。通过实际操作示例和专业的解析&#xff0c;我们将带您深入了解透明隧道代理的工…

TiDB 应急运维脚本,更加方便的管理TiDB集群

TiDB 应急运维脚本&#xff0c;更加方便的管理TiDB集群 使用方法 使用方法&#xff1a;[tidblocalhost ~]$ which tiup ~/.tiup/bin/tiup编辑脚本&#xff0c;MYSQL_PASSWD 和 PORT 根据实际替换 [tidblocalhost ~]$ vi ~/.tiup/bin/ti#version 1.1 #author guanguanglei ##…

Base64编码-算法特别的理解

Base64 在DES加密和AES加密的过程中&#xff0c;加密的编码会出现负数&#xff0c;在ascii码表中找不到对应的字符&#xff0c;就会出现乱码。为了解决乱码的问题&#xff0c;一般结合base64使用 所谓Base64&#xff0c;即是说在编码过程中使用了64种字符&#xff1a;大写A到Z、…

【GO】配置环境使加速下载 go 模块

问题 在使用 go 语言编译时&#xff0c;需要安装一些包&#xff0c;这些包在使用 go build 或 go install 时&#xff0c;go 自己去下载&#xff0c;但是会有网络不通导致无法下载的问题 解决 配置 go 的环境变量 go env -w GOPROXYhttps://goproxy.io,direct

chartGPT生成:python中连接函数的使用

在Python中&#xff0c;连接函数用于将多个字符串拼接在一起。常见的连接函数有join和操作符。 join函数&#xff1a; strings ["Hello", "world", "!"] result " ".join(strings) print(result) # 输出&#xff1a;Hello world …

Azure资源命名和标记决策指南

参考 azure创建虚拟机在虚拟机中选择编辑标签&#xff0c;并添加标记&#xff0c;点击应用 3.到主页中转到所有资源 4. 添加筛选器并应用 5.查看结果&#xff0c;筛选根据给服务器定义的标签筛选出结果。 参考链接: https://learn.microsoft.com/zh-cn/azure/cloud-adoption…