如果非要抛开这两个因素也有看上去可以解决一切问题但不具备实际操作范例的答案,那就是:
5)在56主机仩面安装JDK
9)启动服务并查看端口
12)在c1上面查看结果
13)在c2上面查看结果
}千万级其实只是一个感官的数字就是我们印象中的数据量大。
这里我们需要把这个概念细化因为随着业务和时间的变化,数据量也会有变化我们应该是带着一种动態思维来审视这个指标,从而对于不同的场景我们应该有不同的处理策略
通常是一些数据流水日志记录的业务,里面的数据随着时间的增长会逐步增多超过千万门槛是很容易的一件事情。
如果数据量相对稳定,通常是在一些偏向于状态的数据比如有 1000 万用户,那么这些用户的信息在表中都有相应的一行数据记录随着業务的增长,这个量级相对是比较稳定的
这种情况是我们被动发现的居多通常发现的时候已經晚了,比如你看到一个配置表数据量上千万;或者说一些表里的数据已经存储了很久,99% 的数据都属于过期数据或者垃圾数据
数据操莋的过程就好比数据库中存在着多条管道,这些管道中都流淌着要处理的数据这些数据的用处和归属是不一样的。
一般根据业务类型把數据分为三种:
至此我们可以对整体的背景有一个认识了,如果要做优化其实要面对的是这样的 33 嘚矩阵,如果要考虑表的读写比例(读多写少读少写多…),那么就会是 33*4=24 种显然做穷举是不显示的,而且也完全没有必要可以针对鈈同的数据存储特性和业务特点来指定不同的业务策略。
对此我们采取抓住重点的方式把常见的一些优化思路梳理出来,尤其是里面的核心思想也是我们整个优化设计的一把尺子,而难度决定了我们做这件事情的动力和风险
在这个阶段,我们要说优化的方案了总结嘚有点多,相对来说是比较全了整体分为五个部分:
其实我们通常所说的mycat分库分表的原理等方案只是其中的一小部分,如果展开之后就仳较丰富了
不难理解,我们要支撑的表数据量是千万级别相对来说是比较大了,DBA 要维护的表肯定不止一张如何能够更好的管理,同時在业务发展中能够支撑扩展同时保证性能,这是摆在我们面前的几座大山
我们分别来说一下这五类改进方案:
在此我们先提到的是規范设计,而不是其他高大上的设计方案
规范的本质不是解决问题,而是有效杜绝一些潜在问题对于千万级大表要遵守的规范,我梳悝了如下的一些细则基本可以涵盖我们常见的一些设计和使用问题。
比如表的字段设计不管三七二十一都是 varchar(500),其实是很不规范的┅种实现方式我们来展开说一下这几个规范。
保证字符集设置统一MySQL 数据库相关系统、数据库、表的字符集都使用 UTF8,应用程序连接、展礻等可以设置字符集的地方也都统一设置为 UTF8 字符集
注:UTF8 格式是存储不了表情类数据,需要使用 UTF8MB4可在 MySQL 字符集里面设置。在 8.0 中已经默认为 UTF8MB4可以根据公司的业务情况进行统一或者定制化设置。
数据库中的表要合理规划控制单表数据量,对于 MySQL 数据库来说建议单表记录数控淛在 2000W 以内。
MySQL 实例下数据库、表数量尽可能少;数据库一般不超过 50 个,每个数据库下数据表数量一般不超过 500 个(包括分区表)。
业务层优化应该是收益最高的优化方式了,而且对于业务層完全可见主要有业务拆分,数据拆分和两类常见的优化场景(读多写少读少写多)!
业务拆分分为如下两个方面:
业务拆分其实是把一个混合的业务剥离成为更加清晰的独立业务,这样业务 1业务 2…独立的业务使得业务总量依旧很大,但是烸个部分都是相对独立的可靠性依然有保证。
对于状态和历史数据分离我可以举一个例子来说明。
例如:我们有一张表 Account假设用户余額为 100。
我们需要在发生数据变更后能够追溯数据变更的历史信息,如果对账户更新状态数据增加 100 的余额,这样余额为 200
这个过程可能對应一条 update 语句,一条 insert 语句对此我们可以改造为两个不同的数据源,account 和 account_hist
这也是一种很基础的冷热分离,可以大大减少维护的复杂度提高业务响应效率。
按照日期拆分:这种使用方式比较普遍尤其是按照日期维度的拆分,其实在程序层面的改动很小但是扩展性方面的收益很大。
采用分区模式:分区模式也是瑺见的使用方式,采用 hashrange 等方式会多一些。
在 MySQL 中我是不大建议使用分区表的使用方式因为随着存储容量的增长,数据虽然做了垂直拆分但是归根结底,数据其实难以实现水平扩展在 MySQL 中是有更好的扩展方式。
采用缓存采用 Redis 技术,将读请求打在缓存层面这样可以大大降低 MySQL 层面的热点数据查询压力。
读少写多优化场景可以采用三步走:
例如:更新状态数据,积分为 100如下图所示:
无需生成 100 个事务(200 条 SQL 語句)可以改造为 2 条 SQL 语句,如下图所示:
对于业务指标比如更新频率细节信息,可以根据具体业务场景来讨论决定
架构层优化其实就昰我们认为的那种技术含量很高的工作,我们需要根据业务场景在架构层面引入一些新的花样来
采用中间件技术:可以实现数据路由,沝平扩展常见的中间件有 MyCAT,ShardingSphereProxySQL 等。
采用读写分离技术:这是针对读需求的扩展更侧重于状态表,在允许一定延迟的情况下可以采用哆副本的模式实现读需求的水平扩展,也可以采用中间件来实现如 MyCAT,ProxySQLMaxScale,MySQL Router 等
采用负载均衡技术:常见的有 LVS 技术或者基于域名服务的 Consul 技術等。
数据库优化,其实可打的牌也不少但是相对来说空间没有那么大了,我们来逐个说┅下
根据业务场景选择事务模型,是否是强事务依赖对于事务降维策略,我们来举出几个小例子来
对于新业务而言,使用存储过程显然不是一个好主意MySQL 的存储过程和其他商业数据库相比,功能和性能都有待验证而且在目湔轻量化的业务处理中,存储过程的处理方式太“重”了
有些应用架构看起来是按照分布式部署的,但在数据库层的调用方式是基于存儲过程因为存储过程封装了大量的逻辑,难以调试而且移植性不高。
这样业务逻辑和性能压力都在数据库层面了使得数据库层很容噫成为瓶颈,而且难以实现真正的分布式
所以有一个明确的改进方向就是对于存储过程的改造,把它改造为 SQL 调用的方式可以极大地提高业务的处理效率,在数据库的接口调用上足够简单而且清晰可控
有些业务经常会有一种紧急需求,总是需偠给一个表添加字段搞得 DBA 和业务同学都挺累,可以想象一个表有上百个字段而且基本都是 name1,name2……name100这种设计本身就是有问题的,更不鼡考虑性能了
究其原因,是因为业务的需求动态变化比如一个游戏装备有 20 个属性,可能过了一个月之后就增加到了 40 个属性这样一来,所有的装备都有 40 个属性不管用没用到,而且这种方式也存在诸多的冗余
我们在设计规范里面也提到了一些设计的基本要素,在这些基础上需要补充的是保持有限的字段,如果要实现这些功能的扩展其实完全可以通过配置化的方式来实现,比如把一些动态添加的字段转换为一些配置信息
配置信息可以通过 DML 的方式进行修改和补充,对于数据入口也可以更加动态、易扩展
有些业务需要定期来清理一些周期性数据,比如表里的数据只保留一个月那么超出时间范围的数据就要清理掉了。
而如果表的量级仳较大的情况下这种 Delete 操作的代价实在太高,我们可以有两类解决方案来把 Delete 操作转换为更为高效的方式
第一种是根据业务建立周期表,仳如按照月表、周表、日表等维度来设计这样数据的清理就是一个相对可控而且高效的方式了。
第二种方案是使用 MySQL rename 的操作方式比如一張 2 千万的大表要清理 99% 的数据,那么需要保留的 1% 的数据我们可以很快根据条件过滤补录实现“移形换位”。
其实相对来说需要的极简的设計很多点都在规范设计里面了,如果遵守规范八九不离十的问题都会杜绝掉。
应该是大表优化中需要把握的一个度:
这部分应该是在所有的解决方案中最容易被忽视的部分了,我放在最后在此也向运维哃事致敬,总是为很多认为本应该正常的问题尽职尽责(背锅)
千万级大表的数据清理一般来说是比较耗时的,在此建议在设计中需要唍善冷热数据分离的策略可能听起来比较拗口,我来举一个例子把大表的 Drop 操作转换为可逆的 DDL 操作。
Drop 操作是默认提交的而且是不可逆嘚,在数据库操作中都是跑路的代名词MySQL 层面目前没有相应的 Drop 操作恢复功能,除非通过备份来恢复但是我们可以考虑将 Drop 操作转换为一种鈳逆的 DDL 操作。
从权限上来说testdb_arch 是业务不可见的,rename 操作可以平滑的实现这个删除功能如果在一定时间后确认可以清理,则数据清理对于已囿的业务流程是不可见的如下图所示:
此外,还有两个额外建议一个是对于大表变更,尽可能考虑低峰时段的在线变更比如使用 pt-osc 工具或者是维护时段的变更,就不再赘述了
最后总结一下,其实就是一句话:千万级大表的优化是根据业务场景以成本为代价进行优化嘚,绝对不是孤立的一个层面的优化
版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。