前文介绍了分表分库的一些基本概念,接下来我对分表分库的具体实现一探究竟。
在如今互联网高速发展的环境下,啥不会就直接找度娘,然后就崇拜着大神指导方案...... 然后 C V 大法真是屡试不爽
最后才发现大佬与菜鸟的区别就是,大佬是如何优雅的实现需求、如何避免bug产生、如何排查以及解决问题.....
敬畏技术,谦卑前行。多总结平时开发涉及到的知识......
分表分库的流行的方案
方案一 : 基于应用层实现分表分库之后的业务逻辑处理
方案二 : 基于代理层实现,即在应用层和底层数据结构中间添加一层代理层,而具体的路由规则由代理层进行处理 (MyCat等框架)
菜鸡的打怪升级过程 (Mybatis 实现水平分表)
在项目中,由于有一张操作记录流水表,短短三个月数据就到达了一亿二千万,虽然做了读写分离、索引,依然无法解决查询数据时的性能问题,为此在大佬的带领下做了水平分表处理;
# 1、如何实现表的创建?
在开发中,持久层框架一般都是采用Mybatis、SpringDataJPA,我们这次在分表过程中对于表的创建采用了 Mybatis 支持动态创建表的特性;
为此介绍 Mybatis 强大的特性 : 动态SQL
MyBatis在对sql语句进行预编译之前,会对sql进行动态解析,解析为一个BoundSql对象,也是在此对动态sql进行处理;
在mapper.xml文件中 #{ } 与 ${ } 的区别
select * from user where name = #{name};
会被解析成:select * from user where name = ?;
select * from user where name = ${name};
当我们传递参数"garen"时,sql会解析为:
select * from user where name = “garen”;
总结:#{ }被解析为一个参数占位符 ?
${ }仅仅为一个纯粹的String替换,在动态SQL解析阶段将会进行变量替换
为此我们就可以利用动态Sql这个特性,动态的去创建表
注:分表的方式有很多中,在菜鸡的打怪过程中是按照主键 模 100 然后将数据打散到100表中
首先:判断表是否存在
<select id="existTable" resultType="java.lang.Boolean">
select count(1)
from information_schema.TABLES
where LCASE(table_name)=#{tableName}
</select>
然后:创建表
boolean createTable(@Param("createTable") String createTable); --> Mapper层
<insert id="createTable">
CREATE TABLE ${createTable} (
id bigint(11) NOT NULL AUTO_INCREMENT,
speed float DEFAULT NULL,
......
);
</insert>
# 2、如何基于应用层实现路由规则实现CRUD?
看完上面介绍的动态Sql创建表,在实现CRUD简直是小菜一碟......
例如:
<insert id="insertOrderOperation">
INSERT INTO ${insertTable}
(speed)
VALUES
(#{trackpoint.speed})
</insert>
# 3、如何处理上线问题?
如文章开篇所述能解决问题的是大佬,菜鸡总是在不断制造bug,如何优雅的处理上线数据才是关键点,为此做出以下几点总结:
1、数据无感知如何迁移
2、上线过程中如何避免数据丢失
3、新旧数据如何过渡
# 4、如何扩展表中字段?
当分表分库之后,在需要在表中增加字段的时候,菜鸡使用的是存储过程,然后在业务逻辑捕获异常做处理,当捕获到由于字段缺失插入数据失败,就做对应的处理;
具体如何实现,请看下文分解......
鄙人不才,在您面前献丑只愿与您结伴而行,文章若有不当之处,望大佬指点一二;如果我对您有帮助的话,还希望您能点赞分享,成长是一场苦涩的独自修行,我很需要您的陪伴与支持,这也是鄙人不断前行的根本动力,让我们在互相陪伴见证彼此生长的同时能够感染身边最亲近的人一同成长,鄙人在此叩谢!