• UUID
  • 数据库自增序列
  • 雪花算法
  • 基于 redis 、 mongodb 、 zk等中间件生成
  • Leaf-segment

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、mongodb、zk等中间件生成

5、Leaf-segment


采用每次获取一个 ID区间段的方式来解决,区间段用完之后再去数据库获取新的号段,这样一来可以大大减轻数据库的压力。


核心字段: biz_tag , max_id , step。


biz_tag 用来区分业务, max_id 表示该 biz_tag 目前所被分配的 ID 号段的最大值, step表示每次分配的号段长度,原来每次获取 ID 都要访问数据库,现在只需要把 Step 设置的足够合理如 1000,那么现在可以在 1000 个 ID 用完之后再去访问数据库。



优点


扩张灵活,性能强能够撑起大部分业务场景。


ID 号码是趋势递增的,满足数据库存储和查询性能要求。


可用性高,即使 ID 生成服务器不可用,也能够使得业务在短时间内可用,为排查问题争取时间。


缺点


可能存在多个节点同时请求 ID 区间的情况,依赖 DB




双buffer :将获取一个号段的方式优化成获取两个号段,在一个号段用完之后不用立马去更新号段,还有一个缓存号段备用,这样能够有效解决这种冲突问题,而且采用双 buffer的方式,在当前号段消耗了10 % 的时候就去检查下一个号段有没有准备好,如果没有准备好就去更新下一个号段,当当前号段用完了就切换到下一个已经缓存好的号段去使用,同时在下一个号段消耗到 10 % 的时候,又去检测下一个号段有没有准备好,如此往复。




优点



基于 JVM 存储双 buffer 的号段,减少了数据库查询,减少了网络依赖,效率更高。



缺点



segment号段长度是固定的,业务量大时可能会频繁更新号段,因为原本分配的号段会一下用完如果号段长度设置的过长,但凡缓存中有号段没有消耗完,其他节点重新获取的号段与之前相比可能跨度会很大,动态调整 Step。


二、如何实现分库分表


将原本存储于单个数据库上的数据拆分到多个数据库,把原来存储在单张数据表的数据拆分到多张数据表中,实现数据切分,从而提升数据库操作性能。



分库分表的实现可以分为两种方式:垂直切分和水平 切分



水平:将数据分散到多张表,涉及分区键,


  • 分库:每个库结构一样,数据不一样,没有交集。库多了可以缓解io和cpu压力
  • 分表:每个表结构一样,数据不一样,没有交集。表数量减少可以提高sql执行效率、减轻cpu压力

垂直:将字段拆分为多张表,需要一定的重构


  • 分库:每个库结构、数据都不一样,所有库的并集为全量数据
  • 分表:每个表结构、数据不一样,至少有一列交集,用于关联数据,所有表的并集为全量数据

Master slave

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

代理层实现读写分离:

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

解决主库读的压力

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

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

在查询语句前加:

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

垂直分库:

mongodb java雪花算法ID 雪花算法和uuid的优缺点_数据

垂直分表:

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,只能通过程序调用,开发复杂。

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

水平分库

mongodb java雪花算法ID 雪花算法和uuid的优缺点_中间件_02

水平分表

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阿帕奇的

mongodb java雪花算法ID 雪花算法和uuid的优缺点_分布式_03