分布式id生成方案,如何实现分库分表

分布式id生成方案?

1、UUID

1 ,当前日期和时间 时间戳
2 ,时钟序列。 计数器
3 ,全局唯一的 IEEE 机器识别号,如果有网卡,从网卡 MAC 地址获得,没有网卡以其他方式获得。
优点:代码简单,性能好(本地生成,没有网络消耗),保证唯一(相对而言,重复概率极低可以忽略)
缺点
每次生成的 ID 都是无序的,而且不是全数字,且无法保证趋势递增。
UUID 生成的是字符串,字符串存储性能差,查询效率慢,写的时候由于不能产生顺序的append 操作,需要进 行insert操作,导致频繁的页分裂,这种操作在记录占用空间比较大的情况下,性能下降比较大,还会增加读 取磁盘次数UUID 长度过长,不适用于存储,耗费数据库性能。
ID 无一定业务含义,可读性差。
有信息安全问题,有可能泄露 mac 地址。

2、数据库自增序列

单机模式:
优点:
实现简单,依靠数据库即可,成本小。
ID 数字化,单调自增,满足数据库存储和查询性能。
具有一定的业务可读性。(结合业务 code
缺点
强依赖 DB ,存在单点问题,如果数据库宕机,则业务不可用。
DB 生成 ID 性能有限,单点数据库压力大,无法扛高并发场景。
信息安全问题,比如暴露订单量, url 查询改一下 id 查到别人的订单。
数据库高可用:多主模式做负载,基于序列的起始值和步长设置,不同的初始值,相同的步长,步长大于节点数。
优点
解决了 ID 生成的单点问题,同时平衡了负载。
缺点
系统扩容困难:系统定义好步长之后,增加机器之后调整步长困难。
数据库压力大:每次获取一个 ID 都必须读写一次数据库。
主从同步的时候:电商下单 -> 支付 insert master db select数据 ,因为数据同步延迟导致查不到这个数 据。加 cache( 不是最好的解决方式 ) 数据要求比较严谨的话查 master 主库。

3、雪花算法

生成一个64bit 的整性数字
第一位符号位固定为 0 41 位时间戳 10 workId 12位序列号,位数可以有不同实现。
 
雪花算法是一种生成分布式全局唯一 ID 的算法,它会得到一个 64 位长度的 long 类型数据。
其中这 64 位的数据,由 4 个部分组成。
第一个 bit 位是符号位,因为 id 不会是负数,所以它一般是 0;
接着用 41 个 bit 位来表示毫秒单位的时间戳;
再用 10 个 bit 位来表示工作机器 id;
最后 12 个 bit 位表示递增的序列号;
把这 64 个 bit 位拼接成一个 long 类型的数字,就是雪花算法的实现。
优点
  • 每个毫秒值包含的ID值很多,不够可以变动位数来增加,性能佳(依赖workId的实现)。
  • 时间戳值在高位,中间是固定的机器码,自增的序列在低位,整个ID是趋势递增的。
  • 能够根据业务场景数据库节点布置灵活挑战bit位划分,灵活度高。
缺点
  • 强依赖于机器时钟,如果时钟回拨,会导致重复的ID生成,所以一般基于此的算法发现时钟回拨,都会抛异常处理,阻止ID生成,这可能导致服务不可用。

4、基于redis、zk、mongodb等中间件生成

Redis生成ID

  • 定义:利用Redis的原子操作(如INCR和INCRBY命令)生成唯一的递增数值作为ID。
  • 优点
    • 高性能,支持高并发环境。
    • 简单且易于扩展。
  • 缺点
    • 依赖于外部服务(Redis),需要管理和维护额外的基础设施。
  • 网络依赖性:高度依赖网络。

Zookeeper生成ID

  • 定义:通过Zookeeper的znode数据版本来生成序列号,可以生成32位或64位的数据版本号。
  • 优点
    • 利用Zookeeper的分布式特性,保证ID的全局唯一性。
  • 缺点
    • 依赖Zookeeper,系统复杂度增加。
    • 在高并发环境下性能可能不理想。
  • 网络依赖性:高度依赖网络。

5、数据库号段模式  Leaf-segment  

  • 定义:从数据库批量获取自增ID号段,然后在本地缓存并生成ID,直到号段用完再向数据库申请新的号段。美团的。
核心字段:biz_tagmax_idstep。
biz_tag 用来区分业务, max_id 表示该 biz_tag 目前所被分配的 ID 号段的最大值, step表示每次分配的号段长度,原来每次获取 ID 都要访问数据库,现在只需要把 Step 设置的足够合理如 1000,那么现在可以在 1000 ID 用完之后再去访问数据库。
优点
减少对数据库的频繁访问,提高性能。
扩张灵活,性能强能够撑起大部分业务场景。
ID 号码是趋势递增的,满足数据库存储和查询性能要求。
可用性高,即使 ID 生成服务器不可用,也能够使得业务在短时间内可用,为排查问题争取时间。
缺点
  • 仍然存在单点故障风险(可通过集群模式解决)。
  • 如果服务在用完ID段之前下线或重启,可能导致ID浪费。
  • 可能存在多个节点同时请求ID区间的情况,依赖DB。
  • 对网络的依赖相对较低,只在申请新的ID段时需要访问数据库。
buffer :将获取一个号段的方式优化成获取两个号段,在一个号段用完之后不用立马去更新号段,还有一个缓存号段备用,这样能够有效解决这种冲突问题,而且采用双 buffer的方式,在当前号段消耗了10 % 的时候就去检查下一个号段有没有准备好,如果没有准备好就去更新下一个号段,当当前号段用完了就切换到下一个已经缓存好的号段去使用,同时在下一个号段消耗到 10 % 的时候,又去检测下一个号段有没有准备好,如此往复。
缺点
segment号段长度是固定的,业务量大时可能会频繁更新号段,因为原本分配的号段会一下用完如果号段长度设置的过长,但凡缓存中有号段没有消耗完,其他节点重新获取的号段与之前相比可能跨度会很大,动态调整 Step。

6、自定义算法

  • 根据具体业务需求,可以设计自定义的分布式ID生成算法。这些算法可能结合时间戳、随机数、机器标识等多种因素来生成唯一ID。
  • 自定义算法的优点是可以根据业务需求灵活调整,但缺点是需要额外的开发和维护工作。

二、如何实现分库分表

将原本存储于单个数据库上的数据拆分到多个数据库,把原来存储在单张数据表的数据拆分到多张数据表中,实现数据切分,从而提升数据库操作性能。
分库分表的实现可以分为两种方式:垂直切分和水平 切分
水平:将数据分散到多张表,涉及分区键,
  • 分库:每个库结构一样,数据不一样,没有交集。库多了可以缓解iocpu压力
  • 分表:每个表结构一样,数据不一样,没有交集。表数量减少可以提高sql执行效率、减轻cpu压力
垂直:将字段拆分为多张表,需要一定的重构
  • 分库:每个库结构、数据都不一样,所有库的并集为全量数据
  • 分表:每个表结构、数据不一样,至少有一列交集,用于关联数据,所有表的并集为全量数据

Master slave

查多于写的场景,写在主库,查询在从库,复制Binlog日志。

代理层实现读写分离:

atlas:Db1、db2、proxy代理 配置文件 proxy配置主从关系 设置端口1234 通过代理层进行查询从库

解决主库读的压力

强制路由 主从同步走网络,极端情况下出现延迟,从库:I/O线程 进行binlog + DB线程

导致数据不能及时同步,从库查不到主库已有的数据,同步不及时,解决?强制路由

在查询语句前加:

/*master*/ select * from t1 where a =1;

垂直分库:

垂直分表:

User表

Tid

Name

Password

Sex

Email

Tel

QQ

Wx

Hobby

1

张三

123

1

2

3

4

5

6

2

李四

456

1

3

5

6

7

8

User_base

Tid

Name

Password

1

张三

123

2

李四

456

User_info

Tid

Sex

Email

Tel

QQ

Wx

Hobby

1

1

2

3

4

5

6

2

1

3

5

6

7

8

垂直拆分:每个库表的结构不一样、每个库表的数据都至少有一列、每个库表的并集是全部数据。

优点:拆分业务清晰(专库专用)、数据维护简单,按业务不同放到不同机器上

缺点:如果单表的数据量大,读写压力大;

受某种业务场景决定、限制,一个业务影响其他数据库的瓶颈,性能问题,如双11,商品、订单库压力大,用户库压力小;

部分业务无法关联join,只能通过程序调用,开发复杂。

数据分布不均匀,有的库数据量大。

水平分库

水平分表

User表

Tid

Name

Password

Sex

Email

Tel

QQ

Wx

Hobby

1

张三

123

1

2

3

4

5

6

2

李四

456

1

3

5

6

7

8

User表1

Tid

Name

Password

Sex

Email

Tel

QQ

Wx

Hobby

1

张三

123

1

2

3

4

5

6

User表2

Tid

Name

Password

Sex

Email

Tel

QQ

Wx

Hobby

2

李四

456

1

3

5

6

7

8

水平拆分:每个库表的结构一样、每个库表的数据不一样、每个库表的并集是全量数据、数据均分。

优点:单库的数据量小,有助于性能提升;

切分的表的结构相同,程序改造较少;

提高系统稳定性和负载能力

缺点: 数据扩容困难

拆分规则很难抽象出来

分片事务的一致性 部分业务无法关联join 只能通过程序调用

需要分布式事务

跨库查询问题?怎样确认一条数据在哪个库

分布式全局唯一ID?每个库中的id一样咋办

分库分表的中间件:

Proxy代理层:mycatatlas、mysql-proxy

jdbc增强 应用层:shardingshpere、TDDL  shardingshpere阿帕奇的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值