数据库系列(五)之 mysql的伸缩性

摘要:
MySQL一直是中国使用最多的数据库,在国外也排名前三。MySQL是一个高性能的开源数据库。这里我们以最流行的数据库MySQL为例来讨论可伸缩性。数据分区从MySQL 5.1开始,支持表级数据分区。此数据分区不需要在应用程序代码中修改。它只需要在MySQL中配置。在中间表模式下,首先插入数据时,将此数据ID与数据库之间的映射关系保存在中间数据库中,然后将其插入到相应的数据库中。

      这篇文章,主要讲述mysql的伸缩性。在国内mysql一直都是使用得最多的数据库,在国外也排名前三。mysql是一款开源的、性能较高的数据库。

      伸缩性是指在软件设计中,软件(数据库、应用程序)通过特定的配置或升级,可以进行横向或纵向扩展,来达到软件适应越来越多用户访问的目的。数据库达到一定瓶颈,需要考虑伸缩性,这是大部分软件设计人员避免不了的事情。

      在移动互联网时代,人人可用手机访问你的APP、网站应用,没有数据库的伸缩,不可能支持那么多的用户量的访问。还有一种场景,数据存储量极大的也考虑伸缩性,如防伪查询、地图软件等。

      这里以最流行的数据库mysql为例子,讨论伸缩性。

 

数据库纵向扩展

      在云时代以前,一般的企业部署应用都是一台机器里有应用+数据库。

clipboard

      这种做法在20世纪一直流行至今,很多内部应用也一直这样运行着十多年。在互联网应用中,数据量稍大的话很快达到瓶颈。

为何很快达到瓶颈?               

      第一,应用软件与数据库在同一台机器,应用与数据库都需要使用到机器的CPU、内存、磁盘IO、磁盘容量。它们两个无时无刻都在争抢。

      第二,价钱达到瓶颈。在第一种情况下,你很容易提高系统的访问速度,提高机器(或VM)的配置。一开始提高很容易,但是提高到一个标准后机器的价格不是一般企业能承受得了。(大约在32核256GB内存)

那么在这种情况下怎么提高扩展性呢?           

      答案是分离应用与数据库。应用部署在一台机器,数据库部署在另外的机器。

clipboard[1]

      再下一步怎么扩展呢?这里不讨论应用的伸缩性。应用的伸缩性大致是部署多个实例,实例上层装个反代或负载均衡。下面着重讨论数据库的伸缩性。

 

Mysql数据库的伸缩性

      对于伸缩性,有三种方式:数据分片、应用拆分、数据备份。Mysql也一样,首先是数据备份。

主从                                            

      数据备份这里体现的是添加主从的方式。即将数据库分成两个数据库,用于读写分离,一般主库用于写,从库用于读。

      当数据进入时,会先从把数据插入主库,然后把相应的数据操作记录到日志上。从库会从主动检查主库日志,并且把新添加的数据同步到从库。流程如下图所示。

clipboard[2]

      也可以在主库进行读写,从库进行读。这是主库的读操作不会太频繁,主要读压力会给予从库。 也有一种是从库主要用来备份,不做任何对外处理,即读写压力都在主库,这种只是纯备份。

      上面无论是主写从读,还是主写读从读,都会给数据库减压。不知道你发现没有,主库进行写操作的时候,把数据备份到从库需要一个时间段。而如果在你写入主库时,马上有人访问从库,这个数据如果还在‘备份阶段’,那么会查找不到此数据。这个是分布式系统的一致性问题。

      主从的数据库是弱一致性,也叫最终一致性。即数据最终都会保持一致,在写数据时有那么一瞬间数据会不一致。这种有上面解决办法吗?一是尽快保持主从库都在同一个局域网中,快速备份数据,尽量减少不一致。二是在程序层面,提供一个缓存层,即在主库写入数据后,再写入缓存(根据实际可以是几秒钟、几分钟)。再用户读时,先读缓存,再读数据库。

      在主从上,可以一主多从,多主多从,这些都根据实际业务情况而定。值得注意的是多主的时候,数据延迟要保证带来的侵害性。

数据分区                                               

      从mysql5.1开始,支持表级别的数据分区。此数据分区无需在应用代码做任何修改,只需要在mysql中配置即可。此分区方式是物理级别的分区,它会把同一个表通过指定的算法分离存储到不同位置,最终达到提高表的量级的目的。更深一层说,一个表的数据通过物理分区分离到数个不同的物理区域,每个分区都是独立的。表分区有4种方式,与下面讨论的分表算法一致。

分库分表                                   

      再进一步,就是分库分表了。先讨论一下分库。

      分库很简单,把不同的表分到不同的库,或者把相同的表不同的数据分到不同的库。

第一,不同的表分到不同的库。

      把主库里的表分离出来,分到各个不同业务逻辑上的库。例如主库上分别有:user表、权限表、订单表、购物车表。把库物理分离表,分成用户库:user表、权限表。购物车库:订单表、购物车表。这种分离根据业务拆分很简便,代码修改很少,但是单个表的数据量大时会到瓶颈。如下图展示。

clipboard[3]

第二,相同的表不同的数据分到不同的库。

      这种与分表挂钩,即把数据分离到不同的库,不同库的表都一致。例如主库上分别有:user表、权限表、订单表、购物车表。现在分两个库:库A与库B。库AB的表与主库一致,但数据分离。如库A保存北京用户的数据,库B保存广州用户的数据。如下图展示。

clipboard[4]

 

分表详解

      上述讲述分库的两种方式时,第二种方式涉及到分表。分表的算法为:中间表、求余取模、范围方式、一致性hash。

中间表方式                             

      首先插入数据时,在中间库中保存此条数据id与数据库的映射关系,再插入到对应的库中。如插入用户信息,数据有:用户id、用户名称。首先把数据插入到对应的数据库,如插入到主库A,数据有:用户id、用户名称。然后把数据插入到中间表中,数据有:用户id、数据库ip、数据库名称。

      那么在查询时,首先根据用户id查询中间表得到数据库相关信息(数据库A),再查询相应的数据库A得到用户数据:用户名称。如下图展示。

clipboard[5]

      这种方式好处在于容易分表。如果加库修改中间映射表即可。缺点在于多了一次数据库的读写操作。

求余取模方式                             

      求余取模即根据分区键(或主键等),对分区键进行统一的求余,余数为对应的数据库。这种方式也是使用得最广的方式,因为简单,并且一般企业一开始数据库数量会定好,长时间无需添加库。

      如目前有4台数据库,那么被除数时4。对分区键进行hash取整(如果s是整数则无需取hash),余数是0则在数据库A,余数是1则在数据库B,余数是2则在数据库C,余数是3则在数据库D。如下图所示。

clipboard[6]

      这种方式的有点在于简单,读写数据只需求余取模即可,较中间表方式性能较高。但是如果需要添加数据库的话,比较麻烦,需要迁移数据。

      例如如果要添加数据库,只能是4的整数倍。现在是4,那么被除数变成8,数据库也变成8台。如下图所示。

clipboard[7]

      切分后,还需要迁移数据。如

0%4=0,1%4=1,2%4=2,3%4=3,4%4=0,5%4=1,6%4=2,7%4=3。

0%8=0,1%8=1,2%8=2,3%8=3,4%8=4,5%8=5,6%8=6,7%8=7。

      所以,需要把余数处以8等于4-7之间的,迁移到对应的库E-F。

范围方式                                         

      范围方式是最好理解的方式。范围方式即取得分区键,对分区键进行范围处理,如果指定到某个范围区域,则数据指向到对应得数据库。如范围1-1000W到数据库A,范围1001W-2000W到数据库B,范围2001W-3000W到数据库C。如下图所示。

clipboard[8]

      此方式好处在于简单处理,增加数据库也不需要迁移数据。缺点在于数据太过于离散,可能最终导致查询慢,即所谓的热点问题。如一用户小明1月份购买了一个商品,插入了一条订单数据在库A,在下一个月,已经到了数据库E了,下个月购买的订单数据在库E。当这两条数据有联合查询或更新时,性能较低。

一致性hash方式                             

      在算法层面,一致性hash方式是目前最理想的方式。在hash取模时带来数据迁移问题,在范围方式带来热点数据问题,在中间表带来性能事务问题。有没有一种方式时这些方式的折中呢?一致性hash算法。

      一致性hash算法是求出服务器节点的hash值,将其配置在0~232的圆。然后采用同样的方法求出存储数据的hash值,并映射到相同的圆上。顺时针到最近的服务器,那么此数据存储在这个服务器中。

      例如有数据库A、B、C。数据1,2,3,4通过hash算法落在圆中。数据保存在顺时针最近的服务器。如数据1、5保存在服务器A,数据2保存在服务器B,数据3、4保存在服务器C。如下图所示。

clipboard[9]

      如果加一台服务器D,则通过算法看此服务器加在圆中的那里。如果在服务器A于C之间,则保存在服务器A的数据有一部分需要迁移到服务器D。如下图所示,数据5被迁移到服务器D。

clipboard[10]

 

总结

      综上,数据库的伸缩性首先是主从,然后是分区,最后是分库分表。其中主从是数据库软件支持的操作,应用程序修改得不多。分区是数据库表的分区,应用程序也无需改动,表通过算法分区到不同的物理分区。最后是分表分库,这2种通常是一并使用。分表分库包含了4种常见算法方式:中间表、求余取模、范围方式、一致性hash。

 

可以关注本人的公众号,多年经验的原创文章共享给大家。

数据库系列(五)之 mysql的伸缩性第12张

免责声明:文章转载自《数据库系列(五)之 mysql的伸缩性》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇C# 简单的区块链实现webpack学习笔记-2-file-loader 和 url-loader下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

sqlserver2017安装及连接过程中发现的问题

1、SSMS安装报错,如下图 根据搜索资料发现是防火墙的问题,关闭防火墙就行了。 2、连接用户时报错 这个是因为远程连接相关问题。 首先打开服务器远程连接: 其次点击: SqlServer配置管理器--点击MSSQLSERVER的协议--启用TCP/IP 最后新增入站规则端口1433 3、在数据库 'master' 中拒绝了 CREATE DATA...

无法登录oracle数据库--由于资源不足引起

  通过sqlplus以sysdba登录数据库时,出现了资源不足的错误(具体错误代码已经记不住了)。   首先应该观察一下系统中资源的一些限制参数。 [oracle@viti1 ~]$ cat /etc/security/limits.conf # /etc/security/limits.conf # #Each line describes a li...

Prometheus+Grafana监控mysql主从故障告警

因业务需求,mysql主从常常出现同步故障,故研究了Prometheus来做mysql主从同步状态监控报警。 1 Prometheus介绍 1.1什么是Prometheus? Prometheus是由SoundCloud开发的开源监控报警系统和时序列数据库(TSDB)。Prometheus使用Go语言开发,是Google BorgMon监控系统的开源版本。...

Navicat远程连接MySQL数据库

Navicat连接远程MySQL数据库 环境:Ubuntu 18.10 (GNU/Linux 4.18.0-13-generic x86_64)+Navicat 12.0.18(64-bit)-Premium Welcome to Ubuntu 18.10 (GNU/Linux 4.18.0-13-generic x86_64) * Documen...

3. mysql 索引命中规则及优化

1.什么是索引 “索引(在mysql中叫键 key),是存储引擎快速找到记录的一种数据结构。” --- 《高性能MySQL》,例如innodb引擎使用的就是B+树。 2.索引类型 命令:show index from table_name; 查看索引详情。 主键索引 PRIMARY KEY: 一种特殊的唯一索引,不允许为null,一般建表时会创建主键,若...

MySQL Error--Error Code

mysql error code(备忘)1005:创建表失败1006:创建数据库失败1007:数据库已存在,创建数据库失败1008:数据库不存在,删除数据库失败1009:不能删除数据库文件导致删除数据库失败1010:不能删除数据目录导致删除数据库失败1011:删除数据库文件失败1012:不能读取系统表中的记录1020:记录已被其他用户修改1021:硬盘剩余...