背景: 业务发展初期为了便于快速迭代, 很多应用都采用集中式的架构, 随着业务规模的扩展, 系统变得越来越复杂, 访问量越来越大, 不得不进一步扩展系统的吞吐能力.
优化 1, 主从集群: 通过数据库的复制策略, 可以将一台 mysql 数据库服务器中的数据复制到其他的 mysql 数据库服务器之上, 当各台数据库服务器上都包含相同数据的时候, 前端应用通过访问 mysql 集群中任意一台服务器, 都能够读取到相同的数据, 这样, 每台 mysql 服务器所需要承担的负载就会大大降低, 从而提高整个系统的承载能力, 达到系统扩展的目的.
要实现数据库的复制, 需要开启 master 服务器端的 binary log, 数据复制的过程实际上就是 slave 从 master 获取 binary log, 然后再在本地镜像的执行日志中所记录的操作, 由于复制过程是异步的, 因此, master 和 slave 之间的数据有可能存在延迟的现象, 此时只能够保证数据最终的一致性.
优化 2, 读写分离: 前端服务器通过 master 来执行数据写入的操作, 数据的更新通过 binary log 同步到 slave 集群, 而对于数据读取的请求, 则交由 slave 来处理, 这样, slave 集群可以分担数据库读的压力, 并且, 读写分离还保障了数据能够达到最终一致性. 一般而言, 大多数站点的读数据库操作要比写数据库操作更为密集, 如果读的压力较大, 还可以通过新增 slave 来进行系统的扩展, 因此, master-slave 的架构能够显著的减轻前面所提到的单库读的压力, 毕竟在大多数应用当中, 读的压力要比写的压力大的多.
master-slaves 复制架构存在一个问题, 即所谓的单点故障, 当 master 宕机, 系统将无法写入, 而在某些特定的场景下, 可能需要 master 停机, 以便进行系统维护, 优化或者升级, 同样的道理, master 停机将导致整个系统都无法写入, 直到 master 恢复, 大部分情况下这显然是难以接受的. 为了尽可能的降低系统停止写入的时间, 最佳的方式就是采用 dual master 架构, 即 master-master 架构.
优化 3, 分表: 对于访问极为频繁且数据量巨大的单表来说, 我们首先要做的, 就是减少单表的记录条数, 以便减少数据查询所需要的时间, 提高数据库的吞吐, 这就是所谓的 分表. 在分表之前, 首先需要选择适当的分表策略, 使得数据能够较为均衡的分布到多张表中, 并且, 不影响正常的查询. 对于互联网企业来说, 大部分数据都是与用户进行关联的, 因此, 用户 id 是最常用的分表字段, 因为大部分查询都需要带上用户 id, 这样既不影响查询, 又能够使数据较为均衡的分布到各个表中.
优化 4, 分库: 分表能够解决单表数据量过大带来的查询效率下降的问题, 但是, 却无法给数据库的并发处理能力带来质的提升, 面对高并发的读写访问, 当数据库 master 服务器无法承载写操作压力时, 不管如何扩展 slave 服务器, 此时都没有意义了. 因此, 我们必须换一种思路, 对数据库进行拆分, 从而提高数据库写入能力, 这就是所谓的 分库. 举例来说, 假设某门户网站, 它包含了新闻, 用户, 帖子, 评论等等几大块内容, 对于数据库来说, 它可能包含这样几张表, news,users,post,comment, 随着数据量的增加, 可以根据业务逻辑进行拆分, 分成多个库, 以提高系统吞吐能力.
有的时候, 数据库可能即面临着高并发访问的压力, 又需要面对海量数据的存储问题, 这时候, 需要对数据库即采用分库策略, 又采用分表策略, 以便同时扩展系统的并发处理能力, 以及提升单表的查询性能, 这就是所谓的 分库分表.
假设将原来的单库单表 order 拆分成 256 个库, 每个库包含 1024 个表, 那么, 按照前面所提到的路由策略, 对于 userid=262145 的访问, 路由的计算过程如下:
中间变量 = 262145%(256*1024)=1
库 = 取整 (1/1024)=0
表 = 1%1024=1
这意味着, 对于 userid=262145 的订单记录的查询和修改, 将被路由到第 0 个库的第 1 个表中执行.
缺陷:
1. 条件查询, 分页查询受到限制, 查询必须带上分库分表所带上的 id
2. 事务可能跨多个库, 数据一致性无法通过本地事务实现, 无法使用外键
3. 分库分表规则确定以后, 扩展变更规则需要迁移数据
来源: http://www.bubuko.com/infodetail-2651323.html