数据库分库分表就这么简单+源码案例
Posted 爪哇笔记
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据库分库分表就这么简单+源码案例相关的知识,希望对你有一定的参考价值。
背景
随着业务发展,数据量越来越大,mysql中单表数据量达到1000w时性能就变得非常差。分库分表技术应运而生。
这些技术看似很高深,其实不难,其核心就是对数据库数据进行划分,将数据放到不同的表、不同数据库中。具体如何划分则需要根据实际业务操作。
分库分表
分库分表是为了解决数据量过大而导致数据库性能下降的问题,一般而言当单表的数据量达到1000w行或100G以后,由于查询维度较多,即使添加从库和索引,很多操作性能性能仍然下降严重。
垂直分表
将一个表按照字段分成多表,每个表存储其中一部分字段。
把不常用的字段单独放在一张表中
把text、blot 等大字段拆分出来放在附表中
经常组合查询的列放在一张表中
大字段IO效率低,因为大字段占据比较多的存储空间,可能存在跨页存储的情况。内存与磁盘的数据交换是以页为单位,根据局部性原理,一般是一次读取一页的数据,当存在跨页情况时,需要进行两次IO,降低了读取效率。
商品表中,用户在浏览商品时一般都是先浏览商品列表,当用户对某个商品感兴趣时才会去查看商品的描述、详情。这里商品描述属于冷数据,商品名称价格图片店铺等信息是热数据,并且商品描述是大字段。
通过垂直分表可以较少IO资源竞争,降低锁表的几率查看详情的用户与商品信息浏览互不影响;
充分发挥热门数据的操作效率,商品信息查询的高效率不会被商品描述的低效率拖累。
分表的局限性:虽然解决了单表数据量过大的问题,性能得到一定的提升,但是数据始终在同一个机器上,竞争的还是同一台机器上的CPU、IO、网络资源。
垂直分库
垂直分库:解决单个机器性能不足的问题,可以进行数据库垂直分库,将一个数据库拆分成多个部署在不同机器上。
垂直分库是指按照业务将表进行分类,分布在不同的数据库上面。每个数据库可以放在不同的服务器,核心理念是专库专用。不影响表结构。
垂直分库通过将表按业务分类,然后分布在不同数据库,并且可以将这些数据库部署在不同服务器上,从而达到多个服务器共同分摊压力的效果,但是依然没有解决单表数据量过大的问题。
水平分库
水平分库:垂直分库可以解决单个机器性能不足的问题,但还是不能解决单表数据量过大导致性能降低的问题。水平分库则是把同一个表的数据按照一定的规则拆分到不同的数据库中,每个库可以放在不同的服务器上。水平分库优点:
解决单库大数据高并发的性能瓶颈
提高了系统的稳定性及可用性
当一个应用难以再细粒度的垂直分库或分库后数据量行数巨大,存在单库读写、存储性能瓶颈的时候,需要进行水平分库,经过水平切分往往能解决单库存储量性能瓶颈。但是由于同一个表的数据被分配到不同的数据库存储到不同的机器中,需要额外进行数据的路由工作,将大大提高了应用系统的复杂度。
水平分表
水平分表:水平分表的思想与水平分库一样,只是水平分表的是在同一个数据库上进行切分,按照一定规则将一个表根据行进行切分。水平分表的优点:
优化单一表数据量过大而产生的性能问题
避免IO资源竞争减少锁表的几率
分库分表总结
垂直分表:可以把一个宽表的字段按访问频次、是否是大字段的原则拆分为多个表,这样既能使业务清晰,还能提升部分性能。拆分后,尽量从业务角度避免联查,否则性能方面将得不偿失。
垂直分库:可以把多个表按业务耦合松紧归类,分别存放在不同的库,这些库可以分布在不同服务器,从而使访问压力被多服务器负载,大大提升性能,同时能提高整体架构的业务清晰度,不同的业务库可根据自身情况定制优化方案。但是它需要解决跨库带来的所有复杂问题。
水平分库:可以把一个表的数据(按数据行)分到多个不同的库,每个库只有这个表的部分数据,这些库可以分布在不同服务器,从而使访问压力被多服务器负载,大大提升性能。它不仅需要解决跨库带来的所有复杂问题,还要解决数据路由的问题(数据路由问题后边介绍)。
水平分表:可以把一个表的数据(按数据行)分到多个同一个数据库的多张表中,每个表只有这个表的部分数据,这样做能小幅提升性能,它仅仅作为水平分库的一个补充优化。
垂直切分
优点:解决业务系统层面的耦合,业务清晰;与微服务治理类似,可以对不同业务的数据进行分级管理、维护、监控、扩展等;高并发场景下垂直切分一定程度提升IO、数据库连接、单机硬件资源、网络资源等。
缺点:分库后无法进行join,只能通过接口聚合的方式解决,提升了开发的复杂度;分库后分布式事务变得更加复杂,需要同时操作多个数据库保持事务原子性。依然存在单表数据量过大的问题(需要进行水平切分)
水平切分
优点:不存在单表数据量过大、高并发的性能瓶颈,提升系统稳定性和负载能力应用端改造较小,不需要进行业务模块拆分
缺点:夸分片的事务一致性难以保证;夸库的join关联查询性能差;数据多次扩展难度和维护难度大
一般来说,在系统设计阶段就应该根据业务耦合松紧来确定垂直分库,垂直分表方案,在数据量及访问压力不是特别大的情况,首先考虑缓存、读写分离、索引技术等方案。若数据量极大,且持续增长,再考虑水平分库水平分表方案。
数据分片规则
对一张大表进行水平切分的时候,要根据什么规则进行切分,涉及到数据分片的规则。
比较常见的:Hash取模分表,数值Range分表,一致性Hash算法分表。
优点:数据分片相对均匀,不容易出现热点和并发访问的瓶颈。
缺点:后期分片集群扩容时,需要进行旧数据的迁移,难度大;容易面临跨分片查询的复杂问题,比如有一个查询不带good_id 时,我们无法定位数据在那个分片中,需要同时向四个分片发起查询请求,在内存中对数据进行整合。
优点:单表大小可控;便于水平扩展;使用分片字段进行范围查询时,可以快速定位数据所在分片,有效避免跨分片问题。
缺点:热点数据成为性能瓶颈。例如:按照时间字段进行分片,历史数据可能成为冷数据很少被访问到;最近时间段的数据可能会被频繁的读写。
分库分表带来的问题
可以通过分布式事务中间件解决,具体要看业务需求,使用强一致性分布事务还是最终一致性事务。
全局表:就是系统中所有模块都依赖的一些表,改动比较小,为了避免跨库join查询,可以在每个数据库中保存一份
字段冗余:用一定空间换时间
数据组装:在系统层面分两次查询,先从第一次的结果集里面找出关联的数据id,再根据关联id查询关联数据,最后将获得的数据进行字段拼装。
跨节点多库查询时,会出现limit分页、order by 排序等问题,当排序字段是分片时可以根据分片规则快速定位到指定的分片。当排序字段为分片字段时,就变得复杂很多。需要先查询不同分片数据进行排序返回,然后将不同分片的数据汇总再次排序,最终返回数据。
主键自增不合理,而且多库的情况下可能出现主键冲突问题。UUID能保证唯一性,但UUID是无序的,无法做到根据主键排序,可以考虑用雪花算法。
采用双写的方式,修改代码,所有涉及到分库分表的表的增、删、改的代码,都要对新库进行增删改。同时,再有一个数据抽取服务,不断地从老库抽数据,往新库写,
边写边按时间比较数据是不是最新的。
粉丝福利
本案例是 从0到1构建分布式秒杀系统 的补充,仅供参考!
分表案例
分库分表案例
读写分离案例
分库分表读写分离案例
技术选型:SpringBoot 2.2.6.RELEASE + shardingsphere 4.0.1 + MySQL + Druid + JPA
源码:gitee.com/52itstyle/spring-boot-sharding-sphere
以上是关于数据库分库分表就这么简单+源码案例的主要内容,如果未能解决你的问题,请参考以下文章
老大又批评我不要为了“分库分表”而“分库分表”
给小白演示 分库分表案例
MYSQL分库分表和不停机更改表结构
MyBatis实现Mysql数据库分库分表操作和总结
如何设计可以动态扩容缩容的分库分表方案
数据库分库分表最佳实践附源码