Mysql高并发解决方案

94 篇文章 6 订阅
44 篇文章 3 订阅

Mysql高并发解决方案

前言

随着近些年来分布式的应用,其伴随而来的是系统的数据量也越来越大,为了可以提升系统的整体性能,我们对以Mysql为代表的关系型数据库也提出了“分布式”的要求。

MyCat入门可参考我的博客:MyCat入门

使用HaProxy实现Mycat的高可用可参考我的博客: 使用HaProxy实现Mycat的高可用

正文

Mysql高并发解决方案

Mysql单节点的性能极限:

  • mysql默认的最大连接数为151,上限为100000。
  • 如果借助InnoDB的行级锁来实现“减库存”的话:由于数据库中InnoDB的行锁针对同一行数据的更新操作是串行执行的,那么某一个线程在未释放锁之前,其余的线程将会全部阻塞在队列中等待拿锁,并发越高时,等待的线程也就会越多,这会严重影响数据库的TPS,从而导致RT线性上升,最终可能引发系统出现雪崩。

由于Mysql单节点存在性能瓶颈,所以要进一步通过增加节点的方式来提升并发量,于是可以采用主从复制进而实现读写分离,缓解单节点的IO压力。

MySQL主从复制实现读写分离

事务的两阶段提交
Mysql使用两阶段提交解决故障恢复、主从、主备复制时,保持了数据的一致性,即实现binlogInnoDB redo log的数据一致性。

  • 阶段一redo log 写盘,InnoDB 事务进入 prepare 状态
  • 阶段二:如果前面prepare成功,binlog 写盘,那么再继续将事务日志(redo log)持久化到binlog,如果持久化成功,那么InnoDB事务 则进入commit 状态

每个事务binlog的末尾,会记录一个 XID event,标志着事务是否提交成功。

MySql数据库主从复制的方式

主从复制是基于日志(binlog)主要有以下四种:

  • 异步复制(默认)MySQL 默认的复制策略,Master处理事务过程中,将其写入Binlog就会通知Dump thread线程处理,然后完成事务的提交,不会关心是否成功发送到任意一个slave中。
  • 半同步复制Master处理事务过程中,提交完事务后,必须等至少一个Slave将收到的binlog写入relay log返回ack(提交后才同步)才能继续执行处理用户的事务。
  • 增强半同步复制:半同步的问题是因为等待ACK的点是Commit之后,此时Master已经完成数据变更,用户已经可以看到最新数据,当Binlog还未同步到Slave时,发生主从切换,那么此时从库是没有这个最新数据的,用户又看到老数据。增强半同步将等待ACK的点放在提交Commit之前(同步后再提交),此时数据还未被提交,外界看不到数据变更,此时如果发送主从切换,新库依然还是老数据,不存在数据不一致的问题。
  • 组复制MySQL在引擎层完成Prepare操作写Redo日志之后,会被MySQL的预设Hook拦截进入MGR层,MGR层将事务信息打包通过Paxos协议发送到全部节点上,只要集群中过半节点回复ACK(半数写成功),那么将告诉所有节点数据包同步成功,然后每个节点开始自己认证(certify)通过就开始写Binlog,提交事务或者写relay log,数据同步,如果认证不通过则rollback

MySql主从复制的涉及三个行为:

  1. 数据存储Master将数据改变记录到二进制日志(binary log)中,也就是配置文件log-bin指定的文件,这些记录叫做二进制日志事件(binary log events);
  2. 数据传输Slave 通过 I/O 线程读取 Master 中的 binary log events 并写入到它的中继日志(relay log);
  3. 数据重放Slave 重做中继日志中的事件,把中继日志中的事件信息一条一条的在本地执行一次,完成数据在本地的存储,从而实现将改变反映到它自己的数据。

分表

水平分表的特点

  • 将一张表拆分成多张表,每张表的结构是一样(使用的是同一个FRM文件,但每一子表存放在在同一个磁盘中一个独立MYD文件和一个独立的MYI文件,MRG文件记录分表信息);
  • 利用主表作为查询的接口(没有数据文件),表一表二作为存储数据的实际表单 ;
  • 决定数据放在那一张实际的表,往往采用对ID取模(即求余)或者对业务主键hash运算,确保有关联性的数据在同一个子表中;
  • merge来分表,是最简单的一种方式实现分区;

以对ID取模的方式举例:

#向表一插入数据:
insert into tb_member1(id,name,sex) select id,name,sex from member where id%2=0; //这里区分表一表二
#向表二插入数据:
insert into tb_member2(id,name,sex) select id,name,sex from member where id%2=1;
#查看一下主表的数据:
select * from tb_member;

分区

水平分区的特点:

  • 分区一张表的数据分成N多个区块,这些区块可以在同一个磁盘上,也可以在不同的磁盘上,但实际上还是同一张表,只是把MYDMYI同时切分了很多份,Par文件会记录分区信息;
  • 分区使用partition by比较容易实现,水平分区支持range分区、list分区、hash分区等方式;
  • 采用那种方式进行分区取决于业务,比如以权益中心为例:通常来说我们希望同一个用户的数据会存在同一个物理表中,可以采用以手机号进行hash的方式进行分区;
#向表插入数据,分区相对于分表是无感知的:
insert into member(id,name,sex) values (1,’luo’,’男’);
#查看一下主表的数据:
select * from tb_member;

分表分库

分表分库是一种分区+分表结合起来的方式:

  • 原本存储于一个库的数据分块存储到多个库上;
  • 把原本存储于一个表的数据分块存储到多个表上;
  • 分库可以解决单台服务器性能不够,或者成本过高问题;
  • 分表分库可以是水平分表分库,也可以是垂直分表分库;

分表分库常见的问题

跨库join

当数据分到不同的库上,一般是禁止跨库join的,一般会采用以下方式:

  • 全局表:所谓全局表,就是有可能系统中所有模块都可能会依赖到的一些表。比较类似我们理解的“数据字典”。为了避免跨库join查询,我们可以将这类表在其他每个数据库中均保存一份;
  • 字段冗余:比如“订单表”中保存“卖家Id”的同时,将卖家的“Name”字段也冗余,这样查询订单详情的时候就不需要再去查询“卖家用户表”;
  • 数据同步:使用ETL工具(数据迁移)做表数据同步,定时A库中的tab_a表和B库中tbl_b有关联,可以定时将指定的表做同步;

跨库事务

由于数据存储到了不同的库上,数据库事务管理出现了困难。如果依赖数据库本身的分布式事务管理功能去执行事务,将付出高昂的性能代价,所以实际上我们只会对历史数据进行分表分库拆分。

跨库事务

由于数据存储到了不同的库上,数据库事务管理出现了困难。跨库事务的核心是保障一致性问题,主要有两种方式:

  • 分布式事务:分布式事务能最大限度保证了数据库操作的原子性,但是成本过高,一般不采用。
  • 最终一致性:采用本地事务,本地落地,补偿发送。

如果依赖数据库本身的分布式事务管理功能去执行事务,将付出高昂的性能代价,所以实际上我们只会对历史数据进行分表分库拆分。

跨库分页、排序、函数问题

跨节点多库进行查询时,会出现limit分页、order by排序等问题:

  • 当排序字段就是分片字段时:通过分片规则就比较容易定位到指定的分片;
  • 当排序字段非分片字段时:需要先在不同的分片节点中将数据进行排序并返回,然后将不同分片返回的结果集进行汇总和再次排序,最终返回给用户。

唯一全局主键问题

在分库分表环境中,由于表中数据同时存在不同数据库中,主键值平时使用的自增长将无用武之地,某个分区数据库自生成的ID无法保证全局唯一,常见有两种方案:

  • UUID:主键是最简单的方案,本地生成,性能高,没有网络耗时。但缺点也很明显,由于UUID非常长,会占用大量的存储空间;另外,作为主键建立索引和基于索引进行查询时都会存在性能问题,在InnoDB下,UUID的无序性会引起数据位置频繁变动,导致分页。
  • snowflake雪花算法:解决了分布式系统生成全局ID的需求,生成64位的Long型数字,生成的ID整体上按时间趋势递增;

分表分库的业务场景

对数据库进行分表分库时可参考一下原则:

  • 能不切分尽量不要切分:不到万不得已不用轻易使用分表分库,避免“过度设计”和“过早优化”。
  • 数据量过大,正常运维影响业务访问:单表太大,备份时需要大量的磁盘IO和网络IO等。
  • 业务发展,需要对某些字段垂直拆分:比如我们有时候会把用户登陆这部分从用户表独立出来,做成登陆表。
  • 数据量快速增长:如果由于数据量的增长,性能接近瓶颈,就需要考虑水平切分,要根据业务选择合适的规则切分,如对ID取模或者对手机号做hash运算等。
  • 安全型和可用性:将数据切分到不同的数据库可以降低数据库宕机对业务的影响。

MyCat实现Mysql的读写分离本质上其实就是分表分库的实践:具体可参考我的博客:MyCat入门

在这里插入图片描述

  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值