数据库常用架构方案

数据库架构原则

  1. 高可用
  2. 高性能
  3. 一致性
  4. 扩展性

常见的架构方案

主备架构

该方案只有主库提供读写服务,备库冗余作故障转移。
数据库链接字符串:jdbc:mysql://vip:3306/xxdb
img

  1. 高可用分析:高可用,主库挂了,keepalive(一种工具)会自动切换到备库。这个过程对业务层是透明的,无需修改代码或配置。
  2. 高性能分析:读写都操作主库,很容易产生瓶颈。大部分互联网应用读多写少,读会先成为瓶颈,进而影响写性能。另外,备库只是单纯的备份,资源利用率只有50%。
  3. 一致性分析:读写都操作主库,不存在数据一致性问题。
  4. 扩展性分析:无法通过加从库来扩展读性能,进而提高整体性能。
  5. 可落地分析:两点影响落地:第一,性能一般,这点可以通过建立高效的索引和引入缓存来增加读性能,进而提高性能。这也是通用的方案。第二,扩展性差,这点可以通过分库分表来扩展。

双主架构

该方案,两个主库同时提供服务,负载均衡。
数据库链接字符串:jdbc:mysql://vip:3306/xxdb
img

  1. 高可用分析:高可用,一个主库挂了,不影响另一台主库提供服务。这个过程对业务层是透明的,无需修改代码或配置。
  2. 高性能分析:读写性能相比于方案一都得到提升,提升一倍。
  3. 一致性分析:存在数据一致性问题。
  4. 扩展性分析:当然可以扩展成三主循环,但不建议(会多一层数据同步,这样同步的时间会更长)。如果非得在数据库架构层面扩展的话,扩展为方案四。
  5. 可落地分析:两点影响落地:第一,数据一致性问题,一致性解决方案可解决问题。第二,主键冲突问题,ID统一地由分布式ID生成服务来生成可解决问题。

一主多从

该方案采用主从架构,一主多从,读写分离。
数据库链接字符串:

1
2
3
4
5
jdbc:mysql://master-ip:3306/xxdb

jdbc:mysql://slave1-ip:3306/xxdb

jdbc:mysql://slave2-ip:3306/xxdb

img

  1. 高可用分析:主库单点,从库高可用。一旦主库挂了,写服务也就无法提供。
  2. 高性能分析:大部分互联网应用读多写少,读会先成为瓶颈,进而影响整体性能。读的性能提高了,整体性能也提高了。另外,主库可以不用索引,线上从库和线下从库也可以建立不同的索引(线上从库如果有多个还是要建立相同的索引,不然得不偿失;线下从库是平时开发人员排查线上问题时查的库,可以建更多的索引)。
  3. 一致性分析:存在数据一致性问题。
  4. 扩展性分析:可以通过加从库来扩展读性能,进而提高整体性能。(带来的问题是,从库越多需要从主库拉取binlog日志的端就越多,进而影响主库的性能,并且数据同步完成的时间也会更长)
  5. 可落地分析:两点影响落地:第一,数据一致性问题,一致性解决方案可解决问题。第二,主库单点问题,暂时没想到很好的解决方案。

双主+主从

数据库链接字符串:

1
2
3
4
5
jdbc:mysql://vip:3306/xxdb

jdbc:mysql://slave1-ip:3306/xxdb

jdbc:mysql://slave2-ip:3306/xxdb

img

  1. 高可用分析:高可用。
  2. 高性能分析:高性能。
  3. 一致性分析:存在数据一致性问题。
  4. 扩展性分析:可以通过加从库来扩展读性能,进而提高整体性能。(带来的问题同方案二)
  5. 可落地分析:同方案二,但数据同步又多了一层,数据延迟更严重。

数据一致性解决方案

主库和从库一致性解决方案

img

注:图中圈出的是数据同步的地方,数据同步(从库从主库拉取binlog日志,再执行一遍)是需要时间的,这个同步时间内主库和从库的数据会存在不一致的情况。如果同步过程中有读请求,那么读到的就是从库中的老数据。如下图。
img

既然知道了数据不一致性产生的原因,有下面几个解决方案供参考:

  1. 直接忽略,如果业务允许延时存在,那么就不去管它。

  2. 强制读主,采用主备架构方案,读写都走主库。用缓存来扩展数据库读性能 。如果缓存挂了,可能会产生雪崩现象,不过一般分布式缓存都是高可用的。
    img

  3. 选择读主,写操作时根据库+表+业务特征生成一个key放到Cache里并设置超时时间(大于等于主从数据同步时间)。读请求时,同样的方式生成key先去查Cache,再判断是否命中。若命中,则读主库,否则读从库。代价是多了一次缓存读写,基本可以忽略。
    img

  4. 半同步复制,等主从同步完成,写请求才返回。就是大家常说的“半同步复制”semi-sync。这可以利用数据库原生功能,实现比较简单。代价是写请求时延增长,吞吐量降低。

  5. 数据库中间件,引入开源(mycat等)或自研的数据库中间层。思路同选择读主。数据库中间件的成本比较高,并且还多引入了一层。
    img

DB和缓存一致性解决方案

img

先来看一下常用的缓存使用方式:

第一步:淘汰缓存;

第二步:写入数据库;

第三步:读取缓存?返回:读取数据库;

第四步:读取数据库后写入缓存。

注:如果按照这种方式,图一,不会产生DB和缓存不一致问题;图二,会产生DB和缓存不一致问题,即r2.read先于w3.sync执行。如果不做处理,缓存里的数据可能一直是脏数据。解决方式如下:
img

注:设置缓存时,一定要加上失效时间,以防延时淘汰缓存失败的情况!

MySQL复制

MySQL主从复制

目的

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

原理

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

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

MySQL一主多从复制

目的

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

原理

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

优点

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

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

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

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

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

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任何一台服务器收到了数据的写的操作都会同步更新到另一台服务器,实现了数据库主主复制。主主复制可以提高系统的写可用,实现写操作的高可用。
img

MySQL主主复制失效恢复

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

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

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

MySQL复制注意事项

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

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

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

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

本文标题:数据库常用架构方案

文章作者:王洪博

发布时间:2019年04月09日 - 15:04

最后更新:2019年09月12日 - 10:09

原始链接:http://whb1990.github.io/posts/4c1379b8.html

▄︻┻═┳一如果你喜欢这篇文章,请点击下方"打赏"按钮请我喝杯 ☕
0%