分库分表,来了,作为高级篇章,肯定会给大家带来不一样的地方,来听我唠
这篇主要是认识分库分表,和抛出一系列问题
这里给一个面试题,看过我之前文章的小伙伴可能见过,
面试官:这边有个数据库-单表1千万数据,未来1年还会增长多500万,性能比较慢,说下你的优化思路
回答这道题,不能直接分库分表,应当这样回答
这个可以从两方面来考虑,一种是分库分表,一种是优化,分库分表带来的问题是很多的,所以要先考虑优化
优化分为软优化和硬件优化,
硬件优化,可以提高带宽,cpu,硬盘,
然后就是软优化了,这个就很多了。比如说让运维那边进行数据库参数的调优,数据量不是很大的情况下,先考虑读写分离,引入Nosql,多级缓存架构等等,索引,mysql调优这些,
数据量极大,且增长较快的话,再考虑分库分表
好,这道题就完成了,总之就是不能一上来就直接分库分表,
这里带一个小福利,mysql调优,mysql调优-腾讯云开发者社区-腾讯云 (tencent.com)
引入Nosql,多级缓存架构,多级缓存架构一致性问题解决-腾讯云开发者社区-腾讯云 (tencent.com)
没错!我都搞定了
这个其实很多人都用过,一个单体项目,比如商城,用户表,商品表,订单表,都在一个库中,微服务做的话,一个微服务一个库,这个就是垂直分库。
垂直分表,垂直嘛,就是把一个表从上往下切开,分字段,
//拆分前
CREATE TABLE `product` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`title` varchar(524) DEFAULT NULL COMMENT '视频标题',
`cover_img` varchar(524) DEFAULT NULL COMMENT '封面图',
`price` int(11) DEFAULT NULL COMMENT '价格,分',
`total` int(10) DEFAULT '0' COMMENT '总库存',
`left_num` int(10) DEFAULT '0' COMMENT '剩余',
`learn_base` text COMMENT '课前须知,学习基础',
`learn_result` text COMMENT '达到水平',
`summary` varchar(1026) DEFAULT NULL COMMENT '概述',
`detail` text COMMENT '视频商品详情',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
//拆分后
CREATE TABLE `product` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`title` varchar(524) DEFAULT NULL COMMENT '视频标题',
`cover_img` varchar(524) DEFAULT NULL COMMENT '封面图',
`price` int(11) DEFAULT NULL COMMENT '价格,分',
`total` int(10) DEFAULT '0' COMMENT '总库存',
`left_num` int(10) DEFAULT '0' COMMENT '剩余',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
CREATE TABLE `product_detail` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`product_id` int(11) DEFAULT NULL COMMENT '产品主键',
`learn_base` text COMMENT '课前须知,学习基础',
`learn_result` text COMMENT '达到水平',
`summary` varchar(1026) DEFAULT NULL COMMENT '概述',
`detail` text COMMENT '视频商品详情',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
这个就是垂直分表
水平分库,就是冗余一份数据库,db_0,db_1这样,数据分摊进去
水平分表就是,把一个表的数据,分摊到多张表
首先,垂直的好处:
就是业务的区分了,垂直分库,就是每个微服务一个库,
垂直分表,这个也是业务方面的,比如电商中,商品浏览页,和详情页,做数据的隔离。详情页的点击频次不如浏览页嘛
缺点:垂直分库分表并不能解决单表数据量多的情况
水平:
水平分库,水平分表,他们一般一起做,解决单表数据量多的情况,一般单表到达1000w就到达分库分表的要求了
单单水平分表不能解决数据库性能问题,因为都还是一个库
分库分表为何不提倡无脑引入,就是因为他虽然好处不少,劣势也很多,但是总体肯定利大于弊
优点,
首先就是分库的好处了,摆脱了数据库的性能瓶颈,摆脱了io,cpu,连接数,提高了并发能力,水平分库也可以分摊数据,
分表的好处
主要是水平分表,避免大表性能问题,将数据划分到不同表
劣质:
这里就值得讨论讨论了,
因为要做分库分表,就是要把劣势都搞定,优势是效益!
问题一:
多表join联合查询、多维度查询
这个问题是分库分表下,导致的查询问题,多表联合查询,分表前,直接join就好了,分表后,join就会变的很麻烦
多维度查询,这个就比较有意思了
比如用户的订单表,分表的分片键partionkey是user_id
用户查询订单,可以通过用户的user_id,去找到自己的订单列表,因为就是按照user_id去做的分表,
商家呢????商家咋搞,这样的架构下,只能一个一个,去搞了,笛卡尔积
问题二:
垂直分库后的的分布式事物问题
问题三:
执行复制sql,例如排序、分页、函数计算性能
数据分布在不同的节点,比如排序,需要从每个表里排出来,再在内存中排序,来做到正常的查询需求,很占用内存
问题四:
分布式主键id问题
单表,自增id就搞定了,多表呢?我们不能让主键id重复
问题五:
数据扩容问题,
当分库一次后,可能要分第二次,数据迁移咋搞?这都是问题
问题六:
分库分表技术选型
市面上这么多,选哪个更稳定,效率更高呢??
我们做海量数据处理,一般指的是水平的分库分表,
那么分的策略是什么?按照什么去分??
一种是按照范围分,range
另一种是hash取模分
对于范围划分,也可分很多,具体看场景
例如数字划分,通过用户id划分,通过时间划分,通过地域范围划分
id划分好处是简单明了,1-10000 10001到2000这样,非常方便,但会有一些问题
比如老用户一般操作就少了,新用户操作多,导致节点承载请求量不均匀
这种方案适合日志、流水的场景,就是单纯记录,复杂操作很少,甚至都不去读这样的
按照时间划分,这个也会有一些问题
比如用户增长,一般都是刚开始增长的慢,中间增长的快,最后慢,那么导致数据分配不均匀
按照地域划分,这个就很常见了,
同样也要考虑问题,
按照省份的话,北京,和黑龙江的能比吗?有时候外卖就因这个而垮掉,又可以把北京分为,北京1区,北京2区….这样
看我们卖阿里云的场景,就是按照地域划分
hash取模就很常用了,通过分配键partionkey取hash值,再取模,分配到对于的数据节点上
比如来一个,一个库4张表,两个库8张表的例子
userId id % 2 (库-取余) id /2 % 4 (表) 1 1 0 2 0 1 3 1 1 4 0 2 5 1 2 6 0 3 7 1 3 8 0 0 9 1 0
问题六:
分库分表技术选型
市面上这么多,选哪个更稳定,效率更高呢??
这里我们先把这个问题解决掉,顺便扫盲一些分库分表的术语
TDDL 头都大了
这是jar包形势的,阿里内部使用,开演功能较少,所以不适合我们学习使用
myCat
这是基于proxy代理的中间件,做了一层代理,对程序来说是透明的,但是做了一层代理,性能自然慢些
ShadingSphere-jdbc
这是Apache旗下的,基于jdbc,以jar包形式引入,无需代理,所以性能犹豫myCat,开源社区强大,缺点是代码侵入,我们需要配置
可以理解为加强版的jdbc驱动,兼容jdbc和ROM框架
这里选择sharingSphere-jdbc,来完善blog
这里面试官可能会问
shadringSphere-jdbc和myCat的区别
这个主要从这几方面来说
相同点是,都是对sql就行解析,路由、改写、合并
shardingSphere-jdbc无需代理,性能快,但是代码有侵入性,而myCat做了一层代理,对于程序透明,无侵入性,但是性能不如sharingSphere-jdbc
shardingSphere-jdbc以jar包形式,轻量型的,而myCat,要拦截所有jdbc请求
扫盲一些shardingSphere-jdbc的术语
本专栏主要解决分库分表的各种难题,不过于扫盲
仅仅列举常用的
分片键PartionKey,就是按照哪个分片
行表达式分片策略 InlineShardingStrategy
这里举一个分表的例子
这里做个最基础的认识,为后续方案的解决做铺垫。