mysql使用

68 阅读3分钟

这些日子为了解决业务上的挑战,想要解决MySQL的性能提升方案。

目前找了主要有:

  1. 分库分表
  2. 读写分离

读写分离最简单,牺牲一点一致性能减少读的压力,分表也比较简单,但是目前没有特别合适的中间件,结合我们的业务场景,分库是目前最适合下点功夫的。(另外还需要做高可用,可以做双主,但是不需要我过多参与,因此这里不谈。)

背景介绍

  • MongoDB用来存储大部分非事务相关的业务
  • MySQL用来做电商相关业务,所有数据几乎都与账户ID相关
  • 账户ID是MongoDB的ObjectId
  • 对于普通用户来说没有关联到其他用户的操作
  • 管理员需要统计以及查看所有的用户数据

分库算法

一致性hash

需要停机,遍历所有库,将需要移动的数据移动到新的库上。

具体步骤

停机 => 数据迁移(不删除旧数据) => 调整服务器配置 => 上线 => 遍历检查并删除各个库冗余的数据

优点
  • 平滑提升性能,节约服务器
  • 迁移过程中移动数据很少
缺点
  • 线上迁移时间时间会比较久
  • 计算速度没有取模快

取模

  • 也算是一种一致性hash,只不过更简单;
  • 拆库的方案是按2的倍数去拆,比如先拆成2个库,然后需要扩容的时候拆成4个,不然的话可能每次迁移都得全部重新迁移;
具体步骤

停机 => 所有的库复制一份 => 调整服务器配置 => 上线 => 遍历检查并删除各个库冗余的数据

优点
  • 数据会非常均匀;
  • 由于不用操作迁移数据库,直接使用备份恢复的方式,线上扩容速度会快很多;
  • 一次拆库之后能坚持很长时间;
缺点
  • 比较耗服务器,比如每个库最多放100W个用户的数据,那数据涨到150W左右的时候就应该拆分了;
    无论怎么拆,性能都是跳跃性提升的,不能平滑提升;
  • 由于我们使用的是mongodb的ObjectId,数据不均匀的可能性非常高;

好了,无论怎么分,都会涉及到停机升级的问题,但是停机意味着损失收入,那么为了解决停机的问题,我们找到了一个迁移方案:索引表

经过上面的比较,为了让数据库不停机以及迁移尽可能快,我们选择一致性hash方案再加上索引表

  • 每次根据用户ID取库的时候,先查索引表,如果没有,再计算;
  • 开启定时任务,定期扫描,迁移数据,再更新索引表;

迁移需要注意一点就是需要锁住数据,手动进行两阶段事务,不然可能会造成数据不一致,然后这个迁移任务尽量在凌晨无人的时候进行,而且也只是单个用户,因此这样可以将对用户的影响减到最少。

几个问题

  1. 是否需要公共库?
    如果是公共库,很可能是跟事务不相关的,移到MongoDB即可。
  2. MySQL ID自增怎么解决?
    换成ObjectID,或者UUID之类的。
  3. Node.js有没有相关的中间件?
    可以看看TribeDB,但是不满足我们目前的需求。(蠢蠢欲动想要造轮子了
  4. select *,order by之类的需要跨库,或者联合所有库的操作怎么办?
    这些操作在我们这一般是管理后台才要用,所以可以放到其它工具去做,比如elasticsearch,而且这样的查询会影响数据库性能,我们巴不得砍掉这些查询