小麦带你学服注册体系十二

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: 分布式id

# 分布式ID


分布式ID的两大核心需求:


- **全局唯一**

- **趋势有序**

- **高性能**





## UUID


基于 `UUID` 实现全球唯一的ID。用作订单号`UUID`这样的字符串没有丝毫的意义,看不出和订单相关的有用信息;而对于数据库来说用作业务`主键ID`,它不仅是太长还是字符串,存储性能差查询也很耗时,所以不推荐用作`分布式ID`。


**优点**


- 生成足够简单,本地生成无网络消耗,具有唯一性


**缺点**


- 无序的字符串,不具备趋势自增特性

- 没有具体的业务含义,看不出和订单相关的有用信息

- 长度过长16 字节128位,36位长度的字符串,存储以及查询对MySQL的性能消耗较大,MySQL官方明确建议主键要尽量越短越好,作为数据库主键 `UUID` 的无序性会导致数据位置频繁变动,严重影响性能


**适用场景**


- 可以用来生成如token令牌一类的场景,足够没辨识度,而且无序可读,长度足够

- 可以用于无纯数字要求、无序自增、无可读性要求的场景




## 数据库自增ID


基于数据库的 `auto_increment` 自增ID完全可以充当 `分布式ID` 。当我们需要一个ID的时候,向表中插入一条记录返回`主键ID`,但这种方式有一个比较致命的缺点,访问量激增时MySQL本身就是系统的瓶颈,用它来实现分布式服务风险比较大,不推荐。相关SQL如下:


```mysql

CREATE DATABASE `SEQ_ID`;

CREATE TABLE SEQID.SEQUENCE_ID (

   id bigint(20) unsigned NOT NULL auto_increment,

   value char(10) NOT NULL default '',

   PRIMARY KEY (id),

) ENGINE=MyISAM;


insert into SEQUENCE_ID(value)  VALUES ('values');

```


**优点**


- 实现简单,ID单调自增,数值类型查询速度快


**缺点**


- DB单点存在宕机风险,无法扛住高并发场景


**适用场景**


- 小规模的,数据访问量小的业务场景

- 无高并发场景,插入记录可控的场景




## 数据库多主模式


单点数据库方式不可取,那对上述的方式做一些高可用优化,换成主从模式集群。一个主节点挂掉没法用,那就做双主模式集群,也就是两个Mysql实例都能单独的生产自增ID。


**问题**:如果两个MySQL实例的自增ID都从1开始,会生成重复的ID怎么办?


**解决方案**:设置`起始值`和`自增步长`


MySQL_1 配置:


```mysql

set @@auto_increment_offset = 1;     -- 起始值

set @@auto_increment_increment = 2;  -- 步长

-- 自增ID分别为:1、3、5、7、9 ......

```


MySQL_2 配置:


```mysql

set @@auto_increment_offset = 2;     -- 起始值

set @@auto_increment_increment = 2;  -- 步长

-- 自增ID分别为:2、4、6、8、10 ......

```


那如果集群后的性能还是扛不住高并发咋办?则进行MySQL扩容增加节点:



从上图可以看出,水平扩展的数据库集群,有利于解决数据库单点压力的问题,同时为了ID生成特性,将自增步长按照机器数量来设置。增加第三台`MySQL`实例需要人工修改一、二两台`MySQL实例`的起始值和步长,把`第三台机器的ID`起始生成位置设定在比现有`最大自增ID`的位置远一些,但必须在一、二两台`MySQL实例`ID还没有增长到`第三台MySQL实例`的`起始ID`值的时候,否则`自增ID`就要出现重复了,**必要时可能还需要停机修改**。


**优点**


- 解决DB单点问题


**缺点**


- 不利于后续扩容,而且实际上单个数据库自身压力还是大,依旧无法满足高并发场景


**适用场景**


- 数据量不大,数据库不需要扩容的场景


这种方案,除了难以适应大规模分布式和高并发的场景,普通的业务规模还是能够胜任的,所以这种方案还是值得积累。




## 数据库号段模式


号段模式是当下分布式ID生成器的主流实现方式之一,可以理解为从数据库批量的获取自增ID,每次从数据库取出一个号段范围,例如 (1,1000] 代表1000个ID,具体的业务服务将本号段,生成1~1000的自增ID并加载到内存。表结构如下:


```mysql

CREATE TABLE id_generator (

 id int(10) NOT NULL,

 max_id bigint(20) NOT NULL COMMENT '当前最大id',

 step int(20) NOT NULL COMMENT '号段的步长',

 biz_type int(20) NOT NULL COMMENT '业务类型',

 version int(20) NOT NULL COMMENT '版本号',

 PRIMARY KEY (`id`)

)

```


biz_type :代表不同业务类型


max_id :当前最大的可用id


step :代表号段的长度


version :是一个乐观锁,每次都更新version,保证并发时数据的正确性


| id   | biz_type | max_id | step | version |

| ---- | -------- | ------ | ---- | ------- |

| 1    | 101      | 1000   | 2000 | 0       |


等这批号段ID用完,再次向数据库申请新号段,对`max_id`字段做一次`update`操作,`update max_id= max_id + step`,update成功则说明新号段获取成功,新的号段范围是`(max_id ,max_id +step]`。


```mysql

update id_generator set max_id=max_id+${step}, version = version+1 where version=${version} and biz_type=${XXX}

```


由于多业务端可能同时操作,所以采用版本号`version`乐观锁方式更新,这种`分布式ID`生成方式不强依赖于数据库,不会频繁的访问数据库,对数据库的压力小很多。





## Redis模式


`Redis`也同样可以实现,原理就是利用`redis`的 `incr`命令实现ID的原子性自增。


```shell

# 初始化自增ID为1

127.0.0.1:6379> set seq_id 1

OK


# 增加1,并返回递增后的数值

127.0.0.1:6379> incr seq_id

(integer) 2

```


用`redis`实现需要注意一点,要考虑到`redis`持久化的问题。`redis`有两种持久化方式`RDB`和`AOF`:


- `RDB`:会定时打一个快照进行持久化,假如连续自增但`redis`没及时持久化,而这会`redis`挂掉了,重启`redis`后会出现ID重复的情况

- `AOF`:会对每条写命令进行持久化,即使`Redis`挂掉了也不会出现ID重复的情况,但由于incr命令的特殊性,会导致`Redis`重启恢复的数据时间过长




**优点**


- 有序递增,可读性强

- 能够满足一定性能


**缺点**


- 强依赖于Redis,可能存在单点问题

- 占用宽带,而且需要考虑网络延时等问题带来地性能冲击


**适用场景**


- 对性能要求不是太高,而且规模较小业务较轻的场景,而且Redis的运行情况有一定要求,注意网络问题和单点压力问题,如果是分布式情况,那考虑的问题就更多了,所以一帮情况下这种方式用的比较少


Redis的方案其实可靠性有待考究,毕竟依赖于网络,延时故障或者宕机都可能导致服务不可用,这种风险是不得不考虑在系统设计内的。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
6月前
|
安全 区块链
区块链农场游戏系统开发运营版/玩法详情/规则方案/案例设计/项目源码
Developing a blockchain farm game system is an interesting and challenging task. Here is a design solution that can help you get started developing such a system
|
6月前
|
监控 数据可视化 安全
Spring Cloud可视化智慧工地大数据云平台源码(人、机、料、法、环五大维度)
智慧工地平台是依托物联网、互联网、AI、可视化建立的大数据管理平台,是一种全新的管理模式,能够实现劳务管理、安全施工、绿色施工的智能化和互联网化。围绕施工现场管理的人、机、料、法、环五大维度,以及施工过程管理的进度、质量、安全三大体系为基础应用,实现全面高效的工程管理需求,满足工地多角色、多视角的有效监管,实现工程建设管理的降本增效,为监管平台提供数据支撑。
121 2
|
4月前
|
缓存 前端开发 测试技术
什么是七星创客系统丨七星创客系统开发规则玩法/设计方案/逻辑需求/案例项目/源码功能
七星创客系统开发指南是一个帮助开发人员理解并完成七星创客系统的开发任务的指南。以下是一个简要的开发指南需求:
|
新零售 人工智能 供应链
七星创客/艾倍生/推三返一/系统开发方案项目/开发案例/规则玩法/源码程序
  所谓新零售即是个人、企业以互联网为依托,通过运用大数据、人工智能等先进技术手段,对商品的生产、流通与销售过程进行升级改造,进而重塑业态结构与生态圈,并对线上服务、线下体验以及现代物流进行深度融合的零售新模式。
|
6月前
|
安全 BI 定位技术
同城校园外卖跑腿系统开发规则详细/需求步骤/案例设计/功能逻辑/源码版
同城校园外卖跑腿系统是为满足校园内用户对食品和商品的快速配送需求而设计的一种服务平台。
|
消息中间件 NoSQL 安全
|
存储 消息中间件 JSON
|
缓存 监控 负载均衡