一、小米
1、背景
小米关系型存储数据库首选 MySQL,单机 2.6T 磁盘。由于小米手机销量的快速上升和 MIUI 负一屏用户量的快速增加,导致负一屏快递业务数据的数据量增长非常快, 每天的读写量级均分别达到上亿级别,数据快速增长导致单机出现瓶颈,比如性能明显下降、可用存储空间不断降低、大表 DDL 无法执行等,不得不面临数据库扩展的问题。
对于 MySQL 来讲,最直接的方案就是采用分库分表的水平扩展方式,综合来看并不是最优的方案,比如对于业务来讲,对业务代码的侵入性较大;对于 DBA 来讲提升管理成本,后续需要不断的拆分扩容,即使有中间件也有一定的局限性
2、迁移过程
整个迁移分为 2 大块:
数据迁移
对于存量数据,可以使用逻辑备份、导入的方式,除了传统的逻辑导入外,官方还提供一款物理导入的工具 TiDB Lightning。
对于增量备份可以使用 TiDB 提供的 Syncer (新版已经更名为 DM – Data Migration)来保证数据同步。
流量迁移
流量切换到 TiDB 分为两部分:读、写流量迁移。每次切换保证灰度过程,观察周期为 1~2 周,做好回滚措施。
读流量切换到 TiDB,这个过程中回滚比较简单,灰度无问题,则全量切换。
再将写入切换到 TiDB,需要考虑好数据回滚方案或者采用双写的方式(需要断掉 Syncer)。
二、美团点评
对于初期上线的业务,我们比较谨慎,基本的原则是:离线业务 -> 非核心业务 -> 核心业务
1、写入量大、读 QPS 高的离线业务
1.1、现在 TiDB 的 GC 对于每个 kv-instance 是单线程的,当业务删除数据的量非常大时,会导致 GC 速度较慢,很可能 GC 的速度跟不上写入。目前可以通过增多 TiKV 个数来解决,长期需要靠 GC 改为多线程执行
1.2、Insert 响应时间越来越慢。业务上线初期,insert 的响应时间 80 线(Duration 80 By Instance)在 20ms 左右,随着运行时间增加,发现响应时间逐步增加到 200ms+。期间排查了多种可能原因,定位在由于 Region 数量快速上涨,Raftstore 里面要做的事情变多了,而它又是单线程工作,每个 Region 定期都要 heartbeat,带来了性能消耗
临时解决:增加 Heartbeat 的周期,从 1s 改为 2s,效果比较明显
彻底解决:需要减少 Region 个数,Merge 掉空 Region,官方在 2.1 版本中已经实现了 Region Merge 功能,我们在升级到 2.1 后,得到了彻底解决
另外,等待 Raftstore 改为多线程,能进一步优化
2、在线 OLTP,对响应时间敏感的业务
执行计划偶尔不准
三、摩拜单车
1、场景一:开关锁日志成功率统计
按照我们的估计,这个业务一年的量在数百亿
- 使用单机的 MySQL 库需要频繁的进行归档
- 特别是遇到单机数据库瓶颈的情况下,扩容更是带来了非常大的挑战
- 其次,根据我们之前使用分库分表的经验,对于这类需要频繁更新表结构进行 DDL 操作的业务,一旦数据量过大,很很容易出现数据库假死的情况,不仅影响服务的可用性,更严重的是很可能导致数据不一致的情况出现
最终通过对比分析,我们选择了 TiDB 作为开关锁日志成功率统计项目的支撑数据库
2、场景二:实时在线 OLTP 业务
由于是典型 OLTP 场景,可选项并不多,而且数据量增长极快,这些数据库的数据在一年内轻松达到数百亿量级。这些场景在我们有了 TiDB 的使用经验以后,发现 TiDB 的所有特性都非常契合这种海量高并发的 OLTP 场景。TiDB 的容量/并发可随意扩展的特性不在赘述,支持在线 DDL 这个特性特别适合这些业务,有需要业务更改不会阻塞业务,这是我们业务快速迭代比较需要的特性。
目前,这两个在线 OLTP 集群拥有数十个节点,百亿级数据,上线以后非常稳定,PingCAP 客户支持团队也协助我们进行该集群的日常运维工作。
3、订单集群(P0 级业务)
TiDB 合库作为 readonly 负责其他多维度的查询
TiDB 的出现,不仅弥补了 MySQL 单机容量上限、传统 Sharding 方案查询维度单一等缺点,而且其计算存储分离的架构设计让集群水平扩展变得更容
四、头条
1、活动场景
突然接了一个元旦的活动,这个时候上传的图片就比较多,数据增长的就太大了,这种活动中 S3 系统压力比较大。我们 MySQL 的单盘基本上稳定的在 2.0TB 以上(盘总计 2.8TB),对此我们就只能删数据(一些很老的数据),跟业务部门沟通说,这个数据不要了,从 MySQL 的单盘里删掉,通过这种方式来支撑。
但即使这么做,单盘还是扛不住现在数据增长的需求。然后当时就想干脆激进点,把一些写进来后立即就读、并且以后都不会读的一些流量切到 TiDB 里。因为 S3 存储分很多 bucket ,做活动的人就去新建一些 bucket, 这些 bucket 的元数据就直接存在 TiDB 里面,就不存 MySQL 了。
2、遇到的问题
Row id 的打散。这个问题正好是我们这边碰到的一个性能上的问题。因为 TiDB 存储数据是这么存的:我要插入一行数据,他会有两行,第一行是索引,索引是 Key ,然后 value 是 row id;第二行是 row id 是 Key,value 是整行的数据,相当于第二行有点像聚集索引这种东西。但是这个聚集索引的 Key 是 row id。原来的版本实现上是说这个 row id 是个递增了,所以这种就导致不管你插入什么数据,这个 row id 都是递增的,因为 row id 一递增,这些数据都会打到一个 TiKV 的一个 region 上面。因为我的 TiKV 是一个有序的 Map,所以说 row id 如果递增的话,肯定大家插入的时候都是打到一个 TiKV 上面。我们当时业务的压力比较大,导致客户发现他把这个业务的机器实例数给扩容上去之后,会发现这个 insert 的 TPS 大概也就在两万,一行大概就一百多个字节吧,你再怎么加他上不去了,也就是说 insert 的这个 QPS 上不去了。
这一点 TiDB 新版本的方案就是,row id 不是单调递增,而是把 row id 打的很散,这种方案性能会比较好,没有热点。
内容出处: