数据库架构演变概要
一.背景
为了适应业务增长,数据库数据量快速增长,性能日趋下降,稳定性不佳的实际情况,急需架构逐步演变适应未来的业务发展。
二.现状
【稳定性】数据库为单点,没有高可用和稳定性方案。
【数据量大】数据库目前400G左右,每个月大约100G的增量;
单表数据只增不删,数据持续增长;
【业务优化,剥离难】业务比较复杂,单纯的业务梳理剥离和优化,涉及业务方沟通及方案确立周期太长;
【查询慢】单机性能已出现过cpu瓶颈导致响应缓慢,大量的慢查询。
三.架构升级方案概要
数据库架构演变顺序:
1) 大表表级拆分多表方案【风险:中 效果:不会特别明显】
优点:通过拆分大表,拆分冷热数据,从而减少单表的数据扫描,进而优化数据库性能。
缺点:只能缓解大表的数据增量,但是不能彻底解决快速增长数据的本质问题。以目前的业务增量,即便做了冷热数据分离,也最多多支持几个月时间。
总结:只能缓解增量的症状[避免全表扫描的不必要的数据筛选],但不能解决本质问题。
2) UUID转int方案【风险:高 效果:应该比较明显】
优点:保守估计性能大约有6倍左右的提升(连表操作),索引及内存存储量降低为原来的1/4左右,表大小,数据库大小都会有相应的减少。
缺点:现有的数据库太大约400g,整体迁移过程和步骤相对非常复杂,需要自行通过编码实现迁移,难度很高。
总结:在cpu运算上和内存上会有明显优化,但是解决不了数据量(磁盘)本质问题。
3) 用户维度拆分方案【风险:高 效果:最好】
优点:通过用户维度拆分多个用户库和主库(这里的主库不一定是一个库,也可以是垂直拆分的多库),从而分散数据量,增加多个表和库锁的粒度,数据库的连接池,硬件资源等;用户维度性能提升n倍,主库可以通过读写分离提升性能;足够业务n年的数据发展和平滑扩展。
缺点:拆分多库,可用性和服务器稳定性下降(但是理论上出问题仅影响部分用户,可以保证总体可用性不会降低)。后期维护索引和更新,运维工作量加大多倍。业务代码基本大部分稍微调整(需要选择分库),部分业务代码需要分布式事务支持(基本现有代码的所有一致性事务需要调整)。
总结:全维度(cpu,内存,磁盘)优化数据库,较彻底解决数据库平行扩展和性能问题(除主库外)。相应的业务运维和运营的工作量加大和调整,但外围业务用户基本无感知架构变化。
4) 业务降低事务化方案【风险:中,效果:高并发下面效果好】
优点:通过降低事务等级,减少读共享锁,避免部分业务更新操作的阻塞;从而提升并发处理的性能(类似java读写锁原理,现在让数据库读不加锁或者部分加锁)。
缺点:部分数据会出现脏读(但是用户基本无感知)(资金财务相关的不得降低事务等级),但去锁并不会加快单条数据查询的速度。业务代码基本大部分需要根据业务场景,进行细粒度的事务等级控制(原则上一些查询校验,能不用事务就不用事务;大块事务尽量拆开多个事务;能通过Tcc或者最终一致性的业务幂等解决就不用强事务)(类似java方法级的锁,修改成方法内的多条代码级锁,减少锁粒度,保证尽快释放事务和锁)。
总结:有效的降低锁竞争导致的阻塞问题,能够有效提升业务高并发下面的总体并发能力,但是对无高并发下面的单笔业务处理耗时不会有明显提升,同时业务代码改动和梳理时间略费时间,但可根据情况自行取舍。mysql和sqlserver事务锁处理可能略有不同,但是总体降低事务等级思路不变。
5) 数据库读写分离方案【风险:中 效果:比较好】
优点:基于用户维度拆分后,特别是针对主库进行读写分离(根据用户维度读指定的读库); 将一些报表性查询,根据业务的实际情况选择读库或者写库(再加上低事务等级),极大的提升数据库的性能(主库中一些全局的配置可以做读写分离,用户维度考虑硬件层面读备热切换和读写分离)。
缺点:需要代码级别支持读库宕机,移除节点,平滑故障(需要分库分表中间件支持配置中心和数据库故障检测信息打通,自动故障转移)。要梳理业务逻辑,使一部分业务代码的查询切换到读库。
总结:读写分离主要解决用户维度拆分后,主库的读压力(也可以部分分布式缓存解决)和稳定性。从二八理论上讲,能分担大部分的性能到从库,但是从库会有数据延迟的可能性,故在业务读写分离处理时需考虑。
6) 绝对低耦合(独立性)服务数据库垂直拆分【风险:中 效果:未知】
优点:低耦合的服务化数据库拆分成独立服务或者功能,此服务化数据库又可以按照多维和技术特性进行更细粒度的服务化拆分和高性能,可以提供服务复用性和独立稳定性规划。进一步降低业务数据量,提高业务的纯性能。(一般独立服务拆分有个特点: 要么是共性业务,要么不带业务属性的功能,而且这种服务数据量不少或稳定性要求极高)
缺点:未来业务确保不会出现耦合度粘性的发展,细粒度服务会更多,但是开发稳定后一般不会更改。
总结:只拆绝对低耦合的业务为服务(如没把握,宁可不拆)
四.架构简单示意图