- 应用层解决:添加多数据源,由程序员完成,不能做到动态增加数据源
- 使用中间件:优点,源程序无需做任何改动,动态添加数据源无需重启;确定,程序依赖中间件,由中间件做中转代理,性能下降
spring基于应用层实现
使用aop技术,生成代理对象,通过获取方法名,进行切换数据源(需要配置多数据源)
https://www.cnblogs.com/ngy0217/p/8987508.html
中间件:mycat,通过拦截sql语句,进行分析,然后发往真实点数据库
mycat是数据库代理中间件
sharding jdbc
https://www.cnblogs.com/kevingrace/p/9365840.html
分库分表
当一张表的数据达到几千万时,为了缩短查询时间,进行分表
订单表的分库分表设计方案
按订单号拆分
(订单号的末尾3个数字,代表库名,表名;订单号是字符串,进行hash计算;)
查询用户所有订单(订单分散在了多个库,多个表中)
按用户id拆分
0-2千万的uid,对应的订单数据在a库,b表(一般不会用,数据不分散,如果某个用户下单多,会造成这个库压力特别大,而其他库压力小)
下面是常使用的方式
对uid取模运算(数据比较均匀分散到多个库中去;但扩容麻烦,需要进行数据迁移;为了减少数据迁移量,一般扩容是以倍数形式增加,这样迁移的数据量就比较小,使用倍数扩容,可以保证使用较长时间)
- 库名称计算:用户uid后4位,取32模,余数在0-31之间,所以库有32个库,库名为order_db_0,...,order_db_31
- 表名称计算:用户uid后4位,除以32,取整数,整数再除以32取余数,这样,表名为order_tb_0. order_tb_31
比如用户id:19408064,用最后4位数字8064除以32,得到是251.9,取它的整数是251。接着将251除以32,取余数,余数为27。
这样32*32=1024张表,单表维持在1千万-5千万的数据量,1024*1千万,就可以表示好多数据
优点:查询指定用户的所有订单,避免了跨库跨表查询
缺点:数据分散不均匀
最好的方案是:数据均匀分算,又能避免单表数据过多,还方便扩容
现有场景,通过订单号进行查询订单信息(通过上述存储方式,并不知道订单所存储的位置)
建立订单用户关联表,这样就可以知道订单属于哪个用户,再根据uid找到对应的库。这个表也应该分库分表进行存储,直接根据订单号进行分库分表
这是方便买家进行数据查看,卖家怎么办?通过数据冗余解决。还是上面思路,只不过根据卖家id进行分库分表。下单时,写两份数据,先把订单写入买家库,然后通过消息中间件同步订单数据到卖家库。
按时间分的话,性能比较差。