27

腾讯开心鼠英语存储演进漫谈

 3 years ago
source link: https://mp.weixin.qq.com/s?__biz=MzUxMDk2MTAyMA%3D%3D&%3Bmid=2247486303&%3Bidx=1&%3Bsn=8689d407ab6681deff443ad2280f6fd6
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

今年腾讯开心鼠项目的用户量每天都在肉眼可见的急剧增长,某些周的复合增长率甚至达到了10%,随着用户量的增长和业务复杂性的增加,数据库的高峰性能压力和存储压力不断变大,下面整体介绍下我们进行的一系列存储架构的调整以及未来的规划。

年初项目的整体架构如下,大部分模块都在以(ip+port)的方式使用同个DB实例。

在量较小的情况下,核心DB的CPU和存储负载都没有太大压力,但量变大后整体风险逐步暴露,主要有:

  1. 耦合度高:任何一个业务svr的SQL性能都会影响所有业务的性能,一旦某个svr没控制好,可能整体全挂

  2. 扩展性差:整个存储的磁盘空间,读写性能都会受到单机限制。

AV7rIj3.png!mobile

阶段1:一主多从

结合高峰期数据库审计日志和对业务模块的梳理,发现数据库访问有以下特点:

  1. 读写QPS比例大致在10 : 1;

  2. 写主要集中在用户的物品数据,课程数据,学习数据等;

  3. 读主要分布在账号体系,集训营,管理端,支付物流,学习记录等;

  4. 慢查询主要集中在集训营和管理端的业务上。

针对读写比例的特点,优先优化读请求。

在一主一从的基础上扩充两个RO组,从数据实时性和业务重要性对读操作进行拆分。

数据实时性

针对实时性要求高的用户账号,物品数据读取主库;

针对用户课程数据,学习数据读取从库;

业务重要性

APP主功能,支付等读取主库和从库1;集训营和管理端读取从库2;数据统计、分析读取从库3;

进行读库的拆分后,线上运行稳定,主库CPU负载从40%下载到了20%。

阶段2:横向拆分

在整个读拆分过程发现,从业务划分来看,数据库数据主要分为APP用户数据,集训营数据,支付物流数据,运营活动数据;

其中除了用户账号数据是多个业务模块所需的,其他的基本上是独立的,于是我们考虑将数据库进行拆分,拆分为4个数据库:

  • 公共数据库:用户APP账号数据,微信序账号数据,课程静态数据;

  • 集训营数据库:集训营分配数据,上课数据,老师数据;

  • 支付/物流数据库:支付数据,物流数据,运营活动数据;

  • UGC数据库:用户课程数据,学习数据,活动数据。

每个数据库对应一个modle模块,将各表的增删改查等操作封装,各自以RPC方式去调用其他库的数据库操作。

横向拆分主要涉及代码的改造和数据的迁移,两个核心问题是:

  1. 尽可能降低迁移的改造成本

  2. 如何保障业务不中断平滑迁移

以UGC数据库为例,该库数据主要分为两大类:

  1. 用于数据分析的少量关系化查询的 用户活动数据

  2. 存在大量关系化查询的 用户课程数据

在用户规模不大时,原有的UGC数据都存储在mysql中,但随着用户数增长,mysql的存储空间和写性能都无法满足诉求。

用户课程数据

该部分数据需要支持关系化查询,我们采用了腾讯云的mysql集群解决方案TDSQL,TDSQL主要优势在于:

  1. 整体容量随着分片数的增加而增加,并且是动态扩容的,不影响业务;

  2. 读写分离,拥有更好的读写性能;

  3. 提供Proxy代理,业务像使用单机Mysql一样;

  4. SQL语句完全兼容,业务迁移成本低;

  5. 完备的监控指标和告警支持,同时支持性能分析。

数据表的平滑迁移

  1. 选择合适的sharedkey在TDSQL库中创建新的表;

  2. 使用mysqldump的数据导出服务,导出已有的全量数据,再导入到TDSQL;

  3. 通过腾讯云的DTS(数据传输服务),接入在线教育的统一binlog notify服务,将数据增量变更写入到TDSQL;

  4. 将项目中数据库配置进行读库和写库的改造;

  5. 进行项目中的该表读操作改造,将其改造到TDSQL对应表;

  6. 线上业务监控及观察一段时间,如有问题,及时回滚读库配置;

  7. 读请求迁移平稳后,对项目中的该表写操作改造,将其改造到TDSQL对应表;

  8. 线上业务及监控观察一段时间,如有问题,及时回滚写库配置;

  9. 停止DTS服务和binlog notify服务,迁移完成。

当然我们的UGC业务有一定的延时误差是被允许接受的;如果对延时的接受程度较低,可以采用Mysql,TDSQL的双写方案来进行改造;先迁移写再迁移读来进行迁移改造,这里不再赘述,欢迎随时讨论。

用户活动数据

以用户学习数据为例,主要为用户完成学习活动过程中,在各个环节的表现,该部分数据主要用于数据分析,基本全为写操作,我们最终选择mongdb来存储这部分数据,主要优势在于:

  1. mongdb面向集合存储,模式自由,可以方便地扩展学习数据字段;

  2. mongdb支持大数据量的存储,可以满足这种随时间膨胀的特厉害的存储诉求;

  3. mongdb支持一定程度的关系化查询,满足按用户ID,活动ID来查询数据;

  4. 强大的聚合工具,完美配合MapReduce等数据分析工具;

  5. 支持数据复制和恢复能力,便于分析数据的传输。

数据表的平滑迁移

  1. 在mongdb中建立对应的数据库表

  2. 改造项目代码,将原有数据库表的写请求存储到Kafka队列中

  3. 使用迁移服务,对原有数据表的全量数据进行迁移,写如到mongdb中

  4. 步骤3完成后,启动Kafka对应topic的消费服务,开始将数据平滑写入到mongdb

针对各库的每张表都可以采用类似的方案进行迁移,至此我们可以开始对单库进行优化。

阶段3:单库优化

以公共数据库为例,通过分析业务高峰期的的数据库审计日志,发现:

50%的请求基本集中在用户账号表上,10%的请求集中在课程静态数据上;

下面将讨论如何优化这两部分请求。

用户账号表

该表主要特点有:

  1. 写请求占比大致为11:1;

  2. 写请求主要集中在密码、login时间等少数字段上;

  3. 大部分用户数据:像手机号,ID等基本不变,同时这些字段可接受一定的时延。

于是将用户账号表拆解成两部分:

  1. 对于时延不敏感数据拆成一张mysql表,同时将表数据缓存到redis中;

  2. 写请求较多的拆解成为redis中的缓存。

对比了业界主要的缓存更新方案,考虑对业务无入侵、实时性优、监控完善等特点;

选用便于接入的在线教育统一的DTS更新服务。

muYBz2n.png!mobile

课程相关数据表

该表数据特点:

  1. 基本为静态数据表,不常变更;

  2. 占用空间大致在10M左右,且可预见的数据都不会很大。

可采用内存缓存的来进行读加速,在服务启动时初始化后定时更新。

同时还对各库进行了一系列的慢查询优化,索引优化,尽量保证单库的可用性及性能。

阶段4:整体优化

在针对性对单库进行性能优化后,在实际开发和维护过程中还存在些痛点:

  1. 业务方调用成本高,得理解不同数据库的差异;

  2. 多数据库的安全防护,统计功能、监控等功能都很分散;

  3. UGC数据大表业务高峰写入QPS很高;

  4. UGC数据大表无法在线DDL操作。

问题1/2:DataProxy统一代理

除了针对各个svr合理调整连接数外,引入DB代理也是个较好的解决方案;于是采用Data Proxy的方案,由其代理各个数据库的访问,提供统一接口给业务方调用;同时在proxy可进行各种安全防护措施,比如过载保护,缓存崩塌保护,穿透保护等;另外还能对外提供数据统计、延时监控功能。

问题3:Kafka平滑写入

由于业务特点,高峰期用户数在平时的10倍以上,单纯的扩容数据库机器在大部分时间内都是极其浪费的;同时由于数据特点,少量数据的读延迟是可以接受的;于是引入KAFKA队列,先由PROXY统一写入到队列中,再由消费服务平滑写入TDSQL与MongoDB;这样就能较低成本扛住高峰期流量和突增流量,并且有很好的扩展性。

问题4:在线DDL时停消费服务

对于大表的DDL一直是数据库优化过程中的一个老大难问题;数据库表的变更,不管是索引变更还是字段变更基本都会锁表从而引发业务中断;在引入队列平滑写入情况下,可在线随时停止消费服务后进行的DDL变更,但不会影响正常业务的运转。

最终存储架构

QvuqiqI.png!mobile

挂个招聘

在线教育是近两年互联网的风口,今年的疫情也更加凸显了它的重要性和必要性,腾讯在线教育近一年也得到了长足的发展。后台团队聚焦golang和云原生,各大业务都有大量HC,欢迎大家随时勾搭。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK