存储方面一般我们能想到的三个:关系型数据库、NoSQL、缓存。
关系型数据库主要介绍:读写分离 和 分库分表。
读写分离:
1、分散压力到多节点,存储压力未改变,包括一主一从、一主多从、多主多从。
2、考虑复制延时,从而带来复杂性,一般解决的常见方法:写操作后的读操作指定发给主服务器;读从机失败后再读一次主机;关键业务读写在从,非关键业务读写分离。
分库分表:分散访问压力,分散存储压力。
1、业务分库:按照业务模块将数据分散到不同的数据库服务器。同时带来其他问题,比如:join操作(同库的不同表被分散到不同库)、事务问题(不同库中不同的表需要在同一事务中进行时)、成本问题(服务器增多、工作量增大等)。
2、分表:垂直拆分,比如订单表中将不常用的字段拆分出去,常用字段整合在一张表,提升性能和效率;
水平拆分,主要针对数据量大的,比如数据量达到千万级别,有的就会出现性能问题,需要考虑拆分。
水平拆分的复杂性要大于垂直拆分,一般会涉及到:路由分配问题、count计算问题、join操作问题、order by问题等。
路由分配一般可以通过 指定范围(容易造成分配不均匀)、Hash分配(分配均匀,但扩容不方便,比如2个扩容到4个,4个到8个)、配置路由(类似先索引配置,再写到指定的库表,路由表本身会成为瓶颈,数据量大的时候)。
Join操作:可以在业务逻辑中实现。
Count计算:业务计算 或者 单独的总数记录表。
Order By问题:业务逻辑汇总。
数据库读写分离常见的分配方式有两种:程序代码封装和中间件封装。
程序代码封装:抽象数据访问层来实现读写分离、分库分表。开源方案中比如:淘宝的TDDL
中间件封装:独立的系统,读写分离和分库分表。中间件本身会提供兼容的sql协议,业务服务器访问中间件和访问数据库直接无差别式访问,可以直接视中间件为一个数据库服务器。 业务系统 ---> 中间件(虚拟的数据库) -->数据库(真实的DB)。 开源方案中比如:Mysql官方的 Mysql Router、360开源的 Atlas(基于MySQL proxy实现)。
总的来说,分库分表的复杂度要大于读写分离,因为本身读写分离可以通过sql语句判别。