MySQL之复制策略与分库分表具体实现

1.业务拆分

业务发展的初期为了快速迭代一半采用集中式的架构,随着业务的发展,使系统变得越来越复杂和难以维护,开发效率越来越低,并且系统的资源消耗也越来越大,通过硬件提升性能的成本也越来越高,因此业务拆分难以避免。


image.png

在拆分后,每一块业务都使用不同的数据库来进行存储,前端的业务访问不同的数据库,这样原本依赖数据库的服务,变成了四个库一个承担压力,吞吐能力自然就提高了。

同时还有一个好处,原来一次简单修改,工程启动和部署需要很多时间,还要解决测试分支合并等等诸多问题,随着拆分后,单个系统的复杂度降低了,减轻了应用分支开发带来的合并冲突解决的麻烦,大大提高了开发测试的效率,也提升了系统稳定性。

2.复制策略

架构变化的同时,业务也在不断地发展,可能很快就会发现,随着访问量地不端增加,拆分后某个库地压力会越来越大,马上就要达到系统能力地瓶颈。这时候可以采用MYSQL地replication(复制策略)来对系统进行扩展。

也就是主从复制策略,将一台MYSQL数据库分为两台,一台专门作为写入,一台负责读。同时写入地数据库,需要将数据同步到读数据库中,于是复制策略地作用就显现出来了。前端应用通过MYSQL集群中地任意一台读服务器,每台数据库服务器地负载就会大大降低,从而提高整个系统地负载能力,达到扩展地目的。

MySQL 的M aster与Slave之间数据同步的过程I

如图所示:

实现如下:
要实现数据库的复制,就需要开启Master服务器端的Binary log,数据复制的过程实际上就是Slave从master获取binary log, 然后再在本地镜像的执行日志中记录的操作。由于复制过程是异步的,因此Master和Slave之间的数据有可能存在延迟的现象,此时只能够保证数据最终的一 致性。

MySQL的复制可以基于一 条语句 (statem entlevel), 也可以基千一 条记录 Crow level)。通过row level的复制,可以不记录执行的SQL语句相关联的上下文信息,只需要记录数据变更的内容即可。但由于每行的变更都会被记录,这样可能会产生大量的日志内容,而使用statement level则只是记录修改数据的SQL语句,减少了binary log的日志量,节约了I/0成本。但是,为了让SQL语句在Slave端也能够正确地执行,它还需要记录SQL执行的上下文信息,以保证所有语句在Slave端执行时能够得到在Master端执行时的相同结果。

一般而言,大多数站点的读数据库操作要比写数据库操作更为密集。如果读的压力较大,还可以通过新增Slave来进行系统的扩展,因此,Master-Slave的架构能够显著地减轻前面所提到的单库读的压力。


image.png

存在的问题

单点故障,当Master宥机时,系统将无法弓入,而在某些特定的场景下,也可能需要Master停机,以便进行系统维护、优化或者升级。同样的道理,Master停机将导致整个系统都无法写入,直到Master恢复,大部分情况下这显然是难以接受的。

解决方式:

使用Dual-Master架构,所谓的Dual Master, 实际上就是两台MySQL服务器互相将对方作为自己的Master, 自己作为对方的Slave, 这样任何一 台服务器上的数据变更,都会通过 M ySQ L 的复制机制同步到另一台服务器。

这样不会导致两台互为Master的MySQL之间循环复制吗?当然不会,这是由于MySQL在记录Binary log日志时,记录了当前的server-id, server-id 在我们配置MySQL复制时就已经设置好了。 一 旦有了server-id, MySQL就很容易判断最初的写入是在哪台服务器上发生的,MySQL不会将复制所产生的变更记录到Binary log, 这样就避免了服务器间数据的循环复制。

当然,我们搭建Dual-Master架构,并不是为了让两个Master能够同时提供写入服务,这样会导致很多问题。举例来说,假如MasterA与Master B几乎同时对一 条数据进行了更新,对Master A的更新比对Master B的更新早,当对MasterA的更新最终被同步到Master B时,老版本的数据将会把版本更新的数据覆盖,并且不会抛出任何异常,从而导致数据不一 致的现象发生。在通常情况下,我们仅开启一 台M aster的写入,另一 台M aster仅仅stand by或者作为读库开放,这样可以避免数据写入的冲突,防止数据不一 致的情况发生。

如果Msater需要进行停机维护,可以按照以下的步骤进行Mater的切换操作:

(1) 停止当前Master的所有写入操作。
(2) 在Master上执行set global read_ only= 1, 同时更新MySQL配置文件中相应的配置,避免重启时失效。
(3) 在Master上执行show Master status, 以记录Binary log坐标。
(4) 使用Master上的Binary log坐标,在stand by的Master上执行select Master _pos _ wa项),等待stand by Master的Binary log跟上Master的Binary log。
(5) 在stand by Master开启写入时,设置read_only=O。
(6) 修改应用程序的配置,使其写入到新的Master。

假如Master意外宅机,处理过程要稍微复杂一 点,因为此时M aster与stand by Master上的数据并不一 定同步,需要将 M aster上没有同步到stand by Master的Binary log复制到Master上进行replay, 直到stand by Master与原Master上的Binary log同步,才能够开启写入:否则,这一 部分不同步的数据就有可能导致数据不一 致。

分表与分库

对千大型的互联网应用来说,数据库单表的记录行数可能达到千万级别甚至是亿级,并且数据库面临着极高的并发访问。采用Master-Slave复制模式的MySQL架构,只能够对数据库的读进行扩展,而对数据的写入操作还是集中在Master上,并且单个Master挂载的Slave也不可能无限制多,Slave的数量受到Master能力和负载的限制。因此,需要对数据库的吞吐能力进行进一 步的扩展,以满足高并发访问与海摄数据存储的需要。

对于访问极为频繁且数据量巨大的单表来说,我们首先要做的就是减少单表的记录条数,以便减少数据查询所需要的时间,提高数据库的吞吐,这就是所谓的分表。在分表之前,首先需要选择适当的分表策略,使得数据能够较为均衡地分布到多张表中,并且不影响正常的查询。

关于分表策略,对于互联网企业来说,大部分数据都是与用户关联的,因此用户id是最常用的分表手段。因为大部分查询都需要带上用户的id,这样既不影响查询,又能够是数据比较均衡的分布到各个表中,有时还能优化查询的效率。


image.png

假设有一张记录用户购买信息的订单表order,由于order表记录条数太多,将被拆分成256张表13。拆分的记录根据user_id%256取得对应的表进行存储,前台应用则根据对应的user_id%256, 找到对应订单存储的表进行访问。这样一来,userid便成为一个必需的查询条件,否则将会由于无法定位数据存储的表而无法对数据进行访问。

假设user表的结构如下:
create table order( 
order_id bigint(20) primary key auto_increment, user_id bigint(20), 
user_nick varchar(50), 
auction_id bigint(20), 
auction_title bigint(20), price bigint(20), auction_cat varchar(200), seller_id bigint(20), seller_nick varchar(SO) 
) ; 

那么分表以后,假设 user_id=257, 并且 auction_id= 100, 需要根据 auction_id 来查询对应的订单信息,则对应的SQL语句如下:
select* from order_l where user_id = 257 and action_id = 100;
其中, order_l根据 257% 256 计算得出,表示分表之后的第 1张order表。

分库

分表能够解决单表数据量过大带来的查询效率下降的问题,但是,却无法给数据库的并发处理能力带来质的提升。面对高并发的读写访问,当数据库 M aster服务器无法承载写操作压力时,不管如何扩展 Slave 服务器,此时都没有意义了。因此,我们必须换一 种思路,对数据库进行拆分,从而提高数据库写入能力,这就是所谓的分库。

与分表策略相似,分库也可以采用通过一 个关键字段取模的方式,来对数据访问进行路由。
MySQL 分库策略

还是之前的订单表,假设 user_id 字段的值为257, 将原有的单库分为 256 个库,那么应程序对数据库的访问请求将被路由到第 1个库 (257% 256=1)。

分库分表

有时数据库可能既面临着高并发访问的压力,又需要面对海量数据的存储问题,这时需要对数据库即采用分库策略,又采用分表策略,以便同时扩展系统的并发处理能力,以及提升单表的查询性能,这就是所谓的分库分表。

分库分表的策略比前面的仅分库或者仅分表的策略要更为复杂,一种分库分表的路由策略如下:
• 中间变量=user_id%(库数量*每个库的表数量);
• 库=取整(中间变量/每个库的表数量);
• 表=中间变量%每个库的表数量。
同样采用user_id作为路由字段,首先使用user_id对库数量X每个库表的数量取模,得到一个中间变量:然后使用中间变量除以每个库表的数量,取整,便得到对应的库;而中间变量对每个库表的数量取模,即得到对应的表。


MySQL分库分表策略

假设将原来的单库单表order拆分成256个库,每个库包含1024个表,那么按照前面所提到的路由策略,对千user_id=262145的访问,路由的计算过程如下:
• 中间变量=262145%(256X 1024) =l;
• 库=取整C1/1024) =0:
表=1%1024=1。

这意味着,对于user_id=262 l 4 5的订单记录的查询和修改,将被路由到第0个库的第1个表中执行。
数据库经过业务拆分及分库分表之后,虽然查询性能和并发处理能力提高了,但也会带来一系列的问题。比如,原本跨表的事务上升为分布式事务;由于记录被切分到不同的库与不同的表当中,难以进行多表关联查询,并且不能不指定路由字段对数据进行查询。分库分表以后,如果需要对系统进行进一 步扩容(路由策略变更),将变得非常不方便,需要重新进行数据迁移。

整理不易,如果喜欢,帮我点个赞。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容