112022.08

数据库架构选型与落地,看这篇就够了

2022.08.11

随着时间和业务的发展,数据库中的数据量增长是不可控的,库和表中的数据会越来越大,随之带来的是更高的磁盘、IO、系统开销,甚至性能上的瓶颈,而单台服务器的资源终究是有限的。因此在面对业务扩张过程中,应用程序对数据库系统的健壮性,安全性,扩展性提出了更高的要求。以下,我从数据库架构、选型与落地来让大家入门。


0x1.数据库架构有哪些

不妨想一想,数据库会面临什么样的挑战呢?


业务刚开始我们只用单机数据库就够了,但随着业务增长,数据规模和用户规模上升,这个时候数据库会面临IO瓶颈、存储瓶颈、可用性、安全性问题。


IO瓶颈:大规模的用户查询和写入,由于单机数据库的IO有限无法支撑;

存储瓶颈:大量数据的存储让数据库原有的逻辑结构已经无法适用,性能急剧下降;

可用性:重点业务系统对数据库的要求是不间断地提供服务,一旦遇到突发事件时系统可以快速恢复;

安全性:数据的容灾能力,保证数据在任何时候不会丢失(避免运维删库跑路);

为了解决上述的各种问题,数据库衍生了出不同的架构来解决不同的场景需求。


一、主从架构


将数据库的写操作和读操作分离,主库接收写请求,使用多个从库副本负责读请求,从库和主库同步更新数据保持数据一致性,从库可以水平扩展,用于面对读请求的增加。这个模式也就是常说的读写分离,针对的是小规模数据,而且存在大量读操作的场景。因为主从的数据是相同的,一旦主库宕机的时候,从库可以切换为主库提供写入,所以这个架构也可以提高数据库系统的安全性和可用性;优点:


结构简单,技术成熟,市面上大多数数据库都支持这个方案;

业务入侵最低;

数据拥有多个容灾副本,提高数据安全性;

当主服务器故障时,可立即切换到其他服务器,提高系统可用性;

缺点:


无法支持大量写的场景,因为主库无法水平扩展;

从库的数据都是全量并且重复的,浪费存储空间;

数据一致性问题;

数据同步延迟问题;

二、垂直分库


在数据库遇到IO瓶颈过程中,如果IO集中在某一块的业务中,这个时候可以考虑的就是垂直分库,将热点业务拆分出去,避免由热点业务的密集IO请求影响了其他正常业务,所以垂直分库也叫业务分库。优点:


业务清晰,专库专用,契合服务化的拆分;

冷热数据分离,业务数据相互独立各不干扰;

独立的数据库便于日常迭代和维护;

缺点:


数据之间无法联表,只能在程序中多次查询组合或者冗余数据;

需要解决分布式事务问题;

三、水平分片


在数据库遇到存储瓶颈的时候,由于数据量过大造成索引性能下降。这个时候可以考虑将数据做水平拆分,针对数据量巨大的单张表,按照某种规则,切分到多张表里面去。但是这些表还是在同一个库中,所以库级别的数据库操作还是有IO瓶颈(单个服务器的IO有上限)。所以水平分表主要还是针对数据量较大,整体业务请求量较低的场景。优点:


单表数据量减少,性能得到提升;

数据都在同个数据库中,没有跨库事务问题;

缺点:


需要解决跨片查询问题;

数据分片在扩容时需要迁移;

存在IO瓶颈,无法处理大量业务请求;

四、分库分表


在数据库遇到存储瓶颈和IO瓶颈的时候,数据量过大造成索引性能下降,加上同一时间需要处理大规模的业务请求,这个时候单库的IO上限会限制处理效率。所以需要将单张表的数据切分到多个服务器上去,每个服务器具有相应的库与表,只是表中数据集合不同。分库分表能够有效地缓解单机和单库的性能瓶颈和压力,突破IO、连接数、硬件资源等的瓶颈。优点:


单表数据量减少,性能得到提升;

数据分散在多个服务器,提高了整体系统的负载能力;

缺点:


需要解决跨片查询问题;

数据分片在扩容时需要迁移;

需要处理广播表(公共表)问题;

需要解决分布式事务问题;

注:分库还是分表核心关键是有没有IO瓶颈。分片方式都有什么呢?RANGE(范围分片)将业务表中的某个关键字段排序后,按照顺序从0到10000一个表,10001到20000一个表。最常见的就是按照时间切分(月表、年表)。比如将6个月前,甚至一年前的数据切出去放到另外的一张表,因为随着时间流逝,这些表的数据被查询的概率变小,银行的交易记录多数是采用这种方式。优点:


天然便于水平扩展,后期想对整个分片集群扩容时,只需要添加节点即可,无需对其他分片的数据进行迁移;

使用分片字段进行范围查找时,连续分片可快速定位分片进行快速查询,有效避免跨分片查询的问题。

缺点:


热点数据成为性能瓶颈。连续分片可能存在数据热点,例如按时间字段分片,有些分片存储最近时间段内的数据,可能会被频繁地读写,而有些分片存储的历史数据,则很少被查询。

HASH(哈希分片)将订单作为主表,然后将其相关的业务表作为附表,取用户id然后hash取模,分配到不同的数据表或者数据库上。优点:


数据分片相对比较均匀,不容易出现热点和并发访问的瓶颈。

缺点:


后期分片集群扩容时,需要迁移旧的数据,容易面临跨分片查询的复杂问题。比如上例中,如果频繁用到的查询条件中不带用户id时,将会导致无法定位数据库,从而需要同时向所有库发起查询,再在内存中合并数据,取最小集返回给应用,分库反而成为拖累。


讲到这里,我们已经知道数据库有哪些架构,解决的是哪些问题,因此,我们在日常设计中需要根据数据的特点,数据的倾向性,数据的安全性等来选择不同的架构。那么,我们应该如何选择数据库架构呢?虽然把上面的架构全部组合在一起可以形成一个强大的高可用,高负载的数据库系统,但是架构选择合适才是最重要的。混合架构虽然能够解决所有的场景的问题,但是也会面临更多的挑战,你以为的完美架构,背后其实有着更多的坑。所以,在选择数据库架构之前,我们先思考一下,实际上会面临什么样的难题?

1、对事务支持分库分表后(无论是垂直还是水平拆分),就成了分布式事务了,如果依赖数据库本身的分布式事务管理功能去执行事务,将付出高昂的性能代价(XA事务);如果由应用程序去协助控制,形成程序逻辑上的事务,又会造成编程方面的负担(TCC、SAGA)。


2、多库结果集合并(group by,order by)由于数据分布于不同的数据库中,无法直接对其做分页、分组、排序等操作,一般应对这种多库结果集合并的查询业务都需要采用数据清洗、同步等其他手段处理(TIDB、KUDU等)。


3、数据延迟主从架构下的多副本机制和水平分库后的聚合库都会存在主数据和副本数据之间的延迟问题。


4、跨库join分库分表后表之间的关联操作将受到限制,我们无法join位于不同分库的表(垂直),也无法join分表粒度不同的表(水平), 结果原本一次查询就能够完成的业务,可能需要多次查询才能完成。


5、分片扩容水平分片之后,一旦需要做扩容时。需要将对应的数据做一次迁移,成本代价都极高的。


6、ID生成分库分表后由于数据库独立,原有的基于数据库自增ID将无法再使用,这个时候需要采用其他外部的ID生成方案。