为什么要冷热分离

由于2020疫情的原因,在线教育行业提前被大家所重视,钉钉教育已经服务超过21万所学校、700万教师和1.4亿学生用户,每天大量的教育数据产生。

在中国互联网技术圈流传着这么一个说法:MySQL 单表数据量大于 2000 万行,性能会明显下降。事实上,这个传闻据说最早起源于百度。具体情况大概是这样的,当年的 DBA 测试 MySQL性能时发现,当单表的量在 2000 万行量级的时候,SQL 操作的性能急剧下降,因此,结论由此而来。然后又据说百度的工程师流动到业界的其它公司,随之也带去了这个信息,所以,就在业界流传开这么一个说法。再后来,阿里巴巴《Java 开发手册》提出单表行数超过 500 万行或者单表容量超过2GB,才推荐进行分库分表。对此,有阿里的黄金铁律支撑,所以,很多人设计大数据存储时,多会以此为标准,进行分表操作。

有业界传说和阿里巴巴的开发手册支撑,这个结论应该是靠谱的,毕竟实践出真知,但这背后的原理是什么呢,目前我们用的MYSQL大部分都是InnoDB引擎,现在我们就从InnoDB引擎说起来扒一扒为什么单表数据在2000W+后会明显下降。

总结一下:单表数据量越大,B 树高度越高,查询需要IO次数越多,性能越差。这里的几个分界值就是2W和2000W,也就是说1000W和100W通过主键来索引的性能其实是差不多的,都需要2次IO。

那么在分库分表后单表数据量依然是2000W+,这种场景怎么破局呢?从上面的分析中我们可以推导出一个MYSQL的性能公式,还是以纪录大小为1K为例:

MYSQL单表查询性能指数 = 单表数据量/(页大小/14)*(页大小/1K) ,这个性能指数越大,性能就越低。那么在降低这个性能指数就只有两种方法:

我们的业务场景是CRUD比较高频且数据量比较小,同时数据的时效性要求又比较高,比如发布的作业,一般时效就是最近2天,很少有人说我要去看下我半年前的作业,然后再做一下。综合考虑下来,降低分子即降低单表数据量是能够有效提升查询性能和稳定性的可靠途径。于是冷热分离应运而生。

冷热分离的好处:

什么是OTS

OTS表格存储(Tablestore)是阿里云自研的多模型结构化数据存储,提供海量结构化数据存储以及快速的查询和分析服务。表格存储的分布式存储和强大的索引引擎能够支持PB级存储、千万TPS以及毫秒级延迟的服务能力。

OTS的几个核心特性:

冷热分离技术方案

技术架构

自动筛选数据分析(冷热分离之OTS表格存储实战)(1)

冷热迁移方案

做业务最重要的就是稳定,为了保证在进行冷热数据分离过程中的系统稳定,在数据迁移的过程中一定要做到:可灰度[降低影响,提前发现],可一键回滚[快速止血]。

1.冷数据迁移

2.对数据查询服务进行灰度验证。

3.通过DTS任务扫描出已经迁移的业务数据并进行逻辑删除。[此时数据在OTS和MYSQL中都存在]

4.对已经逻辑删除的用户进行灰度验证。

5.开启DTS任务中的物理删除开关。

6.扩大灰度放量,观察,直至全量。

从MYSQL迁移到OTS的实战总结

表的映射

MYSQL是结构化数据存储,如果业务需要平滑迁移的话,可以将MYSQL中的表映射到OTS中的宽表,宽表具体结构化数据功能。

与MYSQL相比的不同点:

OTS限制:

宽表建表语句示例:

TableMetatableMeta=newTableMeta("user_xxx"); //添加主键列 tableMeta.addPrimaryKeyColumn(newPrimaryKeySchema("user_xxx",PrimaryKeyType.STRING)); tableMeta.addPrimaryKeyColumn(newPrimaryKeySchema("org_xxx",PrimaryKeyType.INTEGER)); tableMeta.addPrimaryKeyColumn(newPrimaryKeySchema("task_xxx",PrimaryKeyType.INTEGER)); //添加属性列 tableMeta.addDefinedColumn(newDefinedColumnSchema("xxx",DefinedColumnType.INTEGER)); tableMeta.addDefinedColumn(newDefinedColumnSchema("xxxx",DefinedColumnType.INTEGER)); tableMeta.addDefinedColumn(newDefinedColumnSchema("xxxxx",DefinedColumnType.STRING)); tableMeta.addDefinedColumn(newDefinedColumnSchema("xxxxxx",DefinedColumnType.STRING)); .... inttimeToLive=-1;//数据的过期时间,单位为秒,-1表示永不过期。带索引表的数据表数据生命周期必须设置为-1。 intmaxVersions=1;//保存的最大版本数,1表示每列上最多保存一个版本即保存最新的版本。带索引表的数据表最大版本数必须设置为1。 TableOptionstableOptions=newTableOptions(timeToLive,maxVersions); ArrayList<IndexMeta>indexMetas=newArrayList<IndexMeta>(); //任务在班级维度的索引 IndexMetaindexMeta=newIndexMeta("idx_task_xxx"); indexMeta.addPrimaryKeyColumn("task_xxx");//为索引表添加主键列。 indexMeta.addPrimaryKeyColumn("org_xxx");//为索引表添加主键列。 indexMeta.addPrimaryKeyColumn("user_xxx");//为索引表添加主键列。 indexMetas.add(indexMeta); CreateTableRequestrequest=newCreateTableRequest(tableMeta,tableOptions,indexMetas);//创建数据表的同时创建索引表。 otsClient.createTable(request);

索引的映射

MYSQL中的索引映射到OTS则有三种索引。一种是全局二级索引,一种是局部索引,一种是多元索引。

全局二级索引和局部索引和MYSQL一样,查询匹配时需要满足左匹配原则才能命中索引。

与MYSQL相比的不同点:

OTS限制:

CRUD映射

MYSQL中的常用查询映射到OTS为4种查询:主键查询、批量查询、范围查询、索引查询。但是相比于MYSQL,OTS的查询在灵活性和易用性方便会差比较多。

与MYSQL相比的不同点:

OTS限制:

给OTS的建议

本文为阿里云原创内容,未经允许不得转载。

,