首页 > 国内 > 正文

JAVA互联网架构-分库分表分布式下如何实现ID全局唯一性

来源: | 2017-09-25 18:18:18

序言

1 基本思想之什么是分库分表?

从字面上简单理解,就是把原本存储于一个库的数据分块存储到多个库上,把原本存储于一个表的数据分块存储到多个表上。

2 基本思想之为什么要分库分表?

数据库中的数据量不一定是可控的,在未进行分库分表的情况下,随着时间和业务的发展,库中的表会越来越多,表中的数据量也会越来越大,相应地,数据操作,增删改查的开销也会越来越大;另外,由于无法进行分布式式部署,而一台服务器的资源(CPU、磁盘、内存、IO等)是有限的,最终数据库所能承载的数据量、数据处理能力都将遭遇瓶颈。

3 分库分表的实施策略。

分库分表有垂直切分和水平切分两种。

3.1 何谓垂直切分,即将表按照功能模块、关系密切程度划分出来,部署到不同的库上。例如,我们会建立定义数据库workDB、商品数据库payDB、用户数据库userDB、日志数据库logDB等,分别用于存储项目数据定义表、商品定义表、用户数据表、日志数据表等。

3.2 何谓水平切分,当一个表中的数据量过大时,我们可以把该表的数据按照某种规则,例如userID散列,进行划分,然后存储到多个结构相同的表,和不同的库上。例如,我们的userDB中的用户数据表中,每一个表的数据量都很大,就可以把userDB切分为结构相同的多个userDB:part0DB、part1DB等,再将userDB上的用户数据表userTable,切分为很多userTable:userTable0、userTable1等,然后将这些表按照一定的规则存储到多个userDB上。

3.3 应该使用哪一种方式来实施数据库分库分表,这要看数据库中数据量的瓶颈所在,并综合项目的业务类型进行考虑。

如果数据库是因为表太多而造成海量数据,并且项目的各项业务逻辑划分清晰、低耦合,那么规则简单明了、容易实施的垂直切分必是首选。

而如果数据库中的表并不多,但单表的数据量很大、或数据热度很高,这种情况之下就应该选择水平切分,水平切分比垂直切分要复杂一些,它将原本逻辑上属于一体的数据进行了物理分割,除了在分割时要对分割的粒度做好评估,考虑数据平均和负载平均,后期也将对项目人员及应用程序产生额外的数据管理负担。

在现实项目中,往往是这两种情况兼而有之,这就需要做出权衡,甚至既需要垂直切分,又需要水平切分。我们的游戏项目便综合使用了垂直与水平切分,我们首先对数据库进行垂直切分,然后,再针对一部分表,通常是用户数据表,进行水平切分。

分库分表:

跨库的问题

分布式事务问题

查询数据结果集合并

全局唯一性ID保证

要求:

1、全局唯一性:不能出现重复的id号(基本的要求)。

2、信息安全:防止恶意用户规矩id的规则来获取数据。混淆效果

3、数据递增:保证我下一个ID一定大于上一个ID。

当前201709122030 下一个:201709122031 下一个:201709122032

互斥关系:信息安全、数据递增规律

CREATE TABLE `tl_id` (

`id` varchar(255) NOT NULL,

PRIMARY KEY (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

业界分案:

UUID:

通用唯一识别码 16个字节128位的长数字、

组成部分:当前日期和时间序列+全局的唯一性网卡mac地址

执行任务数:10000

------------------------

所有线程共耗时:38.305 s

并发执行完耗时:449.0 ms

单任务平均耗时:3.8305 ms

单线程最小耗时:0.0 ms

单线程最大耗时:193.0 ms

总结:

优点

缺点

代码实现简单、不占用宽带、数据迁移不受影响

无序、无法保证趋势递增(要求3)字符存储、传输、查询慢、不可读

Snowflake雪花算法

国外的twitter分布式下iD生成算法

1bit+41bit+10bit+10+bit=62bit

高位随机+毫秒数+机器码(数据中心+机器id)+10的流水号

国内:

保证数据的唯一性就行了 IDC机房。

总结:

优点

缺点

代码实现简单、不占用宽带、数据迁移不受影响、低位趋势递增

强以来时钟(多台服务器时间一定要一样)、无序无法保证趋势递增(要求3)

Mysql:

JAVA互联网架构-分库分表分布式下如何实现ID全局唯一性

奇数跟我们偶数 递增步长2

适合小型互联网公司、比如可以知道我们一定生成的ID数量 五万的订单量

一年1千8百万

Mysql一张表500万

如果公司每天订单量5万的数据 我们用mysql设置步长位100的话可以用27年

只能为100库 公司来到风投了 每天的订单量50万100万的时候

总结:

优点

缺点

代码实现方便、性能不错、数字排序、可读性很强

受限数据库、扩展麻烦、插入数据库才能拿到ID、单点故障的问题

主从同步的时候:电商下单->支付 insert master db select 数据 因为数据同步延迟导致查不到这个数据。加cache(不是最好的解决方式)数据要求比较严谨的话查master主库。

CREATE TABLE `tl_num` (

`id` bigint(11) NOT NULL AUTO_INCREMENT,

KEY (`id`) USING BTREE

) ENGINE=InnoDB auto_increment=1 DEFAULT CHARSET=utf8;

Redis:

JAVA互联网架构-分库分表分布式下如何实现ID全局唯一性

执行任务数:10000

------------------------

所有线程共耗时:136.587 s

并发执行完耗时:1.515 s

单任务平均耗时:13.6587 ms

单线程最小耗时:1.0 ms

单线程最大耗时:254.0 ms

总结:

优点

缺点

不依赖数据、灵活方便、性能优于数据库的、没有单点故障(高可用)

需要占用网络资源、性能要比本地生成慢、需要增加插件

以上是对分布式下如何实现ID总结,分享给大家,希望大家可以了解什么是mysql分库分表。觉得收获的话可以点个关注收藏转发一波喔,谢谢大佬们支持。(吹一波,233~~)

JAVA互联网架构-分库分表分布式下如何实现ID全局唯一性

【电商岛】

聚焦
热门推荐
图片
Top