金融型数据库Failover架构

时间:2017-06-16 15:36

金融型数据库Failover架构

  数据库往往是IT体系结构中的最终章节,也是最重要的一节。由于路由器、程序、中间件等组件的无状态性,决定了它们最主要的容灾能力即是:重启大法好。而数据库作为最终的信息载体,它的重启往往即意味着整个系统的不可用。这当然是用户和我们所不能接受的。我们必然把绞尽脑汁来保证数据库的稳健性。

  不过根据墨菲定律,越担心发生的事情,它总是要发生的。尤其是当服务器大面积部署之后,一万台服务器每天都要宕个一两台。

  而根据CAP理论,鱼与熊掌不可兼得,我们不可能在一条数据不丢的异地备份前提下,还能保证完美的性能。当业务量极大时,连号称一点数据不丢的Oracle DataGuard最高保护模式下也是根本抗不住的。特别是在某宝这样的数据量负荷下。

  那即使一点数据也不丢,能做到不到一分钟的业务快速恢复么?这里指的是整个业务完成恢复的时间,而不是单指数据库可以拉起来的时间。明显是不行的。或者说业务倒是可以快速恢复了,但是数据仍然不一致,那将导致更严重的问题,这显然也是不行的。

  这就意味着:任何只依赖数据库层面的容灾技术,是无法保证业务快速恢复和数据绝对一致性的,尤其是涉及钱的金融型系统。

  那就无药可施了么?当然不是。办法总是有的,只是,要付出代价。而这个代价,无论是开发的代价,还是机器的代价,也是值得的。

  声明:本文不会有具体的代码的实施方案,讲解的只是一种思路。好,下面我们进入正题。

  我们知道,数据库是一个比较稳定的载体,一般不轻易挂,而如果挂了,则不会轻易就能起来。所以我们的出发点就是根本不能指望它能再起来。因此,我们需要failover。

  Failover是什么?

  (详见维基百科:链接https://en.wikipedia.org/wiki/Failover)

  先简要说下这个Failover的基本思路:

设计之初即在异地机房创建好同样结构的数据库,同样结构的表;

中间件创建两套数据源,配置在内存时环境,可随时切换;

当主备发生故障或弹性流量切换时,人为或自动推荐DRM,中间件选择failover的数据源,新的数据全部流入新库,业务得以立刻恢复(仅限流水型数据)或短时间内快速自我恢复(状态型数据),或新逻辑主库达到一致性后恢复(状态型数据);

数据回流:流水型数据一般不需要回流,因为根据流水单号,可以路由到是原主库还是Failover库,而状态型数据一般需要进行merge。

  前面说到数据也会有类型,所以我们把数据分为三种类型:

流水型数据:流水型数据是无状态的,多笔业务之间没有关联,每次业务过来的时候都会产生新的单据,比如交易流水,支付流水,只要能插入新单据就能完成业务,特点是后面的数据不依赖前面的数据,所有的数据按时间流水进入数据库。

状态型数据:状态型数据是有状态的,多笔业务之间依赖于有状态的数据,而且要保证该数据的准确性,比如账户余额,做余额支付时必须要拿到原来的余额,才能支付成功。

配置型数据:因为此类型数据数据量较小,而且结构简单,这里就暂不讨论。大家可以根据前面的流水和状态型数据灵活地设计出failover方案。

  下面分别看看它是如何实现failover的:

  流水型数据

  我们都知道,帐务对数据一致性的绝对要求(什么?不是绝对一致性要求?那建议你去玩个收藏夹什么的数据库,可以随便丢),当主库DB出现异常宕机时主备库的数据延迟,则无法确认主库与备库差异的数据量以及数据内容,则这部分数据不敢启用。

  举个例子,某同学的银行卡账号在帐务数据库上,A同学通过此银行卡账户购买了一件衣服消费50000元并支付成功返回,主库数据已变动。这时发生DB宕机,A同学的资金变动数据还未同步到备库,则如果备库提供服务,则A同学会惊讶的发现,他的账户里又多了50000元。只有当DB的主备采用强同步模式下才能确保主库宕机后备库与主库数据的强一致性。但强同步下DB的整体性能下降基于到了70%,严重的性能损耗若支撑大业务量,需要大量的DB服务器。成本太高。

  这时,如何解决呢?可以祭出我们的神图了,此图是现代关系型数据库基础思想,核心的手法是放弃全程的一致性,而追求最终的一致性,本质则是工程学中常用的核心思想:【空间换时间】