面试的时候,极可能会被问到海量数据的处理问题:面试
1.订单数据愈来愈多(亿级),查询愈来愈慢,如何处理?spring
2.分库分表会带来哪些反作用?可能的解决方式有哪些?数据库
目前常用的关系型数据库如MySQL、SQL Server等,都是以“行”为单位进行存储,为了快速检索,也都采用了B树或其余索引技术。后端
从原理上来说,表中的数据越多,索引树的范围越大,磁盘读取也越多,性能也就越低。安全
从实践角度来看,通常以百万到千万做为一个表的存储量级,超出该范围以后,性能就会降低,须要采用其余技术手段解决。性能优化
首先想到的就是可否将读和写分离,主数据库用于写入,读数据库(多个)用于对外提供查询,经过数据复制的方式将主数据库的数据同步到读库。该架构提高了数据库的读写能力,但对于主数据库的写入能力依然无法扩展。微信
其次,依据数据库分区的思路,能够将不一样的数据分散到不一样的库中,每一个库存储的数据都不一样,这样就能够将单一库的压力分散到多个库中,从而提高整个数据库的服务能力,这就是所说的分库分表技术。架构
若按照“字段(列)”分区,每一个库/表存储不一样的的字段,即schema不一样,就是“垂直拆分”;框架
若按“数据记录(行)”分区,每一个库/表的schema一致,但存储的数据不一样,就是“水平拆分”。异步
垂直拆分
水平拆分
这样作的好处就是解决了数据存储容量的问题,但也带来了诸多弊端。这里以“水平拆分”为例来分析。
1.如何能作到数据的平均拆分,防止某一库压力过大?
系统开发者要结合业务特色来肯定分库分表键,好比以userID为分库分表键,采用hash取模的方式将数据散列到不一样的库中。
但并非全部场景都适合用userID做为分库分表键的,若存在“大卖家”,则该userID可能有不少条记录,若简单的按照上述方法进行拆分,则可能打爆其中一个数据库。
通常来讲,会将一段时间之前的数据归档(好比某个userID三个月以前的数据),存放到相似HBase这种非关系型数据库中,以此来解决上述问题。
2.分库分表以后就要求每一个查询的where子句中必须携带分库分表键,但并不是每一个查询都能携带分库分表键的。
好比订单库按照订单号hash取模以后存储,此时分库分表键为订单号,那么想查询某位买家全部的订单,查询时就没有了分库分表键,就会出现“全表扫描”的状况。
通常在实践中解决这种问题的方法是创建“异构索引表”,即采用异步机制将原表内的每次一建立或更新,都换一个维度保存一份完整的数据表或索引表,拿空间换时间。
在上面说到,订单库按照订单号hash取模以后存储,同时也按照userID维度进行hash取模,再存储一份数据,那么想要获取某一userID的所有订单时,就将userID做为分库分表键传进去便可,避免了全表扫描。
上面这些是在海量数据处理过程当中出现问题的解决思路,工程师的硬实力不只体如今解决问题的思路上,更在于细节问题的打磨,所以还需在细节上进行更深的学习和探讨。若是你对这些感兴趣,那么如下免费福利就很适合你:
福利1
《网易云课堂Java进阶免费直播课》
适听人群:Java初、中级开发工程师
▼
1. 4月8日 20:00
深刻浅出线程安全 ~ 从原子性到手写实现JAVA锁
2. 4月9日 20:00
Shiro企业级安全框架应用&原理源码解读
3. 4月10日 20:00
美团技术团队-分布式事务实践
4. 4月11日 20:00
搜索引擎核心理论思想
5. 4月12日 20:00
网易严选后端性能优化实录
6. 4月13日 20:00
spring事务管理原理源码解读
7. 4月14日 20:00
网易组件式封装 - 基于Spring Boot实现本身的Starter
(全部直播可回看)
福利2
Java开发进阶资料包
包含「Java开发参考书籍」「Java开发学习图谱」「大数据容器数据库架构技术文档」等
扫描下方二维码
便可免费参与Java直播进阶课程
并领取Java开发进阶资料包
全方位扩充你的知识体系
微信号:weizhuanye51
免费课程,名额有限,先到先得~~