通过数据库锁及存储引擎的学习,我们知道数据库在数据操作过程中为了保证数据的一致性是会给表或行加锁的,在网站发展的初期,由于没有太多访问量,一般来讲只需要一台服务器就够了,这的操作也不会有什么问题。但随着业务系统的扩大,系统变得越来越复杂,越来越难以维护,开发效率变得越来越低,并且对资源的消耗也变得越来越大,通过硬件提高系统性能的方式带来的成本也越来越高。

因此,前期一个好的网站架构设计是后期系统进行扩展和维护的重要保障。随着业务系统的扩大,遇到的问题主要分为两大类:

  1. 海量数据的存取问题
  2. 高并发的安全和效率问题

虽然这些问题的具体解决方案要根据实际场景分析,但其思想基本都是对数据库的扩展,数据库的扩展主要包括:业务拆分、读写分离,数据库分库与分表

业务拆分

业务拆分是在架构设计层面上的解决方案,业务起步初始,为了加快应用上线和快速迭代,很多应用都采用集中式的架构

例如:电商平台,包含了用户、商品、评价、订单等几大模块,最简单的做法就是在一个数据库中分别创建users、shops、comment、order四张表。

但是随着业务系统的扩大,系统变得越来越复杂,越来越难以维护,开发效率变得越来越低,并且对资源的消耗也变得越来越大,通过硬件提高系统性能的方式带来的成本也越来越高。我们不得不对业务进行拆分。每一个模块都使用单独的数据库来进行存储,不同的业务访问不同的数据库,如下图将原本对一个数据库的依赖拆分为对4个数据库的依赖,这样的话就变成了4个数据库同时承担压力,系统的吞吐量自然就提高了。

业务拆分要结合具体的实用常场景,尽早的作出合理的架构设计,以免后续的扩展难度过大。

读写分离

在之前数据库锁的学习中我们知道,读操作是共享锁并不会阻塞其他读操作,但写操作会阻塞其他所有操作。因此显然读的效率一般是远高于写的效率的,特别是在业务读多写少的情况下,写操作会阻塞大量的读,数据量大甚至会造成数据库崩溃,因此采用数据库读写分离的策略解决这个问题。

读写分离,顾名思义就是读操作和写操作分离开来。让主数据库处理事务性增、改、删操作(INSERT、UPDATE、DELETE),而从数据库处理SELECT查询操作。数据库复制被用来把事务性操作导致的变更同步到集群中的从数据库。

数据库读写分离的基本结构:

数据同步

MySQL支持的复制类型

  1. 基于语句的复制。在服务器上执行sql语句,在从服务器上执行同样的语句,mysql默认采用基于语句的复制,执行效率高。
  2. 基于行的复制。把改变的内容复制过去,而不是把命令在从服务器上执行一遍。
  3. 混合类型的复制。默认采用基于语句的复制,一旦发现基于语句无法精确复制时,就会采用基于行的复制。

复制过程

  1. 在每个事务更新数据完成之前,主数据库master在二进制日志记录这些改变。写入二进制日志完成后,master通知存储引擎提交事务。
  2. 从数据库slave将master的binary log复制到其中继日志。首先slave开始一个工作线程(I/O),I/O线程在master上打开一个普通的连接,然后开始binlog dump process。binlog dump process从master的二进制日志中读取事件,如果已经跟上master,它会睡眠并等待master产生新的事件,I/O线程将这些事件写入中继日志。
  3. Sql slave thread(sql从线程)处理该过程的最后一步,sql线程从中继日志读取事件,并重放其中的事件而更新slave数据,使其与master中的数据一致,只要该线程与I/O线程保持一致,中继日志通常会位于操作系统缓存中,所以中继日志的开销很小。

所以对于整个读写分离过程,就是在主服务器上修改,数据会同步到从服务器,从服务器只能提供读取数据,不能写入,实现备份的同时也实现了数据库性能的优化,以及提升了服务器安全。

读写分离的实现

较为常见的Mysql读写分离分为以下两种:基于程序代码内部实现和基于中间代理层实现。

基于程序代码内部实现

在代码中根据select 、insert进行路由分类,这类方法也是目前生产环境下应用最广泛的。优点是性能较好,因为程序在代码中实现,不需要增加额外的硬件开支,缺点是需要开发人员来实现,运维人员无从下手。

基于中间代理层实现

代理一般介于应用服务器和数据库服务器之间,代理数据库服务器接收到应用服务器的请求后根据判断后转发到后端数据库。

有以下代表性代理服务器:

  • mycat 基于阿里的cobar改版的(比较稳定,论坛活跃)
  • atlas 360开发的 网友说不是很稳定 (已经很久没更新)
  • mysql-proxy mysql自带 (不是很稳定)
  • oneproxy 比较稳定 性能也很好 (需要付费)
  • amoeba 好像还行,有一些公司使用 (但是很久没有更新了)

一般选择mycat作为代理服务器来实现,基本实现原理为:

基本思路为:

  1. 当master正常时,读操作发生在两个slave上,写操作发生在master上。master通过主从配置实时同步数据到两个slave上。
  2. 当master挂了,为了数据的一致性,和master为主从关系的slave2被停止访问。这时slave1负责读和写,当master重新恢复后,slave1同步数据给master,然后再次恢复最初读写状态。

主从同步延迟

一个服务器开放N个链接给客户端来连接的,这样有会有大并发的更新操作, 但是从服务器的里面读取binlog 的线程仅有一个, 当某个SQL在从服务器上执行的时间稍长 或者由于某个SQL要进行锁表就会导致,主服务器的SQL大量积压,未被同步到从服务器里。这就导致了主从不一致, 也就是主从同步延迟

主从同步原理及解决方案是视情况而定的,基本没有统一的解决办法,具体可参考这篇文章。

分库分表

分区分库分表

1.分区

分区就是把一张表的数据分成N个区块,在逻辑上看最终只是一张表,但底层是由N个物理区块组成的,分区实现比较简单,数据库mysql、oracle等很容易就可支持。对业务透明,分区只不过把存放数据的文件分成了许多小块,根据一定的规则把数据文件(MYD)和索引文件(MYI)进行了分割,分区后的表呢,还是一张表。

2.分表

分表就是把一张表按一定的规则分解成N个具有独立存储空间的实体表。系统读写时需要根据定义好的规则得到对应的字表明,然后操作它。当数据量大到一定程度的时候,都会导致处理性能的不足,这个时候就没有办法了,只能进行分表处理。也就是把数据库当中数据根据按照分库原则分到多个数据表当中,这样,就可以把大表变成多个小表,不同的分表中数据不重复,从而提高处理效率。

3.分库

分表和分区都是基于同一个数据库里的数据分离技巧,对数据库性能有一定提升,但是随着业务数据量的增加,原来所有的数据都是在一个数据库上的,网络IO及文件IO都集中在一个数据库上的,因此CPU、内存、文件IO、网络IO都可能会成为系统瓶颈。

分表策略

单表的数据量是有限制的,当单表数据量到一定条数之后数据库性能会显著下降。数据多了之后,对数据库的读、写就会很多。分库减少单台数据库的压力。一般都是通过主键进行散列分库分表的。

而就主键来说,对于大部分数据库的设计和业务的操作基本都与用户的ID(主键)相关,因此使用用户ID是最常用的分库的路由策略。用户的ID可以作为贯穿整个系统用的重要字段。因此,使用用户的ID我们不仅可以方便我们的查询,还可以将数据平均的分配到不同的数据库中(当然,还可以根据类别等进行分表操作,分表的路由策略还有很多方式)。

以电商平台为例,订单表order存放用户的订单数据,有用户ID(user_id)、订单号(order_num)等字段列。当数据比较大的时候,对数据进行分表操作,首先要确定需要将数据平均分配到多少张表中,也就是:表的容量

这里假设有100张表进行存储,则我们在进行存储数据的时候,首先对用户ID进行取模操作,根据 user_id %100 获取对应的表进行存储查询操作,示意图如下:

如图,先根据user_id % 100 定位所属表,再根据user_id具体找到查询的数据。

需要注意的是,另外,在实际的开发中,我们的用户ID更多的可能是通过UUID生成的,这样的话,我们可以首先将UUID进行hash获取到整数值,然后在进行取模操作。(UUID 是 通用唯一识别码(Universally Unique Identifier)的缩写,是一种软件建构的标准,UUID是由一组32位数的16进制数字所构成,所以UUID理论上的总数为16^32=2^128,约等于3.4 x 10^38。也就是说若每纳秒产生1兆个UUID,要花100亿年才会将所有UUID用完。)

分库策略

数据库分表能够解决单表数据量很大的时候数据查询的效率问题,但是无法给数据库的并发操作带来效率上的提高,因为分表的实质还是在一个数据库上进行的操作,很容易受数据库IO性能的限制。

因此,如何将数据库IO性能的问题平均分配出来,很显然将数据进行分库操作可以很好地解决单台数据库的性能问题。分库策略与分表策略的实现很相似,最简单的都是可以通过取模的方式进行路由。

依旧以上述电商为例,假设有100个数据库,先根据user_id % 100 定位所属库,再根据user_id具体找到查询的数据。

分库分表策略

上述的配置中,数据库分表可以解决单表海量数据的查询性能问题,分库可以解决单台数据库的并发访问压力问题。

有时候,我们需要同时考虑这两个问题,因此,我们既需要对单表进行分表操作,还需要进行分库操作,以便同时扩展系统的并发处理能力和提升单表的查询性能,就是我们使用到的分库分表。

分库分表的策略相对于前边两种复杂一些,一种常见的路由策略如下:

  1. 中间变量 = user_id%(库数量*每个库的表数量);
  2. 库序号 = 取整(中间变量/每个库的表数量);
  3. 表序号 = 中间变量 % 每个库的表数量;

例如:数据库有256 个,每一个库中有1024个数据表,用户的user_id=262145,按照上述的路由策略,可得:

  1. 中间变量 = 262145%(256*1024)= 1;
  2. 库序号 = 取整(1/1024)= 0;
  3. 表序号 = 1%1024 = 1;

即,对于user_id=262145,将被路由到第0个数据库的第1个表中。

总结

数据库的读写分离和分库分表都是数据库进行扩展的一种方法,除此之外,对于一个可扩展、高性能、高并发的网站使用到的技术远不止这些。使用缓存、页面静态化技术、数据库优化、分布式部署数据库等是实现一个好的网站所必须掌握的技术,但学习是一个漫长的过程,还需一步步脚踏实地。

参考文章:

https://blog.csdn.net/xlgen157387/article/details/53230138

https://blog.csdn.net/xlgen157387/article/details/53976153

MySQL数据库知识学习(五)读写分离与分库分表策略相关推荐

  1. 高性能高可用MySQL(主从同步,读写分离,分库分表,去中心化,虚拟IP,心跳机制)

    高性能高可用MySQL(主从同步,读写分离,分库分表,去中心化,虚拟IP,心跳机制) 视频地址:https://www.bilibili.com/video/BV1ry4y1v7Tr?p=8& ...

  2. mybatis+shardingJdbc实现数据库读写分离和分库分表

    文章目录 一.原理介绍 二.环境准备 2.1 数据库环境 2.2 开发环境 2.2.1 pom.xml 2.2.2 建表语句 三.主要代码 3.1 实体 3.2 Mapper 3.3 Controll ...

  3. MyCat 读写分离与分库分表

    一.Mycat 简介 Mycat 是一个开源的数据库中间件,可以解决分布式数据库环境下的大多数问题,如读写分离.分库分表等,除此之外,它还具备以下特性: 支持 MySQL.Oracle.DB2.SQL ...

  4. MySQL8高级_读写分离和分库分表

    MySQL8高级_读写分离和分库分表 第01章 高性能架构模式 互联网业务兴起之后,海量用户加上海量数据的特点,单个数据库服务器已经难以满足业务需要,必须考虑数据库集群的方式来提升性能.高性能数据库集 ...

  5. 1、读写分离、分库分表

    1-1 海量数据的存储与访问瓶颈解决方案-数据切分 背景         在当今这个时代,人们对互联网的依赖程度非常高,也因此产生了大量的数据,企业视这些数据为瑰宝.而这些被视为瑰宝的数据为我们的系统 ...

  6. 数据库读写分离与分库分表

    3.1 读写分离(主要是为了数据库读能力的水平扩展) 3.1.1 读写分离概念 单台mysql实例情况下不能支持短时间内大量的对数据库的读操作,所以会将数据库配置成集群,一个master(主库).多个 ...

  7. SpringBoot + Sharding JDBC 读写分离、分库分表

    Sharding-JDBC 最早是当当网内部使用的一款分库分表框架,到2017年的时候才开始对外开源,这几年在大量社区贡献者的不断迭代下,功能也逐渐完善,现已更名为 ShardingSphere,20 ...

  8. Sharding-Jdbc实现读写分离、分库分表,妙!

    点击关注公众号,实用技术文章及时了解 1.概览 ShardingSphere-Jdbc定位为轻量级Java框架,在Java的Jdbc层提供的额外服务.它使用客户端直连数据库,以jar包形式提供服务,可 ...

  9. Mycat简单实现读写分离与分库分表

    Mycat数据库读写分离 环境: 客户端1.13↓mycat中间件1.11↙ ↘ master主机1.12 slave主机1.10 一.master主机(1.12)配置 两台主机必须时间同步,可以部署 ...

最新文章

  1. python写web难受-用python写脚本此页面上造成web运行速度减慢
  2. python文本去重_Python做文本按行去重的实现方法
  3. 排序算法之low B三人组
  4. thinking-in-java(12)通过异常处理错误
  5. matlab int 积不出,matlab – 点积:*命令与循环给出不同的结果
  6. sublime Text 3实用功能和常用快捷键收集
  7. macOS 下的数据库客户端工具
  8. keil5怎么放大字体_keil5不同字体不全 keil字体放大快捷键
  9. windowsxp主题包把windowsXP主题改成Windows7风格
  10. gentoo 修改键盘映射
  11. 114-select(基础)
  12. Python 字符串str详解(超详细)
  13. 手机图形计算器matlab,科学图形计算器 Mathlab-科学图形计算器手机版下载V4.12-西西软件下载...
  14. 天正建筑中如何将标注单位M改为mm
  15. 计算机科学投稿须知,《计算机科学》投稿须知
  16. 揭秘你所看不见的技术原理 - 附近的人
  17. LogicFlow从新手到入门
  18. 线性代数——二次型化为标准型的总结
  19. 典型的多层神经网络模型,多层变量神经网络分析
  20. 光纤通信工程-波分复用DWDM(十一)

热门文章

  1. agent与搜索(人工智能学习笔记)
  2. 用java生成一维码
  3. hp z240工作站安装windows7操作系统方法
  4. 电商专题之 Shopee v.s. Lazada
  5. 2013MPD上海6.22 PM 陆宏杰:通往卓越管理的阶梯 6.23AM Ray Zhang 产品创新管理的十八般武艺...
  6. html负一屏效果,负一屏谁最实用 三大旗舰负一屏功能对比
  7. 免费PPT网站,这三个就够了
  8. 网页 服务器长连接超时,服务器客户端长连接超时时间吗
  9. 前端和后端就业前景如何?
  10. 多线程抢票_一个人干掉黄牛 双系统多线程抢票指南