海量用户信息场景下如何进行分库分表
--楼兰带你聊最纯粹的Java
现在面试动不动就是问三高架构。应用大了,数据量多了,查询性能自然就下降了。怎么办呢?很多人自然就想到分库分表。 但是一旦把底层数据库给拆分开了,在业务层面就会暴露出很多问题。 那么在一个具体的业务场景下,要如何设计分库分表方案,并对方案进行优化呢?这次就以用户信息这个具体的场景来分享下如何设计分库分表方案。
两个具体的问题
第一个是一个比较常规的问题:海量用户信息,如何通过分库分表优化查询性能?
第二个是一个比较有难度的问题:用户表按照用户ID分片,在登录时如何按照用户名查询用户?
先来看第一个问题,也就是如何设计一个分库分表方案来提升查询性能。典型的方案其实有两种,垂直分表和水平分表。
垂直分表方案
先来看垂直分表。这种方案其实比较简单,就是将一张大表按照业务字段拆分成几张不同的小表。这虽然不能够从根本上解决单表数据量过大的问题,但却会从根本上影响整个项目的运行效率。
简单的从业务场景来看。拆分之后,登录时就只需要查询包含用户名和密码的小表。而获取用户信息时,就只需要查询包含用户信息的小表。业务上做了一些隔离,每次读的数据就少一些。
垂直分表更深层次的影响则体现在如何根据业务场景不同,配合不同的数据库产品,来选择不同的表设计方案。
在OLTP面向业务的场景中,通常会使用MySQL这样的关系型数据库来存储数据。
在MySQL的innodb引擎中,每个表都是以B+树的形式保存的。在B+树中,数据都以Page为单位构建。Page固定大小16KB。此时,如果表结构设计得更简单,那么每个Page能保存的数据行数也就更多,整个B+树当然也能更小。
当然,这也并不是绝对的。在很多OLAP面向分析的场景中,需要处理更复杂,更庞大的数据集。这时,为了减少多表关联查询,往往就会设计一些宽表,将更多的数据整合到一张大表里。那么这种需要宽表支持的业务需求,用MySQL这样的B+树结构来存储,显然就不合适了。这时,可以选择一些类似于ClickHouse这样的列式存储数据库,以数据列为维度保存数据。这样不管表中包含多少字段,对数据的存储不会有太大的影响。
垂直分表并不能从根本上解决单表数据量多大的问题,但是垂直分表往往是所有数据的底层根基。如何根据不同业务场景,灵活设计更适合的表结构,这是任何一个程序员不可忽视的核心能力。
水平分表方案
接下来,如果真的需要解决单表数据量多大的问题,那就需要使用水平分表了。
水平分表方案本质上就是将原本存在一张表中的数据,分散存储到多个结构相同的子表中。这样每个子表的数据量就没有原来那么多了。而水平分表的核心就是如何设计数据的分配方案。典型的方案有两种,取模分片和按范围分片。
这两种分片策略都有很明显的优点和缺点。所以,如何根据业务场景灵活定制分片策略,就成了面试和工作当中最为重要的一件事情。
用户登录场景下的分库分表问题
对于用户数据,我们