【开营第二课,MySQL 高并发场景实战】
讲师: 凌洛,阿里云数据库解决方案专家。
课程内容:高并发场景下MySQL数据库的技术挑战;如何用RDS MySQL支撑高并发业务;高并发场景数据库运维最佳实践。
答疑汇总:特别感谢班委@李敏 同学
-
Mysql 一年应该是什么水平?需要知道哪些知识?
A:个人学习/接触 Mysql 一年的话,最主要的还是学习基础知识,如果你接触的项目够多的话,你会在实际的项目当中,获得实际的一些和业务、技术结合的经验,一年的话,最开始还是要从基础知识开始学 -
最大连接数1000,高并发指多大的活跃连接数?最大连接数是 1000 的话,根据 rds 的规格来说的话,还是比较低的。在高并发的情况下,指多大的活跃连接数?
A:活跃连接数,和 CPU 的核数是相关的,建议将最大活跃连接数不超过 CPU 核数 3 ~ 4,这个时候它的性能是比较高的。经常有用户会混淆“最大连接数”和“活跃会话数”这两个概念,最大连接数是指你的应用 应用连接池 * 实例上有多少个 DB,不超过最大的连接数的数量(这句话不太好整理),活跃会话数是指正在干活的数量,这个数量不是越多越好,我们要保证活跃会话要尽可能少,这样的话,mysql 才能提供最高的一个性能(理解各种连接数:https://developer.aliyun.com/article/683460) -
Mysql 中分表时,需要组合表查询时,如何做到高效?
A:是不是想问多维查询的概念啊?通常分表了以后。。。(中断,调试了一下连麦)mysql 在分表时,如何做到组合表查询,neng zuodao 高效,其实对于一张单表上面来说的话,它比较容易控制,比如说有主键、唯一键,在一张表上就不会出现,和其他表的关联,就不说了,如果一张表有超过1亿条的记录,就要考虑分库分表了,在分库分表的时候,如果两张表都超过一亿,这位同学,是不是想问多维查询的概念啊?如果想避免多维查询的话,这个时候还是要做数据冗余的,不是说数据表设计符合三范式越好,如果分库分表了以后,尽量还是要避免组合表的查询,特别是在分裤分表了之后,避免不了的话,那两个表join的时候,在关联的字段上面还是要建索引的。在两个表查询的时候,如果查询关联字段不太多的话,还是要做适当的字段冗余)。还有一个巧思是说,比如淘宝系统买家库和卖家库,因为只能按照一个维度来分表,如果按买家分表,但是按照卖家来查询,其实是用不上分库分表的字段,如果你是要用卖家的数据的话,它其实有几种方式,一种方式是做数据冗余,还有另一种方式是在现有表的基础上,相当于是存一个映射的表,相当于你还是要做数据冗余,但是数据冗余是用的不同的的方式,你可以全量地把买家表的数据同步到卖家表,它的数据是一样的(买家表的数据和卖家表一样),只不过你是以另外一种维度(卖家)来分表,这以空间换时间的概念;另一种方式就是,你可以没有,另外一个以卖家维度分表的那一份完整的冗余数据,但是你可以冗余它的 ID,在现有表的基础上,只需要买家表和卖家表对应的id就可以了,这是一个比较轻量级的数据冗余,如果要是用 drds 的话,可以用全局二级索引,我刚才说的那个概念其实也类似于全局二级索引,drds 里面是有这个概念的,你在 drds 创建索引的时候,官方文档是有的。(Polar-X 2.0的全局二级索引 https://help.aliyun.com/document_detail/182180.html?spm=a2c4g.11186623.2.2.1bb148c1p28A4b ;) -
Mysql 5.7 使用 MHA 无损复制,是否有丢数据的可能?
A:还是要看 5.7 使用的架构,三节点的企业版本,双节点的开源社区版本,如果是双节点,以双1的参数(innodb_flush_log_at_trx_commit=,sync_binlog=1)启动的话,原生的社区版是有丢一个事务(数据)的可能的,如果是用 rds 企业版或者金融版,这种的话是不会丢数据的。 -
Mysql 中单表大约一亿行数据,只有首列(自增列)为主键,这种设计是因为高并发吗?高并发在表设计上有哪些需要注意呢?
A:如果只有自增的列为主键,这种方式,如果是只有自增的列作为主键,是有助于高并发的,但又不完全是因为这个。还有哪几种可能会影响高并发的,最主要是内存的缓存命中率,就是 buffer pool 的命中率,如何才能在有限的 buffer pool 里面,存储足够多的数据,那就需要我们在数据库设计的时候注意,因为 buffer pool 里面缓存了索引和数据,buffer pool 的命中率是一个方面,还有一个方面,是在磁盘空间里面,mysql 的 innodb 表是索引组织表,如果是换做一个字符串为主键的话,相当于每个二级索引上都要挂一个这样的叶子结点,不管是它的磁盘空间的使用会增长,buffer pool 里面存储的数据并不是那么多。首列作为主键只是一个参考,我们需要从那几个方面去考虑高并发,最主要的还是要考虑缓存命中率,还有就是底层的数据结构,无论是做查找的时候,还有是在缓存命中率的时候,是否有助于...。为什么会涉及缓存,一级一级来,刚才提到过的 redis,其实也是提升缓存的命中率,对于mysql 来说,buffer pool 也是一个缓存,内存的命中率,怎样才能提升内存的命中率,也是从设计的时候考虑的一个问题。(buffer pool 的大小是可以配置的,内存空间在启动的时候立即分配完成了,老师所说的更多的数据,有时候需要按照更多的记录之类的去理解) -
Mysql 的读写锁怎么使用更好?读写锁的使用场景?
A:如果是单个语句来查询的话,数据库内部自己就控制了,对于应用来说,就不用单独来控制,如果涉及到事务,比如事务,我见过事务最多的是,一个事务里面有一千条语句,那在写事务的时候就要注意了,特别是在核心的事务里面,特别是在减库存的场景里面,你的行锁的释放时间和事务的释放时间是有关系的,我们在使用事务的时候,还是要尽量地减少行锁持有的时间,如果事务里面有读的话,如果业务上允许的话,把它移到外面,尽量地使这个事务足够的少,这个就是事务里面的控制。 -
高并发的时候,频繁 crud,容易读到旧数据应该怎么办?
A:对于数据库来说,底层的 MVCC 已经保证了数据一致性,你问的应该是缓存里面,比如 redis、memcache,从缓存读到旧数据应该怎么办?基于这个问题,我们还是要基于实际的应用场景出发,比如减库存,涉及到交易这种场景的话,以哪个(数据)为准?以缓存的为准,然后把它同步到数据库里面;还是以数据库里面的数据为准,到数据库执行的时候,还是要做一个判断的,如果是想要严格一点的话,还是要以数据库为准;如果要是以数据库为准的话,相当于是你从缓存里面读到既有的数据,你的缓存怎样才能保证100%命中?群里同学也有提到说,redis 那个链路更新的延迟,我们可以算一下,如果要是用这种方式的话(详情见 PPT 17页),相当于是 rds 写 binlog,再同步到 redis 的话,这个可以控制在百毫秒左右,一方面是,db 在返回的时候,我么有 retina 那个补丁,redis 返回了之后,应用程序可以直接拿这个更新 redis,下游链路并不是每次更新 redis 都成功,我们还有一个数据补偿的任务,可以通过 binlog 这种方式,实时地更新 redis 这个链路,这个并不是在几秒,而是在百毫秒内,可以把这个缓存给更新掉,这样的话,增删改查的数据,就是在百毫秒内,redis 和 db 的数据,控制是最新的。 -
大流量的情况 MGR,如何保证从库数据的实时性,老师您开始给出的流量峰值数据库用的什么架构?
A:MGR 的内容见第一个课。峰值数据库的架构有两种,一个是用rds 的分库分表;还有一个是,比较小的用户的话,单个的 rds 就可以支撑。 -
SSD 盘下参数 innodb_io_capacity 建议设置多大?
A:根据不同的 SSD 盘的性能来决定的,对于 rds 来说,不同的实例,io_capacity 是不一样的。自建的话,尽量不要超过盘的...,就要看对物理机分割方法,比如一个物理机上面,分割成很多个实例,是把 io_capacity 严格地区分?还是要尽量用物理机的性能?还是要看物理机资源隔离的方式。总的来说,同一个物理机上所有实例 io_capacity 的总和,不要超过物理机的 iops 的性能,比如说,物理机上所有实例都严格地隔离,一共有 1w 个的 io_capacity,四个实例,这个 io_capacity 要如何划分,均分?还是不限制,让它充分地使用物理机的 io_capacity,这些都是有关系的。 -
5.7 在使用过程中,占用内存会逐渐增大,调整思路是怎样的?
A:如果是内存逐渐增大的话,不排除某些版本存在内存泄漏的可能性,这种还是要持续观察,内存逐渐扩大,有几种可能性,比如表里面有 table open cache,不建议设置过大,使用过程中,哪些会涉及到内存增大的几种情况,就要看一下这些语句,比如说会话里面的几个,就是它的变量,设置 buffer pool 的时候,基本上上限就设置为 75% 这样的一个值,其他几个变量,就是语句里面的会话,比如 join buffer,和会话相关的变量,语句里面是不是有超大的使用内存的情况?刚才几个问题,和 ppt 没有多大关系,就没有演示ppt。PPT 20页中展示的,刚刚提到和内存相关的几个参数,innodb_buffer_pool_instance 是全局的,和会话相关的 join_buffer_stats 和 sort buffer,看是不是有 order by、group by 这样一系列的、会用到内存的几种情况,还要再看刚才提到的 table open cache 是不是设置的比较大,如果设置的比较大的话,就调小一点,这种就是要来回调,来回观察,不断看它调的效果。(参数调优的内容详情见 PPT 20页) -
如何扩展并行写,除了分表还有别的方法吗?
A:并行写,有几种提升写的性能的方法,比如你可不可以把它,把这些请求先存在应用的机器上,然后再批量地刷到数据库里面,这也是一种方法,就是把小批量(这里应该是口误)的请求换成批量的请求,小的一条条的,单条的请求,在应用端先存起来,再批量地刷到 db,这是一种方法,就不一定要分表;还有另外一种情况,就是像我们的 polar db 一样,把底层的存储,给它并行,这样的话也是一种方法。 -
阿里云售卖 AliSQL 吗?我没找到,还是要自己来搭建?
A:售卖的,alisql 有一部分是开源的,在社区都可以找到开源的源代码,现在售卖的 rds 的 mysql 里面,已经包含了 alisql 的特性,比如说刚才提到的库存和线程池,这些补丁都是其中这一,我们写了十多个补丁,然后你都可以用起来。(详情见 PPT 24页) -
能不能讲讲阿里的系统架构?
A:阿里做双十一的一个主要步骤,他的架构其实和阿里云官网上售卖是一样的,当单个实例不足以支撑的时候,可以用 drds ,也可以升级成 polardb。我们内部也是用了 das(详情见 PPT 12页) 和 dms,我们都是用的,基本上,我们是把内部我们用得很不错的补丁和场景,这些我们都是经过双十一验证过的,我们才把它们放到阿里云上售卖,这个和我们用的系统的架构是类似的。 -
热点数据更新具体要怎么做避免死锁之类的问题?
A:热点数据更新和死锁是两个问题。热点更新的方法已经介绍了,而且性能的提升可以看到(PPT 25页)。避免死锁之类的问题,要分析一下 死锁产生的几种情况,就加锁的顺序,无论是同一个表里面,同一个页里面加锁的顺序,两个不同表里面加锁的顺序,出现相互的索引,这种情况才会出现死锁,热点更新和死锁并没有直接的关系,这还是要分成两个情况来看。 -
能讲讲 rds sql 限流的实现原理不?
A:在 sql 解析的时候,捕获你设置的,das 的限流只是界面上的一个功能(PPT 36页),底层是需要内核来支持的,这个是内部双十一场景遇到的,觉得对大家比较有用,确实很多用户反馈说比较实用。它这个原理是,我们捕获到 sql 限流,是没有实际会话对,这里面在 show processlist 非常繁忙的情况,有大的 sql 的话,就可以捞到,就是可以设置限流,设置一系列关键字,在 server 层解析到关键字之后,设置并发,关键字匹配上了之后,就可以根据这个限流了,实现上其实是比较简单的,在 sql 解析层做的。 -
请问监控数据库字段变化的 sdk 框架有什么推荐?
A:ibetas 这种吗? -
热点数据更新从 rds 到 redis 是插件还是接口?
A:是想问 redis 怎样才能保证缓存的命中率,用的是 dts 数据订阅的一个功能,接收 binlog,通过 dts 订阅的一个组件,更新到 redis 里面,可以理解为一个插件。 -
rds redis 数据怎么保持一致性呀?
A:传统的缓存和数据库更新的几种模式:读缓存失效 + 写缓存失效。读缓存失效就是从缓存读不到数据,这个缓存就标记为失效;写缓存失效。如果想保证缓存命中率的话,因为 redis 如果要是撑不住的话,这个实例(口误?流量)打到 rds,也是撑不住的,这个情况的话,就尽量保证 redis 的缓存命中率,曾经历史上,也发生过机器,redis 缓存不命中,直接就把 DB 打挂的情况,就是有出现过,所以后面我们才出了这样一个保证缓存命中率的方案,如果要是频繁地更新的话,对于一般的设计架构,它是保证不了,特别是双十一库存更新这样一个场景,频繁写,保证不了缓存命中率 100% 的,我们是怎样做到的,就是刚才提到的方法,这就是一个非常好的小巧思。 -
Redis 会自动失效吗?
A:这个设置的自动失效,和用户主动更新,频繁写的情况下,失效的事其实没有可比性。用户频繁写的话,用刚才被动的方式,无论是读还是写,还是失效的时间,都是不能保证缓存命中率 100%,如果要是设置失效时间来,它还是会把流量打到DB的,我们设计这种模式,保证缓存命中率 100% 的这种架构,就是为了保证在 redis 不命中的情况下,不要把 redis 打挂。 -
请问之前有关于 5.6、5.7、8.0 性能的测试,那稳定性呢?
A:从 oracle 迁移到 mysql 能否直接上 8.0?都是经过了一系列的稳定性测试,才把它放到阿里云上面的。迁移到 mysql,能否直接上 8.0?从 oracle 直接迁移到 mysql 8.0,还是要验证一下的,直接迁移还是要看语法兼容不兼容这一系列的,比如说 oracle 里面的组件、ser,这些在 mysql 里面是没有的,还有一系列的,你在 orcacle 里面有没有存储过程这样一类的,相当于数据库的异构,不建议直接迁,还是要经过详细的评估,还是是要看功能、语法,语法兼容不兼容,msql 在视图的方面支持得也不太好的,很多 oracle 的用户都习惯用存储过程和视图的,我们不建议把存储过程写到 mysql 里面的,这种是要经过改造的,直接上的话,是有一定风险的。 -
mysql分表后,如何对所有子表的联合数据保证高效查询?
A:联合数据是什么含义,分表后,如果不涉及多维查询的话,和其他事一样的,所有子表的查询语句,和单表没有区别,你在问的是有数据聚合的情况,count、sum、group by,你是问的这种吗? -
只用 rds 不用 drds,可以做到高并发吗?
A:可以,自己可以设置,甚至开发一个 drds 的中间件,这是一种情况,或者是用其他的代理,如果要是用其他的代理,就要验证多维查询,所有子表的联合数据保证,代理在和 rds 交互的时候,网络延迟是一个要考虑的方面,每一个 rds 都是性能上限的,单个 rds,如果设计得足够充分的话,是可以把单个 rds 的性能做到充分的高,单个 rds 的性能,我们做了基准的测试的,最高是可以达到十多万的(PPT 10页),16C64G不是最大规格,可以做到 6W,还有独享物理机(形态)的,是可以做到十多万的,主要看系统的峰值有没有超过单个 rds 性能的峰值,整个数据库的架构设计,还有真个系统的架构设计,能否充分地把数据库的性能发挥到最大化,这种都是有关系的,后面再详细交流。因为之前见过有用户,数据库设计中,索引设计得不是很合理,就不能充分利用数据库的性能,应用和 db 交互的架构,刚才提到的库存里面,事务里面语句的顺序,都是和这个有关系的。所以要想做到高性能,不是一个点就可以做到的,需要从整个架构,性能测试,数据库的测试和缓存的设计,都是有关系的,甚至一个事务里面语句的顺序对会影响到你的性能。 -
redis内存数据有限 读的数据容量有限制吧?
A:redis 也是有规格限制的 -
有推荐的分库架构吗?
A:对于阿里云来说,最常见的就是 drds,现在叫做 polar-X 2.0。 -
秒杀场景下,服务器在北京,新疆 和 北京同时抢,怎么保证两边延迟的公平性和防止超卖?
A:就要看你这个数据是一份还是多份,如果要是一份的话,就没有必要考虑北京和新疆的这样一个问题,服务器在北京,新疆 和 北京同时抢,那就要看最后哪个请求先到 db,不一定北京的请求先到北京。北京的应用的请求,因为你数据库的服务器是在北京,看这两个谁先在数据库里面,数据库里面它也不能保证,不一定能保证是完全的按照先到先得得来的,两边不一定能保证延迟的公平性,防超卖,是库存的一个逻辑,为什么会出现超卖,在业务场景里面,出现超卖就是,实际售出的数量,比商家库存的数量要多。可以网上搜一下,2012 年我们的双十一,出现过超卖的问题,后面经过一系列的改造,才把这个超卖,变成 0 超卖的,这个是一个小专利,可以单独交流一下,解释起来,时间需要比较久,简单来说,防止减下来的数量,实际减的时候,不要超过商家设置的库存的数量就 ok 了。 -
为什么mysql不建议使用存储过程?
A:mysql 在这个方面做的不太好,大多数用户一上云的情况下,都会有考虑下云的可能。有的用户在实际定位问题的时候,往往都是先从应用端开始定位,有的时候会忽略存储过程这样一个逻辑存在,这种从应用的维护和设计上面来讲,不建议使用存储过程。 -
上亿数据并且有聚合的情况?
A:具体还是要看业务的需求量,如果在上亿的情况下,做了分库分表,做了多点存储,不管使用哪些架构,只要是把这些数据给分开来,再做聚合的时候。业内比较常见的是,看业务请求是轻量级的,还是比较重的。如果是比较重的业务聚合的情况下的话,推荐使用 adb,它会把请求下发到各个节点,各个节点是使用 MPP的架构;如果是有轻量级的聚合的情况下,polar-X 2.0 也就是 drds 也是可以胜任的,具体要看业务的请求,数据量,以及对时间的要求是多少。 -
Mysql有个表特别大,40多G,请问单表大小多少保证性能好一些(有大字段)?
A:就是按照经验值来说,500W,是按照存储的行数来说,是指 500W 行,还是要看我们的主键设计以及业务对数据库的性能要求,就是按照经验值是按照行(的维度),那么按照大小来说的话,单表不要超过 10G。有大字段的话,如果是要保证性能更好一些,比如说我们刚刚提到的写库存的场景,我们就要保证,对于 innodb 来说,它写 binlog 是全量的字段更新,而且 binlog 还要再传到备实例上面,要考虑大字段是不是会被经常更新的,如果有,就是需要把大字段给隔离出来的。 -
在刚才读redis 写mysql的场景 mysql的数据库容量也受限制了吧?因为mysql存的太多会撑爆redis?
A:并不是把 mysql 所有的数据都存到 redis 里面,把热数据存到 redis 里面就可以了。我们是要提前算一下的,我们算容量的时候,不止是要算数据库的容量的时候,还要算 redis 的容量。算 redis 容量的时候,我们也是要算一下它是有多少热数据,然后这个量是有多少,也是要充分地扩容 mysql 的量的。 -
如果有多个大字段,一般设计表的时候是把大字段放一个表还是分散的好?
A:如果这个表经常要更删改查的话,而大字段又不经常修改的话,那你就要把它分开;如果整个表,包括这个大字段修改都不是频繁更新,那你把它们放在一起也是 ok 的。 -
谁先到这个应该是自己的应用的决定的吧?
A:应用决定的吧。 -
数据库全量备份会影响写操作,有什么好的方式进行数据备份吗?
A:rds 的备份,一般是在备库上执行的,所以这个也不会影响到写操作。不得不在主实例上备份的时候,这种情况下才可能会影响。数据库全量备份,有好几种备份工具:一个是开源的 Xtrabackup,一个是用 dbs,就是数据先用逻辑备份,备份出来一份全量数据,再用增量 binlog 的方式同步到 oos,这种也是一种方式。如果你要是想不影响写操作的情况,尽量地保证在数据库备库上备份的时间。还有一种,备份可能会失效,就是主备延迟,在数据库设计的时候,和请求量都是有关系的,就不仅是备份工具/方式的问题。如果保证主备同步不中断,没有延迟,备库的备份都是有效的,这样的情况下,就不会到主库,主实例上去做备份,就不会影响到写操作。 -
RDS主备异常的时候会在主库备份的呀?
A:rds 异常的时候,是会在主库备份的,这种概率非常低,什么时候会影响写,就是在 flush 的时候会卡一下。如果要是用 Xtrabackup,在主库备份的时候,是会卡一下的,如果是用 Xtrabackup 的话,没有比较好的方式。另外一种备份方式dbs,经常把全量数据、增量数据同步,这种方式是不会影响的,因为它先是用逻辑在同步 binlog,这种不会suo。 -
Double Sync 在大批量数据操作的时候,IO线程容易down掉,奇怪,新版本RDS还有这问题吗?
A:这个情况,我值班的时候没有遇到过,这个情况发生的概率比较低,如果有的话,我们也是有修复机制的:stop slave + start slave。 -
还有percona 的xback?
A:对,这种备份工具也有。 -
rds和polar db,ocean base区别?
A:价格看起来差蛮多?这种架构我不是很了解,你们可以看看官网上的对比,sa 或者是商务经理,跟他们问一下价格上面的问题。 -
监听数据的修改 sdk,有哪些 sdk,能具体说一下吗?
A:你是说数据库增删改查的那个吗,其实就是 dts 的数据订阅。
39.由于开发不规范,导致有的sql在主库执行没问题,但是在从库回放sql的时候回放失败(比如说更新的条件多了乱七八糟的东西 WHERE id='430753 `wget http:// 169.254 ) 导致主从同步失败,一般我是告诉开发他们这个sql里有开发不规范的问题,他那边处理完了 我这个才能解决问题。本地自建的主从mysql,主从同步失败了 失败报错是update 语句后面where条件问题,这个比较被动,请问老师还有别的方法吗?
A:如果是sql线程回放中断,你的主从同步设置的是什么模式?statement?mix?row?设置row没问题,statement?mix?不严谨