3.1 读写分离(主要是为了数据库读能力的水平扩展)

3.1.1 读写分离概念

单台mysql实例情况下不能支持短时间内大量的对数据库的读操作,所以会将数据库配置成集群,一个master(主库)、多个slave(从库),一般主库负责写,从库负责读,主从之间的同步方式为binlog日志方式。binlog日志可以有Statement(记录修改数据的sql,缺点slave和master执行结果可能不同)、Row(记录每一行数据的修改,缺点日志量大)、Mixed(Statement和Row两种方式的混合)三种方式。

3.1.2 读写分离好处

  • 避免单点故障,可以主从切换。

  • 负载均衡,读能力水平扩展:通过配置多个slave节点,可以有效避免过大的访问量对单个库造成的压力。

3.1.3 读写分离局限性

  • 需要对sql类型进行判断。如果是select等读请求,就走从库,如果是insert、update、delete等写请求,就走主库。

  • 主从数据同步延迟问题。因为数据是从master节点通过网络同步给多个slave节点,因此必然存在延迟。因此有可能出现我们在master节点中已经插入了数据,但是从slave节点却读取不到的问题。对于一些强一致性的业务场景,要求插入后必须能读取到,因此对于这种情况,我们需要提供一种方式,让读请求也可以走主库,而主库上的数据必然是最新的。

  • 事务问题。如果一个事务中同时包含了读请求(如select)和写请求(如insert),如果读请求走从库,写请求走主库,由于跨了多个库,那么jdbc本地事务已经无法控制,属于分布式事务的范畴。而分布式事务非常复杂且效率较低。因此对于读写分离,目前主流的做法是,事务中的所有sql统一都走主库,由于只涉及到一个库,jdbc本地事务就可以搞定。

  • 高可用问题。主要包括:

    新增slave节点:如果新增slave节点,应用应该感知到,可以将读请求转发到新的slave节点上。

slave宕机或下线:如果其中某个slave节点挂了/或者下线了,应该对其进行隔离,那么之后的读请求,应用将其转发到正常工作的slave节点上。

master宕机:需要进行主从切换,将其中某个slave提升为master,应用之后将写操作转到新的master节点上。

3.1.4 Zebra与读写分离

zebra团队提供了GroupDataSource来完成读写分离功能,解决了上述所有问题,且对业务方透明。开发人员可以像操作单个库那样,去访问mysql数据库集群,底层细节完全由zebra屏蔽。

  • 支持水平扩展从库,灵活的调整各个从库的任意流量比例

  • 支持优先就近选择从库进行读取数据,避免跨机房访问

  • 灵活的强制走主库策略,支持单条SQL或者整个请求内所有SQL等维度

3.2 分库分表(主要是为了写能力的水平扩展,如果只是为了读,那么读写分离,多几台slave机器,也可以解决)

3.2.1 分库分表概念

一旦业务表中的数据量大了,从维护和性能角度来看,无论是任何的 CRUD 操作,对于数据库而言都是一件极其耗费资源的事情。即便设置了索引,仍然无法掩盖因为数据量过大从而导致的数据库性能下降的事实 ,这个时候就该对数据库进行水平分区 (sharding,即分库分表 ).水平分区从具体表现上来看可以分为:只分表、只分库、分库分表三种。

3.2.1 分库分表好处

分库好处:降低单台机器的负载压力,提高读写性能。

分表好处:比如原来一张表4000w行数据,经过分表后每张表1000w数据,当执行插入操作时,维护索引的时间缩短,提升了写的效率;读时候可以同时从多张表中读,提升了读的效率。所以读写性能都得到了提升。

3.2.3 分库分表局限性

3.2.3.1 增删查改的功能变得复杂

原来的insert语句如下:

insert into user(id,name) values (1,”tianshouzhi”),(2,”huhuamin”), (3,”wanghanao”),(4,”luyang”);

经过分库分表后,需要将sql语句改为如下形式,并分别到每个库去执行:

insert into user_1(id,name) values (1,”tianshouzhi”)

insert into user_2(id,name) values (2,”huhuamin”)

insert into user_3(id,name) values (3,”wanghanao”)

insert into user_0(id,name) values (4,”luyang”)

具体的流程可以用下图描述:

解释如下:

  • sql解析:首先对sql进行解析,得到需要插入的四条记录的id字段的值分别为1,2,3,4

  • sql路由:sql路由包括库路由和表路由。库路由用于确定这条记录应该插入哪个库,表路由用于确定这条记录应该插入哪个表。

  • sql改写:上述批量插入的语法将会在 每个库中都插入四条记录,明显是不合适的,因此需要对sql进行改写,每个库只插入一条记录。

  • sql执行:一条sql经过改写后变成了多条sql,为了提升效率应该并发的到不同的库上去执行,而不是按照顺序逐一执行

  • 结果集合并:每个sql执行之后,都会有一个执行结果,我们需要对分库分表的结果集进行合并,从而得到一个完整的结果。

3.2.3.2 分布式id问题的解决

分库分表后,不能再使用mysql的自增主键。因为在插入记录的时候,不同库生成的自增id可能会发生冲突,因此要有一个全局的id生成器。

  • Snowflake雪花算法

分配一个64bit的long型id,分配如下:

41bit用作时间戳,精确到ms,10bit用于工作机器id(5bit是数据中心id,5bit是机器id),12bit用作序列号,也就是说某一个数据中心的一台机器在1ms时间内可以分配4096个id,序列号的生成可以采用Synchornized加锁的方式,也可以采用AtomicInteger(底层采用CAS)的方式。当在1ms内向某台机器申请多于4096个id时,机器可以推到下一ms生成。这64bit也可以根据自己需要设置不同bit的用途。

缺点: 时间回拨问题、机器id的分配回收问题、机器id的上限问题。这里不再详细阐述。(待补充)

  • proxy服务+数据库分段获取id

注: DX、YF等表示数据中心名称、leaf表示该数据中心的某台机器、数据表中的biz_tag表示业务标识,该业务的id要保证唯一,不同业务的id不需要保证、max_id表示该业务当前申请的最大id、step表示该业务每次申请的id数量。申请完成后,该step数量的id被数据中心的某台机器所持有,然后机器可以通过Synchornized/AtomicInteger(底层采用CAS)的方式去分配。

申请sql语句如下(使用事务):

Begin

UPDATE table SET max_id=max_id+step WHERE tag=xxx

SELECT tag, max_id, step FROM table WHERE tag=xxx

Commit

优点:每次分配step数量的id,数据库读写压力很低

缺点:HA高可用性要求极高,采用主从部署+异地灾备的部署方案。

3.2.3.3 分布式事务

分库分表场景下,分布式事务涉及到对不同库、不同表的操作要么同时成功,要么同时失败。

分布式事务解决方案:

XA事务

柔性事务:最大努力通知型、可靠消息最终一致性方案以及TCC两阶段提交

(待补充)

3.2.3.4 动态扩容

动态扩容是指增加分库分表的数量。动态扩容一般情况下伴随数据迁移。但使用everydb的方式进行数据库扩容时,不需要进行数据迁移。思路如下:

在id字段的后面额外加上几位数字。比如加上4位数据,2位表示分库编号,2位表示分表编号。这样一共便拥有了100*100=10000张表。原来的同一个分库分表数据后面加的数字一样即可,这样原来同一分库扩容后还在同一个分库,原来同一分表扩容后还在同一张分表。

3.2.3.5 数据迁移

对于新的应用,如果预估到未来数据量比较大,可以提前进行分库分表。对于老的应用,单表数据量已经比较大了,这时就涉及到数据迁移过程。美团使用Buffalo进行数据迁移。数据迁移流程如下:

  • 存量数据迁移。分批次select源数据库,依次将数据插入到目标库中,在该过程中不断有业务写入,通过binlog日志保存增量数据(存量数据迁移过程中的业务写入操作)。

  • 增量数据迁移。存量数据迁移完成后,获取增量数据,经过反解析、过滤、封装后同步到目标库,从而实现源库、目标库数据实时同步。也就是在目标库表中执行一遍存量数据迁移过程中的业务写入操作。

  • 增量数据迁移追上当前时间后,进行数据校验(比如行数、表大小、CRC校验等),一致后则进行切换。

数据库读写分离与分库分表相关推荐

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

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

  2. MySQL数据库知识学习(五)读写分离与分库分表策略

    通过数据库锁及存储引擎的学习,我们知道数据库在数据操作过程中为了保证数据的一致性是会给表或行加锁的,在网站发展的初期,由于没有太多访问量,一般来讲只需要一台服务器就够了,这的操作也不会有什么问题.但随 ...

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

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

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

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

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

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

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

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

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

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

  8. sharing-jdbc实现读写分离及分库分表

    需求: 分库:按业务线business_id将不同业务线的订单存储在不同的数据库上: 分表:按user_id字段将不同用户的订单存储在不同的表上,为方便直接用非分片字段order_id查询,可使用基因 ...

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

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

最新文章

  1. php 魔术变量和超级全局变量,PHP超级全局变量与魔术变量
  2. 为啥不能用uuid做MySQL的主键?
  3. 5.2.4.最简单的模块源码分析3
  4. 提高 Java 代码质量
  5. 阿里云混合云的政企上云新路径
  6. WPF中的Data Binding调试指南
  7. sklearn随机森林概述
  8. 用matlab 拟合实数解,求大神指点matlab用拟合的方式解延迟微分方程组参数
  9. Oracle中计算两个时间的时间差:
  10. amd显卡风扇调节_中端游戏显卡新晋黑马,华硕ROG STRIX RX5600XT O6G GAMING拆解评测...
  11. java中的文件处理io_Java的IO前奏曲:文件操作类之___File
  12. Databricks文档01----Azure Databricks初探
  13. 三七互娱上半年近九成营收来自手游 精品化优势凸显
  14. 了解和使用DotNetCore和Blazor中的异步编程
  15. python数据分析基础 阮敬_Python数据分析用到的几个重要的库
  16. 再学 GDI+[22]: TGPLinearGradientBrush - 之一: TLinearGradientMode
  17. 大碰撞!当Linux多线程遭遇Linux多进程
  18. CentOS 7 配置 VNC 远程桌面连接
  19. PLC 有哪几种常用编程语言
  20. win10红警2黑屏_Windows10黑屏常见情况及解决办法

热门文章

  1. python节日贺卡绘制
  2. 王牌战士服务器维修,《王牌战士》8月12日更新维护公告 英雄免费解锁两周年专属活动...
  3. Win10 发布UWD图形驱动程序 有助于小幅提高性能
  4. “图形驱动程序无法找到兼容的图形硬件”的处理方式
  5. 互联网公司测试组长/leader/经理如何面试社招测试工程师
  6. ion-slides 图片只能滑动一半、图片索引错误导致图片显示错误(缓存问题导致的)
  7. Android DoraemonKit 教程和简介
  8. 校验国内外的座机和手机号码
  9. scratch双语教师课件文档手册 3.scratch桌面舞台坐标系
  10. sql注入进阶/user-agent/基于报错的注入/保姆级教程/一看就会/