Jamzy Wang

life is a struggle,be willing to do,be happy to bear~~~

可扩展系统设计之数据库扩展

2015-03-17 19:32

原创声明:本作品采用知识共享署名-非商业性使用 3.0 版本许可协议进行许可,欢迎转载,演绎,但是必须保留本文的署名(包含链接),且不得用于商业目的。

当生产线上只有一台服务器来提供数据服务的时候,系统会遇到如下的两个问题:

(1) 一台服务器的性能不足以提供足够的能力服务于所有的请求,数据库的响应时间越来越慢。

(2) 一台服务器发生宕机会造成服务整体不可用或是数据的丢失,也就是所谓的单点故障。

于是我们不得不对服务器进行扩展,加入更多的机器来分担性能上的问题,以及来解决单点故障问题,也就是采用分布式数据库系统。从广义上讲,用多于一台以上的机器对外提供服务的系统都可以称之为分布式系统,常见的分布式系统有:分布式文件系统如HDFS、分布式键值(key-value)系统如Redis、分布式数据库如MySQL集群。

在这里需要强调一点,当数据库遇到性能瓶颈时,首先考虑的往往不是直接将单机系统扩展为分布式系统,而是先对单机数据库进行相应的优化,当单机数据库已经无法再有效的优化时才会考虑将数据库扩展为分布式,常见的单机数据库的优化方式有:

(1) MySQL服务器的优化:MySQL参数优化如binlog_cache_size、key_buffer_size

(2) Query的优化:查询缓存优化

(3) 库表设计优化:建立合适的索引、选取最合适的字段属性、适当冗余、选择适当的存储引擎

(4) 业务需求和系统架构优化

MySQL数据库性能优化一文对常见的数据库优化技巧做了详细的介绍。本文将重点介绍分布式系统数据库的扩展方法。通常,有三种手段来扩展我们的数据服务:

(1) 数据镜像(Replication):让多个服务器有相同的数据,提供相当的服务

(2) 数据分区(Partition):就是对数据分块放在不同的服务器上

(3) 采用NOSQL方案:用NoSQL数据库如Redis、Hbase等代替关系型数据库如MySQL、SQL Server

此处输入图片的描述

与这三种扩展手段相关的就有如下需要解决的几个技术难点,这些技术难点几乎贯穿了每个分布式数据库系统。

  • 数据分布:将数据分布到多台机器上并保证分布均匀,如何实现跨服务器读写

  • 一致性:如何保证数据有多个副本,如何修复副本,如何在异常情况下依然保证数据一致

  • 容错:如何检查故障?如何自动的将故障的机器的数据和服务自动迁移

  • 负载均衡:新增服务器和集群正常运行中如何保证负载均衡?数据迁移中如何保证不影响服务?

  • 事物与并发: 如何实现分布式事物?如何实现多版本并发控制?

接下来,本文将具体讨论这三种数据库扩展手段以及与之相关的几个技术难点。

数据镜像(Replication)

数据镜像(或叫数据复制)指的是把数据写到一个master数据库后,系统会自动把整个数据库复制到其他的数据库上(可以使slave数据库或者其他master数据库),即系统自动保证镜像数据与master数据的一致性,一般也把这种数据镜像方式称为主从复制。

那么为什么要有数据镜像呢?数据镜像主要有以下几个作用:

(1) 避免单点故障,提供数据库的高可用性

(2) 提供数据库的水平扩展方式,可以把用户请求分发到多台数据库服务器上

(3) 作为数据库的一种备份方式

根据数据库的master和slave数量以及组合方式,数据镜像的网络架构常见的有以下几种:

一主一从

在一主一从的数据库架构中,master负责数据的读/写操作,slave往往只用来做数据的备份(backup),也有部分系统用slave做数据的读操作。

此处输入图片的描述

一主多从

一主多从是目前最主流的主从同步架构,这种方式可以很好的均衡数据库的负载,后文也将重点探讨这个同步架构。一般来说在一主多从数据库架构中,master只负责写数据,slave只用来读数据。在MySQL中,通常都是通过 主从复制(Master-Slave)的方式来同步数据,再通过读写分离(MySQL-Proxy)来提升数据库的并发负载能力 这样的方案来进行部署与实施的。

此处输入图片的描述

多主

一个系统中有多个master,最常见的是“双master”:两个master互为主从。不过一般都是一个读写,另外一个只读,在异常的时候,才会切换读写。如果两台mysql都提供写操作,可能会有主键冲突的情况,而mysql自身是无法预测该情况,需要应用程序自己去规避该问题。

此处输入图片的描述

主从复制

上文中我们介绍了常见的主从复制架构,这部分我们将介绍实现主从复制的两种方式,同步复制(Synchronous replication)以及异步复制(Asynchronous replication)。 在这里,同步异步指的是,master更新数据之后,是否要等待slave完全更新完毕(包括IO线程的读数据操作和SQL线程的执行操作)后才能将结果返回给client。

同步复制

同步复制,就是master更新数据之后,会一直阻塞,直到所有的slave的IO线程和SQL线程都执行完毕。这种模式,mysql原生是不支持的,实际生产环境用的很少。

  • 优点:数据风险性最小;
  • 缺点:增加了时间开销,主库要等所有的丛库更新都没有问题。

此处输入图片的描述

异步复制

此处输入图片的描述

异步复制,就是master更新数据之后,会去主动通知slave有新的数据,但是不会去关心slave的实际执行情况,即使slave挂了,master照样更新。这也是mysql的默认模式,也是最常见的一种模式。

  • 优点:高效快速,
  • 缺点:1,主从延迟;2,如果从库执行错误了,主库返回却是OK,会有一定的数据风险。

半异步模式

半异步模式,master更新完毕数据,还是会阻塞,但是仅仅等待一个丛库的IO线程执行完毕,不再阻塞。结合了前面两种方式的特点,既可以保证数据的安全性,也尽可能减少延迟。mysql的5.5版本有该功能的实现。

主从同步在技术上具体如何实现可以参考 可扩展系统设计之MySQL主从同步原理(待完成),具体部署可以参考 可扩展系统设计之MySQL主从复制与读写分离(待完成)

数据分区/分表(Partition)

随着数据库表中数据日积月累越来越多,数据库会越来越大,表记录数也会达到千万甚至亿级别,数据库表的访问效率下降明显,导致外层应用的访问效率非常差,访问时间急剧上升,用户体验下降。此时就必须使用数据切分来解决这个瓶颈了。

数据切分就是指通过某种特定的条件,将存放在同一个数据库中的数据分散存放到多个数据库上面,以达到分散单台设备负载的效果。数据切分根据切分规则的类型,可以分为两种模式。一种是:

1
垂直切分:按照不同的表切分到不同的数据库上或不同的表上

另外一种是:

1
水平切分:根据表中数据的逻辑关系,将同一个表的数据按照某种规则切分到多台数据库上或不同的表上

垂直切分

垂直切分就是要把表按模块划分到不同数据库或不同表中。这种切分在大型网站的演变过程中是很常见的。当一个网站还在很小的时候,只有少量的人来开发和维护,各模块和表都在一起,当网站不断丰富和壮大的时候,也会变成多个子系统来支撑,这时就有按模块和功能把表划分出来的需求。

此处输入图片的描述

垂直切分的优缺点: 优点:

  • 数据库表的切分简单明了,切分规则明确;
  • 应用程序模块清晰明确,整合容易;
  • 数据维护方便易行,容易定位;

缺点:

  • 部分表关联无法在数据库级别完成,需要在程序中进行;
  • 对于访问极其频繁且数据量超大的表仍然存在性能瓶颈,不一定能满足要求;
  • 事务处理相对复杂;
  • 切分达到一定程度之后,扩展性会受到限制;
  • 过度切分可能会导致系统过于复杂而难以维护;

水平切分

水平切分可以简单理解为按照数据行的切分,就是将一个表中的某些行切分到一个数据库或表,而另外的某些行又可以切分到其他的数据库或表中。为了能够比较容易判定各行数据被切分到哪个库或表中,切分需要按照某种特定的规则进行。

此处输入图片的描述

水平切分的切分标准可以:

1
2
3
4
按照数据范围分,比如1-100万一个表,100-200万又是一个表;
按照时间顺序来切分,比如一年的数据归到一张表中等;
按照地域范围来分,比如按照地市来分,每个或多个地市一个库等;
按照某种计算公式来切分,比较简单的比如取模的方式

垂直与水平联合切分

联合切分的优缺点: 优点 - 可以充分利用垂直和水平切分各自的优势而避免各自的缺陷; - 让系统扩展性得到最大化提升。 缺点 - 数据库系统架构会比较复杂,维护难度更大; - 应用程序架构也更复杂。

采用NoSQL方案

如高可用性Redis集群方案

Comments