系统设计的垂直拆分和分平拆分

系统设计的垂直拆分和分平拆分

second60 20180420

1背景

当一个系统/网站,刚开始的时候,所有的业务模块和数据都是放在一起的,只有小量的人来开发和维护;

但当系统/网站不断丰富功能和业务的时候,系统将会变的越来越庞大,也会逐渐拆分成各个子系统来支撑,这此就需要把系统拆分,把原来强耦合的系统,拆分成弱耦合的多个子系统,数据表也因为数据量大,需要按业务垂直拆分和按大小来水平拆分。

 

2 系统的拆分

对于系统来说,一般都是系统初始设计时,就考虑好整个系统的架框,分好框架层次,和各个服务,考虑框架的通用性,可配置,可扩展,可兼容等特点。

虽然前期设计好系统框架,但难免随时业务和功能的扩张,系统变的比较庞大,需要对系统进行进一步的细分,主要有两个方向,即垂直扩展和水平扩展。

 

2.1 系统的垂直扩展

对于系统的垂直扩展,即把系统按业务分级,把可独立,或可划分的业务独立出子系统。

 

2.1.1 1

一个简单交易系统,会按业务分,独立出账户类服务,资金类服务,交易类服务。

优点:

1. 耦合度由强耦合变低耦合

2. 拆分后,各子系统接口通用,可服务于其他子系统

3. 每个子系统独立,子系统出问题,只会影响部份涉及此子系统的业务,不会影响全部业务


2.1.2 2

又如果,一个游戏后台业务进程

 

刚开始,可能游戏后台需求简单,把所有业务都放在一个服务中,可能包括:活动类,任务类,社交类。

但后面需求扩展后,可按业务分子服务,分为:活动类服务,任务类服务,社交系统等。

 

2.2 系统的水平扩展

对于系统的水平扩展,即相同的业务,多分几个服务,但各服务其实是一样的,也就是集群。

例如:一个订单服务,每天的订单量十万,一个服务可以搞定,但当订单量达到二十万压力很大时,可以多启一个相同的服务,即相当,两个服务,每个服务处理十万的订单量。当订单量逐渐增加,服务数量也随着增长。

参考:分布式和集群

 

2.3 数据库的扩展

系统运营初期,数据量比较小,所有数据表都在一个库中;但当业务量大后,数据量大,数据表也会变的很庞大,系统数据库操作将会变的比较慢。

 

比如:前期,数据表的大小可能就只有百万的数据量,但发展起来后,数据量增长到上千万一个表。无论是查找速度,还是更新速度,都会变的比较慢。

单表数据量大将会成为性能的瓶颈。

 

2.3.1 数据库的垂直拆分

数据库的垂直拆分,就是按业务,分库分表。

把原有的一个数据库,按业务分成多个数据库,每个数据库放不同业务的表。

垂直拆分,即把不同的表拆分到不同的数据库中。

 

例如:

一个电商系统,只有一个数据库,数据库中有用户表,订单表,支付表等。垂直扩展后,把数据库分成用户信息库,订单交易库,支付数据库。

 

垂直拆分的优点:

1. 拆分后,业务分类,规则明确清晰

2. 系统可扩展性好,可进一步细节

3. 数据库维护方便简单,相关功能的人,只需关注自已的关注的库

4. 可读性高,维护成本降低

 

缺点:

1. 之前有关联的不同库的表,不能再join, 交互通过接口方式解决,代码量增大

2. 每个子库关可能存在性能瓶颈,影响其他库,解决方法,可通过缓存解决

3. 解决不了单表数据量大的瓶颈问题

 

2.3.2 数据库的水平拆分

垂直拆分,其实就是业务的拆分,数据库拆分后,可以更加明确每个库的业务,也更方便维护,但解决不了大数据的瓶颈问题。这时就需要用到数据库的水平拆分。

 

数据库的水平拆分,简单点,就是分库分表。 把同一个表拆分到不同的数据库或数据表中。

 

水平拆分,按照某个字段(通常是主键)的规则,分散到多个库表中。库可以是同一个库,也可以是不同的库。

 

水平拆分的常用方法:

1. id取模,比如:uid% n ---->分到n个表中

2. 按年或月或日,折分表,比如:订单表,每日一个表放当日的订单。

3. 按范围分表,比如:1-999999放表11000000-1999999放表2

4. 按指定规则分表,如按地区等分表

5. 哈希拆分,但要避免哈希值冲突

6. 按枚举分表

7. 按热度分表,热度大的表分小点,热度小的历史数据表数据大点定期整理

 

2.3.2.1 例一-id取模

比如,某系统的一个用户表,原数据量增长后,数据量达到一千万用户,单表数据量比较大,考虑按uid取模分表,分10个表,即uid%10分别分到不同库表当中。

 

原表: t_user

分表后:

t_user_00

存放以0结尾的用户

 

t_user_01

存放以1结尾的用户

 

t_user_02

存放以2结尾的用户

 

t_user_03

存放以3结尾的用户

 

t_user_04

存放以4结尾的用户

 

t_user_05

存放以5结尾的用户

 

t_user_06

存放以6结尾的用户

 

t_user_07

存放以7结尾的用户

 

t_user_08

存放以8结尾的用户

 

t_user_09

存放以9结尾的用户

 


分表后,每个表的数据量将会减少为原来的十分之一,每个表还可以续继增加用户。

 

id取模分表的优点:

1. 每个表的数据分配比较均匀,即每个表约点n分之一的数据量,后台添加用户后也比罗均匀。

2. 业务处理中找表,无须添加复杂的找表的规则,只须uid%n取得操作哪个表t_user_(uid%n)

3. 查询和插入效率,相对单表,将更加有效

 

id取模分表的缺点:

1. 后续扩展比较困难,如果继续添加表,需重新整理表中的数据,然后再分到更多的表中,特别是7*24小时不停服的业务中。

 

2.3.2.2 例二-按年日期分表

比如,电商系统,每天的订单量都上千万上亿,因此,可以订单表,可以按日期做为一个维度,开分表。当然维度是很好的,按日期,按地区等。再这里如按日期为维度,每天一个订单表,事先建好一个月的表。

生产数据表:  t_user_order

当月初时,把上个月的数据放到历史订单表中

t_user_order_20180401

20180401订单表

 

t_user_order_20180402

20180402订单表

 

t_user_order_20180403

20180403订单表

 

t_user_order_20180404

20180404订单表

 

t_user_order_20180405

20180405订单表

 

t_user_order_20180406

20180406订单表

 

.......

 

 


按年月日分表优点:

1. 生产有一个主表,定期把数据放到日期表中,主表将变小

2. 对于数据备份,分析,或后台对历史数据的处理,不会影响到现有的生产库

3. 通常用来历史备份

4. 通过主表和备份表的方式,不会影响到原有逻辑

 

按年月日分表缺点:

1. 数据不一定均匀,如商城搞活动或节日,数据表可能大好几倍

2. 历史数据的读取,可能要定义一定的规则去历史表中读取

 

2.3.2.3按范围分表

比如,某表的生产数据id是从1开始自增1慢慢增长,可以按id范围分表。规则如下:

起始id

结束id

1

10000000

t_XX_01

db_1

10000001

20000000

t_XX_02

db_2

20000001

30000000

t_XX_03

db_3

30000001

40000000

t_XX_04

db_4

 

 

 

 


优点:

1. 数据是按表慢慢增长,使用率高,表1用完后再用表2,可以预见性的扩展表

 

缺点:

1. 数据活跃度不可预知,存在热点问题,即可能某个表操作很频繁,某个表操作很少

 

2.3.2.4按地区枚举分表

比如广东某电信后台经营分析系统,每天数据从21个地区分发数据到数据集市,因此,可以按地区枚举建表,因为每天数据量大,同时可以再加个时间维度。

地区分别为:

广州市

gz

 

江门市

jm

深圳市

sz

茂名市

mm

珠海市

zh

惠州市

hz

汕头市

st

梅州市

mz

佛山市

fs

汕尾市

sw

韶关市

sg

河源市

hy

湛江市

zj

阳江市

yj

肇庆市

zq

清远市

qy

东莞市

dg

中山市

zs

潮州市

cz

揭阳市

jy

云浮市

yf

 

 

 

按地区和按日期两个维度分表

惠州

 

 

t_record_hz_20180401

t_record_gz_20180401

t_record_sz_20180401

t_record_hz_20180402

t_record_gz_20180402

t_record_sz_20180402

t_record_hz_20180403

t_record_gz_20180403

t_record_sz_20180403

t_record_hz_20180404

t_record_gz_20180404

t_record_sz_20180404

t_record_hz_20180405

t_record_gz_20180405

t_record_sz_20180405

 

 

 


2.4水平和垂直分表的目的

水平分表目的

1. 解决表与表之间的IO竟争问题

 

垂直分表的目的

1. 解决单表中数据量大的问题

 

3 总结

无论是系统的垂直还是水平分子系统,还是数据库的垂直和水平拆分。目的都是为了整体系统的效率和维护开发成本。如果在初期规划好可能会出现的风险的瓶颈,并做好系统扩展,是比较容易应对出现的风险问题。

相反,当一个系统初期只为了开发效率而忽略了扩展和通用性,那个后期风险来的时候,可能整体系统的维护和扩展成本很大,甚至要重构系统,那是一件多么可怕的事情。


版权声明:本文为second60原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。