大家好呀,我是沉默。

        以下是我结合平常自己学习收集的一些资料,以系统、全面的方式整理成了这篇文章,也希望能让一些有需要的同行在工作上、成长上提供一定的帮助。

一、数据库性能瓶颈  

zabbix数据库性能优化_数据

二、数据库优化思路  

1. 慢的本质  

zabbix数据库性能优化_Redis_02

关系型数据库:时间复杂度是 O(log n),存储结构是函式存储,能优化的一般只有数据量

高负载:原因有高并发请求、复杂查询等,导致 CPU、磁盘繁忙,而服务器资源不足则会导致慢查询等问题。该类型问题一般会选择集群、数据冗余的方式分担压力

2. 优化层面  

zabbix数据库性能优化_Redis_03

SQL/索引、硬件两个层面很容易理解,所以本次主要从存储结构、存储系统中间两层的优化方案进行整理

三、数据库优化方案  

zabbix数据库性能优化_zabbix数据库性能优化_04

数据类型:静态数据,更新频率低,无需多连表的,where 过滤比较少。动态数据,更新频率高,通过动态条件筛选过滤。

收益类型:短期收益,处理成本低,能紧急应对;长期收益,处理成本高,扩展性更好

1. 减少数据量  

zabbix数据库性能优化_Redis_05

1.数据归档

zabbix数据库性能优化_Redis_06

zabbix数据库性能优化_数据库_07

        建议优先考虑该方案,主要通过数据库作业把非热点数据迁移到历史表,如果需要查历史数据,可新增业务入口路由到对应的历史表(库)

2.中间表(结果表)

zabbix数据库性能优化_数据_08

        中间表(结果表)其实就是利用调度任务把复杂查询的结果跑出来存储到一张额外的物理表,因为这张物理表存放的是通过跑批汇总后的数据,因此可以理解成根据原有的业务进行了高度的数据压缩

           

           

3.数据序列化存储

zabbix数据库性能优化_数据库_09

zabbix数据库性能优化_数据_10

        在数据库以序列化存储的方式,对于一些不需要结构化存储的业务来说是一种很好减少数据量的方式,特别是对于一些 M*N 的数据量的业务场景,如果以 M 作为主表优化,那么就可以把数据量维持最多是 M 的量级

        这种方案属于一种临时性的优化方案,因为从序列化后会丢失了部分字段的查询能力,还有可优化性是有限的

4.分库分表

zabbix数据库性能优化_Redis_11

zabbix数据库性能优化_数据库_12

zabbix数据库性能优化_数据_13

        分库分表作为数据库优化的一种非常经典的优化方案,特别是在以前 NoSQL 还不是很成熟的年代,这个方案就如救命草一般的存在。如今也有不少同行也会选择这种优化方式,但是分库分表是一种优化成本很大的方案。

        建议:

        §分库分表是实在没有办法的办法,应放到最后选择

        §优先选择 NoSQL 代替,因为 NoSQL 诞生基本上为了扩展性与高性能

        §究竟分库还是分表?量大则分表,并发高则分库

2. 用空间换性能  

zabbix数据库性能优化_数据_14

1.分布式缓存

zabbix数据库性能优化_Redis_15

        缓存分为客户端缓存、网络中缓存和服务端缓存,本次主要从分布式缓存进行整理。分布式缓存系统会优先选择 NoSQL 的键值型数据库,例如 Memcached、Redis,而 Redis 的数据结构多样性,高性能,易扩展性也逐渐占据了分布式缓存的主导地位。

        缓存策略分为 Cache-Aside、Read/Wirte-Through、Write-Back,Redis 的更新策略用的是 Cache-Aside。

zabbix数据库性能优化_zabbix数据库性能优化_16

        虽说 Redis 访问速度很快。但毕竟是一个远程调用,而且菜单树的数据很多,在网络传输的过程中,是有些耗时的。所以我们可以使用二级缓存(本地缓存结合 Redis 缓存使用),降低 Redis 压力,同时本地缓存没有连接开销,性能更优。

zabbix数据库性能优化_数据库_17

2.一主多从

zabbix数据库性能优化_数据库_18

        一主多从是部署多台从库只读实例,通过冗余主库的数据来分担读请求的压力,路由算法可有代码实现或者中间件解决。

        一主多从在还没找到根治方案前是一个非常好的应急解决方案,特别是在现在云服务的年代,扩展从库是一件非常方便的事情,而且一般情况只需要运维或者 DBA 解决就行,无需开发人员接入。

        当然这方案也有缺点,因为数据无法分片,所以主从的数据量完全冗余过去,也会导致高的硬件成本。从库也有其上限,从库过多了会主库的多线程同步数据的压力。

zabbix数据库性能优化_zabbix数据库性能优化_19

3. 选择合适的存储系统  

zabbix数据库性能优化_Redis_20

1.CQRS

        简单来说,CQRS(Command Query Responsibility Segration)就是一个系统,从架构上把 CRUD 系统拆分为两部分:命令(Command)处理和查询(Query)处理。其中命令处理包括增、删、改。因此我们在某些业务场景进行存储架构设计时,可以通过关系型数据库的 ACID 特性进行数据的更新与写入,用 NoSQL 的高性能与扩展性进行数据的查询处理,这样的好处是关系型数据库和 NoSQL 的优点都可以兼得,同时对于某些业务不适于一刀切的替换存储的也可以有一个平滑的过渡。

CQRS实现方式

方式

实时性

方案类型

优点

缺点

CDC(变更数据捕获)

无业务侵入,解决多业务入口

额外中间件

领域事件

可读性高

需要在框架代码层面处理

调度任务定时同步

无业务侵入,解决多业务入口

物理删除无法识别,只能全量

zabbix数据库性能优化_Redis_21

        推指的是由数据变更端通过直接或者间接的方式把数据变更的记录发送到接收端,从而进行数据的一致性处理,这种主动的方式优点是实时性高。

        拉指的是接收端定时的轮询数据库检查是否有数据需要进行同步,这种被动的方式从实现角度来看比推简单,因为推是需要数据变更端支持变更日志的推送的。

        推的方式分两种:CDC(变更数据捕获)和领域事件。对于一些旧的项目来说,某些业务的数据入口非常多,无法完整清晰的梳理清楚,这个时候CDC就是一种非常好的方式,只要从最底层数据库层面把变更记录取到就可。

        对于已经服务化的项目来说领域事件是一种比较舒服的方式,因为CDC是需要数据库额外开启功能或者部署额外的中间件,而领域事件则不需要,从代码可读性来看会更高,也比较开发人员的维护思维模式。

2.替换存储

        从本质来看该模式与 CQRS 的核心本质是一样的,主要是要对 NoSQL 的优缺点有一个全面认识,这样才能在对应业务场景选择与判断出一个合适的存储系统。

        当然,替换存储的时候,我这里也有个建议:加入一个中间版本,该版本做好数据同步与业务开关,数据同步要保证全量与增加的处理,随时可以重来,业务开关主要是为了后续版本的更新做的一个临时型的功能,主要避免后续版本更新不顺利或者因为版本更新时导致的数据不一致的情况出现。在跑了一段时间后,验证了两个不同的存储系统数据是一致的后,接下来就可以把数据访问层的底层调用替换了。如此一来就可以平滑更新切换。

四、数据库优化选型  

    从解决问题的角度出发,我们得先了解到问题的原因;其次我们得有一套思考、判断问题的流程方式,让我们合理的站在哪个层面选择方案;最后从众多的方案里面选择一个适合的方案进行解决问题,找到一个合适的方案的前提是我们自己对各种方案之间的优缺点、场景有足够的了解,没有一个方案是完全可以通吃通用的,软件工程没有银弹。如果不清楚选择哪种方案,以下我也列出了方案优先级:  

1.SQL/索引

2.中间表

3.数据归档

4.分布式缓存

5.CQRS

最后,大家如果觉得有什么不对的地方,可以向我提出来哈,一起进步,加油~