欢迎关注公众号(通过文章导读关注:【11来了】),及时收到 AI 前沿项目工具及新技术的推送!
在我后台回复 「资料」 可领取
编程高频电子书
!
在我后台回复「面试」可领取硬核面试笔记
!文章导读地址:点击查看文章导读!
感谢你的关注!
MySQL 中的分库分表方案解决方案
如果在互联网公司中,可能有些表的数据规模膨胀速度很快,比如用户、订单数据,可能达到几千万甚至上亿级别的数据,那么数据量规模过大带来的性能负担是很重的,主要问题为:
- 数据量大的问题 :MySQL 索引底层数据结构使用 B+ 树,如果单表数据量过大,会导致 B+ 树层级过深,磁盘 IO 次数增加,降低索引性能
- 写性能瓶颈的问题 :在单机、主从架构中,如果是并发访问量很高的情况,尤其是写请求的 QPS 很高的情况下,很容易达到 MySQL 的性能瓶颈,只靠简单的主从架构,可以提升高可用和读性能,但是无法提升 MySQL 的写性能
因此需要对数据进行分片处理,来更好的解决这两方面的问题
如何分库分表?
对数据库进行分库分表时,是需要数据库的中间件支持的,比较常用的是:MyCat、Sharding-JDBC
- MyCat 是 Proxy 层的解决方案,对应用来说比较透明,与应用之间耦合度较低,但是需要自己部署运维一套中间件,成本较高
- Sharding-JDBC 是 client 层的解决方案,在应用端引入,运维成本较低,并且不需要 Proxy 层转发,性能较高,但是与应用端耦合度比较高,如果需要版本升级的话,代价比较大
所以,一般小型公司选用 Sharding-JDBC,中大型公司选用 MyCat
什么情况下需要分库分表呢?
比如说在互联网公司中,这里以电商场景举例,毕竟电商的用户量相对来说是比较大的
对于电商中的用户表来说,一般中小型的互联网公司,用户量可能就已经达到了几千万的级别,从而导致用户表的索引层次太深,查询能下降
一般建议 MySQL 中单表的数据量不要超过 1000 万,基本上单表数据量在 100 万以内,性能上不会出现太大的问题
因此对于用户量达到了几千万级别的用户表,需要进行分库分表!
将千万级别的用户数据分散到 100 个表中,user_001、user_002、…、user_100 一百个表,再将这 100 张表分散到多台服务器中去
至于具体分配多少台服务器主要看两个方面:
- 看该表的压力有多大,用户表的话,压力一般不会太大,因为基本上不会出现同时间大量用户登陆注册的情况
- 看该表的数据量有多大,有一个参考标准就是 1 亿条数据的总大小在 1GB - 几 GB 之间,该用户表中几千万的数据最多也就几个 GB,因此该量级的数据对服务器的压力并不大
所以说将这 100 个表分配到 2 台服务器即可,每台服务器上安装一个数据库,将 100 张表均匀分配在 2 台服务器上,一般指定表中的某一个字段来分,比如用户表中的 user_id 字段,对 user_id 进行哈希后,路由到对应的表中去
分库分表后的适配问题
当进行分库分表之后,相应的应用端会出现一些业务上的问题,需要进行分库分表的适配处理,就比如:
- 当根据用户表的 user_id 进行分库分表,那么当用户登录的时候,直接根据 user_account 进行登录,此时是没有 user_id 的值的,这时该如何查找对应的库和表呢?
常规解决方案的话是建立一个映射表(user_account -> user_id),通过 user_account 对这个映射表进行分库分表处理,之后就可以根据 user_account 找到映射表中对应的 user_id,再通过 user_id 去用户表中查询数据
虽然这种方式会带来一定的性能损耗,但是为了解决分库分表的问题,只能付出一定的性能代价
添加映射表之后,通过 account 查找用户数据如下图红线:
分库分表后更复杂的查询问题
上边只说了简单的根据 user_account 查询用户数据所带来的问题,而实际场景中还有还需要根据用户名、手机号、性别等查询条件进行复杂查询,对于这类复杂查询来说,也没有太好的办法,只能对用户表数据的 binlog 进行监听,将要搜索的字段同步到 ES 中去,建立好搜索的索引,之后通过 ES 进行复杂查询,定位到对应的 user_id,再根据 user_id 去分库分表架构中查询对应的用户数据
因此,整套分库分表方案就说完了,基本上就包含了上边的几块内容