MySQL-集群架构及部署
2021-08-05 08:33:28 1 举报
AI智能生成
MySQL集群架构及部署
作者其他创作
大纲/内容
集群架构
集群架构设计
设计理念
在集群架构设计时,主要遵从以下三个维度
可用性
扩展性
一致性
可用性设计
方法
服务高可用,冗余服务
站点高可用,冗余站点
数据高可用,冗余数据
保证高可用的方法是冗余,但是数据冗余带来的问题是数据一致性问题
主要架构模式
主从模式
简单灵活,能满足多种需求
比较主流的用法,但是写操作高可用需要自行处理
双主模式
互为主从,有双主双写、双主单写两种方式,建议使用双主单写
扩展性设计
扩展性主要围绕读操作扩展和写操作扩展展开
提高读性能
加从库
简单易操作,方案成熟
从库过多会引发主库性能损耗,不建议作为长期的扩充方案,应该用良好的设计避免持续加从库来缓解读性能问题
分库分表
可以分为垂直拆分和水平拆分,垂直拆分可以缓解部分压力,水平拆分理论上可以无限扩展
提高写性能
一致性设计
主要考虑集群中各数据库数据同步以及同步延迟问题
方案
不使用从库
扩展读性能问题需要单独考虑,否则容易出现系统瓶颈
增加访问路由层
可以先得到主从同步最长时间t,在数据发生修改后的t时间内,先访问主库
适用场景
MySQL主从模式是指数据可以从一个MySQL数据库服务器主节点复制到一个或多个从节点
MySQL默认采用异步复制方式,这样从节点不用一直访问主服务器来更新自己的数据,从节点可以复制主数据库中的所有数据库,或者特定的数据库,或者特定的表
用途
实时灾备,用于故障切换(高可用)
读写分离,提供查询服务(读扩展)
数据备份,避免影响业务(高可用)
部署条件
从库服务器连通主库
主库开启binlog日志(设置log-bin参数)
主从server-id不同
实现原理
主从复制
步骤
1. 主库将数据库的变更操作记录到Binlog日志文件中
2. 从库读取主库中的Binlog日志文件信息写入到从库的Relay Log中继日志中
3. 从库读取中继日志信息在从库中进行Replay,更新从库数据信息
过程中涉及的Thread
Master-BinlogDump Thread
Master服务器对数据库更改操作记录在Binlog中,BinlogDump接到写入请求后,读取Binlog信息推送给Slave的I/O Thread
Slave-I/O Thread
将读取到的Binlog信息写入到本地Reloay Log中
Slave-SQL Thread
检测到Relay Log的变更请求,解析Relay Log中内容在从库上执行
整个过程都是异步操作,俗称异步复制,存在数据延迟现象
问题
主库宕机后,数据可能丢失
从库只有一个SQL Thread,主库写压力大,复制很可能延时
解决
半同步复制
解决数据丢失的问题
并行复制
解决从库复制延迟的问题
为了提升数据安全,MySQL让Master在某一个时间点等待Slave节点的ACK(Acknowledge_Character)消息,接收到ACK消息后才进行事务提交,这也是半同步复制的基础,MySQL从v5.5开始引入半同步复制机制来降低数据丢失的概率
主库事务写入步骤
1. InnoDB Redo File Write(Prepare Write)
2. Binlog File Flush & Sync to Binlog File
3. InnoDB Redo File Commit(Commit Write)
4. Send Binlog to Slave
级别
1. 当Master不需要关注Slave是否接收到Binlog Event时,即为传统的主从复制
2. 当Master需要在Step3等待Slave返回ACK时,即为after-commit,半同步复制(MySQL 5.5引入)
3. 当Master需要在Step2等待Slave返回ACK时,即为after-sync,增强半同步(MySQL5.7引入)
MySQL从5.6版本开始追加了并行复制功能,目的就是为了改善复制延迟问题,并行复制称为Enhanced_Multi-threaded_Slave(简称MTS)
在从库中IO和SQL线程,都是单线程模式,因此有了延迟问题,可以采用多线程机制来加强,减少从库复制延迟(IO多线程意义不大,主要是SQL多线程)
MySQLv5.6、5.7、8.0都是基于SQL多线程思想,不断优化,减少复制延迟
v5.6原理
其并行是基于库的。如果用户的MySQL数据库中是多个库,对于从库的复制速度的确可以有比较大的帮助
基于库的并行复制,实现相对简单,使用也相对简单。但是遇到单库多表的场景就发挥不出优势,另外对事务并行处理的执行顺序也是个大问题
v5.7原理
基于组提交的并行复制,5.7才可称为真正的并行复制
主要原因是Slave服务器的回放与Master服务器是一致的,不再有库并行复制的限制
原理
v5.7是通过对事务进行分组,当事务提交时,它们将在单个操作中写入到Binlog中。如果多个事务能同事提交成功,那么他们意味着没有冲突,因此可以在Slave上并行执行,所以通过在主库上的Binlog中添加组提交信息
v5.7的并行复制是基于一个前提,即所有已经处于prepare阶段的事务,都是可以并行提交的。这些当然也可以在从库中并行提交,因为处理这个阶段的事务都是没有冲突的。在一个组里提交的事务,一定不会修改同一行。
这是一种新的并行复制思路,完全摆脱了原来一直致力于为了防止冲突二座的分发算法,等待策略等复杂的而又效率低下的工作
为了兼容v5.6,v5.7引入了新的变量slave-parallel-type,其可配置的值有
DATABASE,默认值,基于库的并行复制
LOGICAL_CLOCK,基于组提交的并行复制
Slave如何知道事务是否在同一组
为了避免用户没有开启GTID功能(gtid_mode=OFF),MySQL5.7又引入了称之为Anoymous_Gtid的二进制日志event类型ANOYMOUS_GTID_LOG_EVENT
v5.7二进制日志较之原来的二进制日志内容多了last_committed和sequence_number
last_committed表示事务提交时,上次事务提交的编号
如果事务具有相同的last_committed,表示这些事务都在一组内,可以进行并行的回访
v8.0原理
基于write-set的并行复制
MySQL会有一个集合变量来存储事务修改的记录信息(主键hash值),所有已提交的事务所修改的主键值经过hash后都会与那个变量的集合进行对比,来判断改行是否与其冲突,并以此来确定依赖关系,没有冲突即可并行
这样的粒度到了row级别,此时并行的粒度更加精细,并行的速度会更快
配置与调优
binlog_transaction_dependency_history_size
用于控制集合变量的大小
binlog_transaction_dependency_tracking
用于控制binlog文件中事务之间的依赖关系,即last_committed值
值
COMMIT_ORDERE
基于组提交机制
WRITESET
基于写集合机制
WRITESET_SESSION
基于写集合,比writeset多了一个约束
同一个session中的事务last_committed按先后顺序递增
transaction_write_set_extraction
用于控制事务的检测算法,参数值为
OFF
XXHASH64
MURMUR32
master_info_repository
开启MTS功能后,务必将参数master_info_repository设置为TABLE,这样性能可以有50%-80%的提升
slave_parallel_workers
若设置为0,则MySQL退化为单线程复制
若设置为1,则SQL线程功能转化为Coordinator线程,但是只有一个worker,也是单线程复制,因为多了一次coordinator的转发,性能反而比0要差
slave_preserve_commit_order
v5.7后的MTS可以实现更小粒度的并行复制,但需要将slave_parallel_type设置为LOGICAL_CLOCK
同时需要开启本参数,来保证事务按照relay_log中记录的顺序回放,以保证数据的一致性
监控
Show Slave Status\\G
v5.7后 performance_schema库
replication_applier_status_by_worker表可以看到worker进程的工作情况
读写分离
引入时机
大多数互联网业务中,往往读多写少,数据库的读会首先成为瓶颈。如果已经优化了SQL,但是读还是瓶颈时,这是就可以选择“读写分离”了
读写分离首先需要将数据库分为主从库,一个主库用于写数据,多个从库完成读数据的操作,主从库之间通过主从复制机制进行数据的同步
在应用中可以在从库追加多个索引来优化查询,主库这些索引可以不加,用于提升写效率
读写分离架构也能够消除读写锁冲突从而提升数据库的读写性能,使用时需要注意
主从同步延迟
读写分配机制
使用读写分离时,数据库主从同步具有延迟性,数据一致性会有影响对于一些实时性要求比较高的操作,可以采用
写后立刻读
在写入数据库后,某个时间段内读操作就去主库,之后读操作访问从库
二次查询
先去从库读取数据,找不到时就去主库进行数据读取
该操作容易将压力返还给主库,为了避免恶意攻击,建议对数据库访问API操作进行封装,有利于安全和低耦合
根据业务特殊处理
根据业务特点和重要程度进行调整,比如重要的,实时性要求高的业务数据读写可以放在主库
对于次要的业务,实时性要求不高的可以进行读写分离,查询时去从库查询
读写分配机制是实现读写分离架构最关键的一个环节,就是控制何时去主库写,何时去从库读
实现方案
基于编程和配置实现
程序员在代码中封装数据库的操作,代码中可以根据操作类型进行路由分配,增删改时操作主库,查询时操作从库
这是目前生产环境中应用最广泛的
优点
实现简单,因为程序在代码中实现,不需要增加额外的硬件开支
缺点
需要开发人员来实现,运维人员无从下手,如果其中一个数据库宕机了,就绪呀修改配置重启项目
基于服务器代理实现
中间件代理一般介于应用服务器和数据库服务器之间,应用服务器并不直接进入到master/slave数据库,而是进入代理服务器
代理服务器接收到应用服务器的请求后,先进行判断然后转发到后端master/slave
数据库中间件
MySQL Proxy
官方提供的MySQL中间产品,可以实现负载均衡,读写分离
MyCat
是一款基于阿里开源产品Cobar研发的,基于Java编写的开源数据库中间件
Shardingsphere
是一套开源的分布式数据库中间件解决方案,由Sharding-JDBC、Sharding-Proxy和Sharding-Sidecar(计划中)这3款互相独立的产品组成
已经在2020.04.16从Apache孵化器毕业,成为Apache顶级项目
Atlas
是由360公司web平台部基础架构团队开发维护的一个数据库中间件
Amoeba
变形虫,该开源框架于2008年开始发布一款Amoeba for MySQL软件
很多企业刚开始都是使用MySQL主从模式,一主多从,读写分离等,但是单主如果发生单点故障,从库切换主库还需要做改动
如果是双主或多主,会增加MySQL入口,提升了主库的可用性
概念
指两台服务器互为主从,任何一台服务器数据变更,都会通过复制应用到另外一方的数据库中
双主双写/双主单写
建议使用双主单写,因为双主双写存在
ID冲突
在A库写入,当A数据未同步到B库时,对B库写入,如果采用自动递增容易发生ID主键冲突
可以采用MySQL自身的自动增长步长来解决,但是对数据库运维、扩展都不友好
更新丢失
同一条记录在两个主库中进行更新,会发生前面覆盖后面的更新丢失
高可用架构
一台Master提供线上服务,另一台Master作为备胎供高可用切换,Master下游挂载Slave承担读请求
随着业务发展,架构会从主从模式演变为双主模式,建议用双主单写,再引入高可用组件,如Keepalive和MMM等工具,实现主库故障自动切换
MMM架构
Master-Master Replication Manager for MySQL
是一套用来管理和监控双主模式,支持双柱故障切换的第三方软件
它使用Perl语言开发,虽然是双柱架构,但是业务上同一时间只允许一个节点进行写入操作
故障处理机制
MMM包含两类角色
写节点、读节点
当write节点出现故障,程序会自动移除该节点上的VIP
write操作切换到Master2,并将其设置为writer
将所有slave节点指向Master2
处理管理双节点,MMM也会管理Slave节点,在出现宕机、复制延迟或复制错误,MMM会移除该节点的VIP,直到节点恢复正常
监控机制
monitor
监控集群内数据库的状态,在出现异常时发布切换命令,一般和数据库分开部署
agent
运行在每个MySQL服务器上的代理进程,monitor命令的执行者,完成监控的探针工作和具体服务设置
设置VIP(虚拟IP)
指向新同步节点
MAH架构
Master High Availabiity
介绍
是一套比较成熟的MySQL高可用方案,也是一款优秀的故障切换和主从提升的高可用软件
在MySQL故障切换过程中,MHA能够做到在30s内自动完成数据库的故障切换操作,并且在进行故障切换过程中,MHA能在最大程度上保证数据一致性,以达到真正意义上的高可用
MHA还支持在线快速将Master切换到其他主机,通常只需0.5-2s
架构
目前MHA主要支持一主多从架构,要搭建MHA,要求一个复制集群中必须最少有3泰数据库服务器
组成
MHA Manager管理节点
可以单独部署在一台独立的机器上管理多个master-slave集群,也可以部署在一台slave节点上
负责检测master是否宕机、控制故障转移、检查MySQL复制状况等
MHA Node数据节点
运行在每台MySQL服务器上,不管是Master还是Slave,都成为Node
是被监控管理的对象节点,负责
保存和复制master的二进制日志
识别差异的中继日志事件并将其差异的事件应用于其他的slave
清除中继日志
MHA_Manger会定时探测集群中的所有master节点,当master出现故障时,它可以自动将最新数据的slave提升为新的master,然后将所有其他的slave重新指向新的master,整个故障转移过程对应用程序完全透明
把宕机Master的binlog保存下来
根据binlog位置点找到最新的slave
用最新slave的relay log修复其他slave
将保存下来的binlog在最新的slave上恢复
将最新的slave提升为master
将其他slave重新指向新提升的master,并开启主从复制
自动故障转移快
主库崩溃不存在数据一致性问题
性能优秀,支持半同步复制和异步复制
一个Master监控节点可以监控多个集群
主备切换
指将备库变为主库,主库变为备库,有可靠性优先和可用性优先两种策略
主备延迟
是由主从数据同步延迟导致的,与数据同步有关的时间点包括
主库A执行完成一个事务,写入binlog,这个时刻记为T1
之后将binlog传给备库B,把备库B接收完binlog的时刻记为T2
备库B执行完成这个binlog复制,这个时刻记为T3
主备延迟,就是同一个事务,在备库执行完成的时间和主库执行完成的时间之间的差值,即T3-T1
查看
show slave status
seconds_behind_master表示当前备库延迟了多少秒
原因
备库机器性能问题
机器性能差,甚至一台机器充当多个主库的备库
分工问题
备库提供了读操作,或者执行一些后台分析处理的操作,消耗了大量的CPU资源
大事务操作
大事务耗费的时间长,导致主备复制时间长
可靠性优先
主备切换过程一般由专门的HA高可用组件完成,但是切换过程会存在短时间不可用,因为在切换过程中某一个时刻主库从库都处于只读状态
流程
判断从库B的Seconds_Behind_Master值,当小于某个值才继续下一步
把主库A改为只读状态
等待从库B的Seconds_Behind_Master降为0
把从库B改为可读写状态
把业务请求切换至从库B
可用性优先
不等主从同步完成,直接把业务请求切换至从库B,并且让从库B可读写,这样几乎不存在不可用时间,但可能会数据不一致
总结
主备切换采用可用性优先,由于可能会导致数据不一致,所以大多数情况下,优先选择可靠性优先
在满足数据可靠性的前提下,MySQL的可用性依赖于同步延时的大小,同步延时越小,可用性越高
说明
数据量只增不减,历史数据又必须要留存,非常容易成为性能的瓶颈,要解决这样的问题,“读写分离”和缓存往往都不合适
比较普遍的方案就是使用NoSQL/NewSQL或分库分表
分库分表主要有垂直拆分和水平拆分两种模式,都属于物理空间的拆分
垂直拆分
又称为纵向拆分,是将表按库进行分离,或者修改表结构按照访问的差异将某些列拆分出去
应用时有垂直分库和垂直分表两种方式,一般谈到的垂直拆分主要指垂直分库
垂直分表就是将一张表中不常用的字段拆分到另一张表中,从而保证第一张表中的字段较少,避免出现数据库跨页存储的问题,从而提升查询效率
拆分后业务清晰,拆分规则明确
易于数据的维护和扩展
可以使行数据变小,一个数据块就能存放更多的数据,在查询时减少I/O次数
可以达到最大化利用Cache的目的,具体在垂直拆分的时候可以将不常变的字段放一起,经常改变的放一起
便于实现冷热分离的数据表设计模式
主键出现冗余,需要管理冗余列
会引起表JOIN操作,可以通过在业务服务器上进行join来减少数据库压力,提高了系统的复杂度
依然存在单表数据量过大的问题
事务处理复杂
水平拆分
又称为横向拆分,相对于垂直拆分,它不再将数据根据业务逻辑分类,而是通过某个字段,根据某种规则将数据分散至多个库或表中,每个表仅包含数据的一部分
水平分表是将一张含有很多记录数的表水平切分,不同的记录可以分开保存,拆分为几张结构相同的表
重点考虑拆分规则
范围、时间、Hash算法
拆分规则设计好,join操作基本可以数据库做
不存在单库大数据,高并发的性能瓶颈
切分的表结构相同,应用层改造较少,只需要增加路由规则即可
提高了系统的稳定性和负载能力
拆分规则难以抽象
跨库join性能较差
分片事务的一致性难以解决
数据扩容的难度和维护量极大
日常工作中,通常会同时采通两种拆分方式,垂直拆分更偏向于产品/业务/功能拆分,水平拆分更偏向于技术
主键策略
在分库分表环境中,数据分布在不同的数据表中,主键不能借助数据库自增长特性直接生成,否则会造成不同数据表主键重复
UUID
通用唯一识别码,长度是16个字节,表示为32个16进制数字
使用UUID做主键,可以在本地生成,没有网络消耗,所以性能比较高
但是UUID比较长,没有规律性,耗费存储空间
在InnoDB下,UUID的无序性可能引起数据位置频繁变动,影响性能
COMB
UUID变种,是数据库特有的一种设计思想,通过组合GUID和系统时间,以使其在索引和检索上有更优的性能
设计思路
既然UniqueIdentifier数据因毫无规律造成索引效率低下,那么保留其前10个字节,用后6个字节表示GUID生成的时间,将时间信息和UniqueIdentifier组合起来,保留其唯一性的同时增加了有序性,依次来提高索引效率
解决了UUID的无序问题,性能优于UUID
SNOWFLAKE
是Twiiter开源的分布式ID生成算法,结果是一个long型的ID
生成的ID整体上按照时间自增排序,并且整个分布式系统内不会产生ID重复,并且效率较高
缺点是强依赖机器时钟,如果多台机器环境时钟没同步,或始终回拨,会导致发号重复或服务不可用
数据库ID表
单独建表,ID设置为自动递增,其他地方需要全局唯一ID时,就向这张表模拟插入一条记录,用获取的ID进行其他表的插入
虽然可行,但是性能和可靠性都不够好
Redis ID
使用Redis生成ID,主要依赖与Redis是单线程的,所以可以用生成全局唯一ID
也可以使用Redis集群来获取更高的吞吐量
分片策略
分片(Sharding)是用来确定数据在堕胎存储设备上分布的技术。将一个数据库打碎成多个的过程就叫做分片,分片属于横向扩展方案
在分布式存储系统中,数据需要分散存储在堕胎设备上,分片就是把数据库横向扩展到多个数据库服务器上的一种有效的方式,其主要目的就是为了突破单节点数据库服务器的I/O能力限制,解决数据扩展性问题
策略
数据分片是根据指定的分片键和分片策略将数据水平拆分,拆分成多个数据片后分散到多个数据存储节点中
分片键适用于划分和定位表的字段,一般使用ID或时间字段
分片策略即分片的规则
基于范围分片
根据特定字段的范围进行拆分,如用户ID、订单时间等
新的数据可以落在新的存储节点上,如果集群扩容,数据无需迁移
数据热点分布不均,数据冷热访问不均匀,导致节点负荷不均
哈希取模分片
整型的key可直接对设备数量取模,其他类型的字段可以先计算key的hash值,然后再对设备数量取模
该模式也成为离散分片
实现简单,数据分配比较均匀,不容易出现冷热不均,负荷不均的情况
扩容是会产生大量的数据迁移
一致性hash分片
使用一致性hash能够很大程度避免后期集群扩容需要迁移旧数据的问题,很多中间件的集群分片都会采用一致性hash算法
扩容方案
技术难度
1. 数据迁移问题
2. 分片规则改变
3. 数据同步、时间点、数据一致性
停机扩容
一般初期都会使用的方案
1. 发布升级公告
2. 时间到了,停止所有对外服务
3. 新增数据库,通过数据迁移程序,完成数据迁移
4. 修改数据库服务配置
5. 重启服务,开始对外提供服务
回滚方案
万一数据迁移失败,需要将配置和数据回滚,改天再挂公告
简单
停止服务,缺乏高可用
程序员压力大, 需要指定时间完成
如果有问题没有及时测试出来,运行后发现问题,难以回滚
小型网站
大部分游戏
对高可用要求不高的服务
平滑扩容
数据库扩容的过程中,如果想要持续对外提供服务,保证服务的可用性,平滑扩容是最好的选择
平滑扩容即将数据库数量扩容成原来的2倍
1. 新增2个数据库
2. 配置双主进行数据同步
先测试、后上线
3. 数据同步完成之后,配置双主双写
同步因为有延迟,如果时刻有写操作,可能会存在不准确问题
4. 删除双主同步,修改数据库配置,并重启
5. 扩容完成,需要写程序,清空数据库中多余的数据
能够实现n库扩2n库的平滑扩容,增加数据库服务能力,降低单库一般的数据量,其核心原理是:成倍扩容,避免数据迁移
扩容期间,服务正常进行,保证高可用
相对停机扩容,时间长,项目组压力没那么大,出错率低
扩容期间遇到问题,随时解决,不怕影响线上服务
可以将每个数据库数据量减少一半
程序复杂、配置双主同步、双主双写、检测数据同步等
后期数据库扩容,代价比较高
大型网站
对高可用要求搞的服务
部署
Cent环境部署
1. 解压tar包
tar -xvf
预清除系统自带mariadb
2. 安装common、libs
rpm -ivh
3. 分别安装client、server
4. 安装devel
5. 初始化、实例化数据库
mysqld --initialize --user=mysql
通过 systemctl 设置开机自启动
查看随机产生的密码,登录数据库
6. 关闭防火墙,方便主机互联
主从复制部署
主库
开启binlog日志
设置server-id
设置同步忽略数据库
系统库
设置同步数据库
设置授权
grant replication slave on *.* to 'root'@'%' identified by 'root'
grant all privileges on *.* to 'root'@'%' identified by 'root'
flush privileges
从库
设置relay_log
设置read_only
设置同步
开启
start slave;
show slave status;
安装插件
install plugin rpl_semi_sync_master soname 'semisync_master.so'
开启功能
show variables like '%semi%';
install plugin rpl_semi_sync_slave soname 'semisync_slave.so'
重启slave
设置参数
show variables like '%binlog_group%'
show variables like '%slave_parallel%'
show variables like '%relay_log%'
MySQL
0 条评论
回复 删除
下一页