前瞻:
为保证服务通畅不会时常发生崩溃,原来的单机升级为主从结构,保证高可用(其实高可用往往和高并发支撑紧密联系)。而用户量级进一步提升,会使得主库写入性能急剧消耗,这时也可以考虑通过加主库机器和从库机器缓解,但分库分表是比较好的方案,因为主库多的话,数据一致性是一个重要难题。因此升级为分库分表,这样就没有数据一致性问题,每个数据库实例只维护自己存储的数据即可。
垂直拆分:
、
垂直拆分的特点:
拆分后,各个库表都有原来完整的数据,只不过原来的数据由一份被垂直切割成两份或以上的数据,并且这些数据都是相互对应的,能和原来的数据对应。
水平拆分:
水平分库分表的规则:
水平拆分特点:
每张表或者每个库都只保存部分数据,并且数据的性质都是相同的。提供数据时,会根据一定的策略去找到对应的机器或者数据库实例,相当于水平线切割了数据表/库。
当用户量急剧增加的时候,同一个表肯定不允许容纳大量数据,因此先采取分表,但仍然是同一个数据库实例,因此当流量进一步增大,演变成分库,分成多台数据库实例在多台机器上。
业务场景:
实际应用中,水平拆分的应用多些,下面是水平拆分的应用场景,遵循水平拆分原则:
但有种场景:
1.这种情况下,如果只采用用户id hash,你不知道手机号存哪里,解决不了手机号查询,你得所有分库都扫描一遍才拿得到用户id。
2.如果采用手机号hash分片(分库),那用户id查询 你得全分库扫描。
因此解决方案是比较折中的方案:
通过id/手机号查询,再根据关系表进行进一步哈希定位。
这样的例子,就是典型的借助了空间换取时间,使得查询效率提升。反正现时代,存储空间是廉价的。
C端用户查看自己的投递状态,根据用户id哈希很快就能查到,但是B端的话由于是接收了很多个求职者,在数据量大的情况,让每个用户id都哈希一遍再拿也不是好的方案。所以以企业做分片,根据企业来得到用户信息。都是典型的空间换时间的做法。
分片策略:根据业务中的关键字段来进行合适的分片策略,如果遇到像上述中矛盾的场景,就要以空间换时间,做些冗余存储,然后采用不同字段分片策略,它们再进行一定的映射即可。
分库分表还存在的问题:
主键冲突:原来单机一般采用的主键递增,但在分布式的情况下,不能再采用,避免冲突。方法:
分表分库后,怎么连接操作数据库实例也是个问题。
方法:
1.代理方式:运维层面做了以后,写代码的时候,直接就当作操作一台数据库。
2.应用层方式:需要指定目标实例,要配置多套连接。
跨库跨表join解决方案:
全局表(字典表),每个库都备一份,join的时候就在一个数据库 ( mysql 连接表,FEDERATED引擎 ,该引擎可以在原有的引擎上叠加 ) 内解决。