10分钟搞懂:亿级用户的分布式数据存储解决方案!

来源:IT进阶思维原创,转载请注明原出处

内容提供:李智慧,前阿里巴巴技术专家,《大型网站技术架构》作者

6月6日晚,林志玲与Akira公布婚讯、徐蔡坤祝福高考同学超常发挥,粉丝们百万的转发和点赞造成微博短暂宕机。

分布式数据库和分布式存储是分布式系统中难度最大、挑战最大,也是最容易出问题的地方。互联网公司只有解决分布式数据存储的问题,才能支撑更多次亿级用户的涌入。

接下来,你将花费十分钟掌握以下三方面内容:

1、MySQL复制:包括主从复制和主主复制;

2、数据分片:数据分片的原理、分片的方案、分片数据库的扩容;

3、数据库分布式部署的几种方案。

一、MySQL复制

1.MySQL的主从复制

MySQL的主从复制,就是将MySQL主数据库中的数据复制到从数据库中去。

主要目的是实现数据库读写分离,写操作访问主数据库,读操作访问从数据库,从而使数据库具有更强大的访问负载能力,支撑更多的用户访问。       

它的主要的复制原理是:当应用程序客户端发送一条更新命令到数据库的时候,数据库会把这条更新命令同步记录到Binlog中,然后由另外一个线程从Binlog中读取这条日志,然后通过远程通讯的方式将它复制到从服务器上面去,从服务器获得这条更新日志后,将其加入到自己的Relay log中,然后由另外一个SQL执行线程从Relay log中读取这条新的日志,并把它在本地的数据库中重新执行一遍。

这样当客户端应用程序执行一个update命令的时候,这个命令会在主数据库和从数据库上同步执行,从而实现了主数据库向从数据库的复制,让从数据库和主数据库保持一样的数据。

2.MySQL的一主多从复制

MySQL的主从复制是一种数据同步机制,除了可以将一个主数据库中的数据同步复制到一个从数据库上,还可以将一个主数据库上的数据同步复制到多个从数据库上,也就是所谓的MySQL的一主多从复制。

多个从数据库关联到主数据库后,将主数据库上的Binlog日志同步地复制到了多个从数据库上。通过执行日志,让每个从数据库的数据都和主数据库上的数据保持了一致。这里面的数据更新操作表示的是所有数据库的更新操作,除了不包括SELECT之类的查询读操作,其他的INSERT、DELETE、UPDATE这样的DML写操作,以及CREATE TABLE、DROPT ABLE、ALTER TABLE等DDL操作也都可以同步复制到从数据库上去。

3.一主多从复制的优点

一主多从复制有四大优点,分别是分摊负载、专机专用、便于冷备和高可用。 

a.分摊负载

将只读操作分布在多个从数据库上,从而将负载分摊到多台服务器上。

b.专机专用

可以针对不同类型的查询,使用不同的从服务器。

c.便于进行冷备

即使数据库进行了一主多从的复制,在一些极端的情况下。也可能会导致整个数据中心的数据服务器都丢失。所以通常说来很多公司会对数据做冷备,但是进行冷备的时候有一个困难点在于,数据库如果正在进行写操作,冷备的数据就可能不完整,数据文件可能处于损坏状态。使用一主多从的复制就就可以实现零停机时间的备份。只需要关闭数据的数据复制进程,文件就处于关闭状态了,然后进行数据文件拷贝,拷贝完成后再重新打开数据复制就可以了。

d.高可用

如果一台服务器宕机了,只要不发请求给这台服务器就不会出问题。当这台服务器恢复的时候,重新发请求到这台服务器。所以,在一主多从的情况下,某一台从服务器宕机不可用,对整个系统的影响是非常小的。

4.MySQL的主主复制

但是一主多从只能够实现从服务器上的这些优点,当主数据库宕机不可用的时候,数据依然是不能够写入的,因为数据不能够写入到从服务器上面去,从服务器是只读的。

为了解决主服务器的可用性问题,我们可以使用MySQL的主主复制方案。所谓的主主复制方案是指两台服务器都当作主服务器,任何一台服务器上收到的写操作都会复制到另一台服务器上。       

如上主主复制原理图,当客户端程序对主服务器A进行数据更新操作的时候,主服务器A会把更新操作写入到Binlog日志中。然后Binlog会将数据日志同步到主服务器B,写入到主服务器的Relay log中,然后执Relay log,获得Relay log中的更新日志,执行SQL操作写入到数据库服务器B的本地数据库中。B服务器上的更新也同样通过Binlog复制到了服务器A的Relay log中,然后通过Relay log将数据更新到服务器A中。

通过这种方式,服务器A或者B任何一台服务器收到了数据的写的操作都会同步更新到另一台服务器,实现了数据库主主复制。主主复制可以提高系统的写可用,实现写操作的高可用。

5.MySQL的主主失效恢复

使用MySQL服务器实现主主复制时,数据库服务器失效该如何应对?

正常情况下用户会写入到主服务器A中,然后数据从A复制到主服务器B上。当主服务器A失效的时候,写操作会被发送到主服务器B中去,数据从B服务器复制到A服务器。

主主失效的维护过程如下:

最开始的时候,所有的主服务器都可以正常使用,当主服务器A失效的时候,进入故障状态,应用程序检测到主服务器A失效,检测到这个失效可能需要几秒钟或者几分钟的时间,然后应用程序需要进行失效转移,将写操作发送到备份主服务器B上面去,将读操作发送到B服务器对应的从服务器上面去。

一段时间后故障结束,A服务器需要重建失效期间丢失的数据,也就是把自己当作从服务器从B服务器上面去同步数据。同步完成后系统才能恢复正常。这个时候B服务器是用户的主要访问服务器,A服务器当作备份服务器。

5.MySQL复制注意事项

使用MySQL进行主主复制的时候需要注意的事项如下:

a.不要对两个数据库同时进行数据写操作,因为这种情况会导致数据冲突。

b.复制只是增加了数据的读并发处理能力,并没有增加写并发的能力和系统存储能力。

c.更新数据表的结构会导致巨大的同步延迟。

需要更新表结构的操作,不要写入到到Binlog中,要关闭更新表结构的Binlog。如果要对表结构进行更新,应该由运维工程师DBA对所有主从数据库分别手工进行数据表结构的更新操作。

二、数据分片

数据复制只能提高数据读并发操作能力,并不能提高数据写操作并发的能力以及数据整个的存储容量,也就是并不能提高数据库总存储记录数。如果我们数据库的写操作也有大量的并发请求需要满足,或者是我们的数据表特别大,单一的服务器甚至连一张表都无法存储。解决方案就是数据分片。

1.数据分片介绍     

a.主要目标:将一张数据表切分成较小的片,不同的片存储到不同的服务器上面去,通过分片的方式使用多台服务器存储一张数据表,避免一台服务器记录存储处理整张数据表带来的存储及访问压力。

b.主要特点:数据库服务器之间互相独立,不共享任何信息,即使有部分服务器故障,也不影响整个系统的可用性。第二个特点是通过分片键定位分片,也就是说一个分片存储到哪个服务器上面去,到哪个服服务器上面去查找,是通过分片键进行路由分区算法计算出来的。在SQL语句里面,只要包含分片键,就可以访问特定的服务器,而不需要连接所有的服务器,跟其他的服务器进行通信。

c.主要原理:将数据以某种方式进行切分,通常就是用刚才提到的分片键的路由算法。通过分片键,根据某种路由算法进行计算,使每台服务器都只存储一部分数据。

2.硬编码实现数据分片

如图例子,通过应用程序硬编码的方式实现数据分片。假设我们的数据库将数据表根据用户ID进行分片,分片的逻辑是用户ID为奇数的数据存储在服务器2中,用户ID为偶数的数据存储在服务器1中。那么,应用程序在编码的时候,就可以直接通过用户ID进行哈希计算,通常是余数计算。如果余数为奇数就连接到服务器2上,如果余数为偶数,就连接到服务器1上,这样就实现了一张用户表分片在两个服务器上。

这种硬编码主要的缺点在于,数据库的分片逻辑是应用程序自身实现的,应用程序需要耦合数据库分片逻辑,不利于应用程序的维护和扩展。一个简单的解决办法就是将映射关系存储在外面。

3.映射表外部存储       

应用程序在连接数据库进行SQL操作的时候,通过查找外部的数据存储查询自己应该连接到哪台服务器上面去,然后根据返回的服务器的编号,连接对应的服务器执行相应的操作。在这个例子中,用户ID=33查找服务器是2,用户ID=94查找服务器也是2,它们根据查找到的用户服务器的编号,连接对应的服务器,将数据写入到对应的服务器分片中。

4.数据分片的挑战及解决方案  

数据库分片面临如图的挑战:    

现在有一些专门的分布式数据库中间件来解决上述这些问题,比较知名的有Mycat。Mycat是一个专门的分布式数据库中间件,应用程序像连接数据库一样的连接Mycat,而数据分片的操作完全交给了Mycat去完成。

如下这个例子中,有3个分片数据库服务器,数据库服务器dn1、dn2和dn3,它们的分片规则是根据prov字段进行分片。那么,当我们执行一个查询操作”select * from orders where prov=’wuhan’“的时候,Mycat会根据分片规则将这条SQL操作路由到dn1这个服务器节点上。dn1执行数据查询操作返回结果后,Mycat再返回给应用程序。通过使用Mycat这样的分布式数据库中间件,应用程序可以透明的无感知的使用分片数据库。同时,Mycat还一定程度上支持分片数据库的联合join查询以及数据库事务。

5.分片数据库扩容伸缩

一开始,数据量还不是太多,两个数据库服务器就够了。但是随着数据的不断增长,可能需要增加第三个第四个第五个甚至更多的服务器。在增加服务器的过程中,分片规则需要改变。分片规则改变后,以前写入到原来的数据库中的数据,根据新的分片规则,可能要访问新的服务器,所以还需要进行数据迁移。

不管是更改分片的路由算法规则,还是进行数据迁移,都是一些比较麻烦和复杂的事情。因此在实践中通常的做法是数据分片使用逻辑数据库,也就是说一开始虽然只需要两个服务器就可以完成数据分片存储,但是依然在逻辑上把它切分成多个逻辑数据库。具体的操作办法,本文不用大篇幅进行阐述了。

三、数据库部署方案

1.单一服务和单一数据库      

这是最简单的部署方案。应用服务器可能有多个,但是它们完成的功能是单一的功能。多个完成单一功能的服务器,通过负载均衡对外提供服务。它们只连一台单一数据库服务器,这是应用系统早期用户量比较低的时候的一种架构方法。

2.主从复制实现伸缩              

如果对系统的可用性和对数据库的访问性能提出更高要求的时候,就可以通过数据库的主从复制进行初步的伸缩。通过主从复制,实现一主多从。应用服务器的写操作连接主数据库,读操作从从服务器上进行读取。

3.两个Web服务及两个数据库            

随着业务更加复杂,为了提供更高的数据库处理能力,可以进行数据的业务分库。数据的业务分库是一种逻辑上的,是基于功能的一种分割,将不同用途的数据表存储在不同的物理数据库上面去。

在这个例子中,有产品类目服务和用户服务,两个应用服务器集群,对应的也将数据库也拆分成两个,一个叫做类目数据库,一个叫做用户数据库。每个数据库依然使用主从复制。通过业务分库的方式,在同一个系统中,提供了更多的数据库存储,同时也就提供了更强大的数据访问能力,同时也使系统变得更加简单,系统的耦合变得更低。

4.综合部署方案              

根据不同数据的访问特点,使用不同的解决方案进行应对。比如说类目数据库,也许通过主从复制就能够满足所有的访问要求。但是如果用户量特别大,进行主从复制或主主复制,还是不能够满足数据存储以及写操作的访问压力,这时候就就可以对用户数据库进行数据分片存储了。同时每个分片数据库也使用主从复制的方式进行部署。

以上为分布式数据库的部署方案,如果你的应用不是非要使用关系数据库的话,你还可以选择NoSQL数据库,NoSQL数据库会提供更强大的数据存储能力和并发读写能力。但是NoSQL数据库因为CAP原理的约束可能会遇到数据不一致的问题。解决数据不一致的问题,可以通过时间戳合并、客户端判断以及投票这样的几种机制解决,实现最终一致性。

Image placeholder
Braov
未设置
  34人点赞

没有讨论,发表一下自己的看法吧

推荐文章
高并发下的接口幂等性解决方案!

一、背景我们实际系统中有很多操作,是不管做多少次,都应该产生一样的效果或返回一样的结果。例如:前端重复提交选中的数据,应该后台只产生对应这个数据的一个反应结果。我们发起一笔付款请求,应该只扣用户账户一

10分钟,用TensorFlow.js库,训练一个没有感情的“剪刀石头布”识别器

大数据文摘出品编译:Luciana、小七、宁静“剪刀石头布”是我们小时候经常玩的游戏,日常生活中做一些纠结的决策,有时候也常常使用这种规则得出最后的选择,我们人眼能很轻松地认知这些手势,“石头”呈握拳

NAS与对象存储:谁是非结构化数据存储的最佳选择?

非结构化数据是增长最快的数据类型之一。随着企业日积月累地生成、收集和存储越来越多的数据,必然会带来一个问题:什么是存储非结构化数据的最佳方式?直白来说,非结构化数据就是不遵循传统数据库格式的数据,其结

滴滴 曾奇:谈谈我所认识的分布式锁

桔妹导读:随着计算机技术和工程架构的发展,微服务变得越来越热。如今,绝大多数服务都处于分布式环境中,其中,数据一致性是我们一直关注的重点。分布式锁到底是什么?经过了哪些发展演进?工程上有哪些实现方案?

一个简单的基于 Redis 的分布式任务调度器 —— Java 语言实现

折腾了一周的JavaQuartz集群任务调度,很遗憾没能搞定,网上的相关文章也少得可怜,在多节点(多进程)环境下Quartz似乎无法动态增减任务,恼火。无奈之下自己撸了一个简单的任务调度器,结果只花了

干货 | 揭秘京东数科强一致、高性能的分布式事务中间件JDTX

导读:在分布式数据库、云原生数据库、NewSQL等名词在数据库领域层出不穷的当今,变革——在这个相对稳定的领域已愈加不可避免。相比于完全革新,渐进式增强的方案在拥有厚重沉淀的行业则更受青睐。同所有分布

快看,我们的分布式缓存就是这样把注册中心搞崩塌

写公众号两年以来,每当有机会写故障类主题的时候,我都会在开始前静静地望着显示器很久,经过多次煎熬和挣扎之后才敢提起笔来,为什么呢?因为这样的话题很容易招来吐槽,比如“说了半天,不就是配置没配好吗?”,

基于 Zookeeper 的分布式锁实现

1.背景最近在学习Zookeeper,在刚开始接触Zookeeper的时候,完全不知道Zookeeper有什么用。且很多资料都是将Zookeeper描述成一个“类Unix/Linux文件系统”的中间件

iOS开发60分钟入门

===============本文面向已有其它语言(如Java,C,PHP,Javascript)编程经验的iOS开发初学者,初衷在于让我的同事一小时内了解如何开始开发iOSApp,学习目标包括: 能

Shell脚本编程30分钟入门

什么是Shell脚本 示例 看个例子吧: #!/bin/sh cd~ mkdirshell_tut cdshell_tut for((i=0;ibash 但在MacOS上不是,/bin/sh和/

30分钟让你掌握Git的黑魔法

本文转载自云效公众号在GitRevNews#48期的LightReading中有一篇文章写的不错,不仅干货满满而且还附带了操作视频。其中的内容不仅覆盖了很多git使用上的基础知识,也从使用角度上解答了

如何解决云中容器数据存储的移动性挑战?

如今,在云计算领域,越来越多的IT组织正在构建混合云和多云环境以支撑其业务运行。从容器的角度来看,我们知道,容器应用程序从一开始就内置了非常可观的可移动性、灵活性和效率。但是对于容器数据来说,它的移动

Redis百亿级Key存储方案

1.需求背景该应用场景为DMP缓存存储需求,DMP需要管理非常多的第三方id数据,其中包括各媒体cookie与自身cookie(以下统称supperid)的mapping关系,还包括了supperid

分布式存储时代,横空出世的OceanBase

数据,被誉为新时代的石油。几乎任何一个企业的IT管理者,都会在演讲、采访或其他形式的交流分享中强调数据的重要性。获取洞察、行为预测、市场分析、业务转型升级……数据能够为企业带来巨大的商业价值。但与此同

《从PPTV网络视频,到PPIO区块链分布式存储》

摘要:2019年11月26日,同济创业谷与PPIOCodeTalks联合举办了《创新X-区块链与创新创业》区块链技术分享会,本期我们为读者带来主题分享--《从PPTV网络视频,到PPIO区块链分布式存

Flutter高内聚组件怎么做?闲鱼打造开源高效方案!

fish_redux是闲鱼技术团队打造的开源flutter应用开发框架,旨在解决页面内组件间的高内聚、低耦合问题。开源地址:https://github.com/alibaba/fish-redux从

GoWeb教程_06.0. session 和数据存储

Web开发中一个很重要的议题就是如何做好用户的整个浏览过程的控制,因为HTTP协议是无状态的,所以用户的每一次请求都是无状态的,我们不知道在整个Web操作过程中哪些连接与该用户有关,我们应该如何来解决

本地读写的多活数据存储架构设计要义

本文由公众号EAWorld翻译发表,转载需注明出处。作者:ParasharBorkotoky 译者:白小白 原文:http://t.cn/AiKO0q4P原题:DesignConsiderations

MySQL 亿级数据数据库优化方案测试-银行交易流水记录的查询

作者:逸宸a链接:https://www.jianshu.com/p/cbdef47fb837对MySQL的性能和亿级数据的处理方法思考,以及分库分表到底该如何做,在什么场景比较合适?比如银行交易流水

Onvif/RTSP海康大华网络安防摄像机网页无插件直播方案EasyNVR登陆用户名密码失效问题解决方案

背景分析随着互联网基础设施建设的发展,4G/5G/NB-IoT各种网络技术的大规模商用,视频随时随地可看、可控的诉求越来越多,互联网思维、架构和技术引入进传统监控行业里,成为新形势下全终端监控的基础需

从关系型数据库到分布式机器学习,揭秘腾讯大数据十年发展历程

大数据技术在过去10多年中极大改变了企业对数据的存储、处理和分析方式。如今,大数据技术逐渐成熟,涵盖了计算、存储、数仓、数据集成、可视化、NOSQL、OLAP分析、机器学习等丰富领域。在未来,大数据技

分布式时序数据库QTSDB的设计与实现

现有的开源时序数据库influxdb只支持单机运行,在面临大量数据写入时,会出现查询慢,机器负载高,单机容量的限制。为了解决这一问题,360基础架构团队在单机influxdb的基础上,开发了集群版——

Go语言高级编程_6.1 分布式id生成器

6.1分布式id生成器 有时我们需要能够生成类似MySQL自增ID这样不断增大,同时又不会重复的id。以支持业务中的高并发场景。比较典型的,电商促销时,短时间内会有大量的订单涌入到系统,比如每秒10w

Go语言高级编程_6.2 分布式锁

6.2分布式锁 在单机程序并发或并行修改全局变量时,需要对修改行为加锁以创造临界区。为什么需要加锁呢?我们看看在不加锁的情况下并发计数会发生什么情况: packagemain import( "sy

Go语言高级编程_6.4 分布式搜索引擎

6.4分布式搜索引擎 在Web一章中,我们提到MySQL很脆弱。数据库系统本身要保证实时和强一致性,所以其功能设计上都是为了满足这种一致性需求。比如writeaheadlog的设计,基于B+树实现的索