数据库部署架构是从容量、可用性、性能、成本等多方面权衡的结果,网商银行基础架构从建行之初满足快速业务响应的分布式架构,到单元化架构的落地,再到云原生时代,其中伴随着业务的快速发展,数据库的部署架构也经过多个版本的迭代发展。
容灾方面,从最初的“两地三中心”,具备机房级容灾,不具备全部的城市级容灾,经过扩容建设发展到现在的“三地五中心”。
具体部署方式如图3-1-1所示,采用3-2-1的部署方式,任意一个城市的故障,通过选主(选择主库)实现主库的切换完成容灾。
分布式业务应用为支撑业务容量的快速发展和业务的多样性,持续进行微服务的拆分改造,其中数据库也随着进行扩容、拆分、迁移。数据库之间的隔离性、集群故障的业务影响面愈加重要,如何合理规划业务集群,实现业务的故障影响面可控,是发展过程中一直面临的挑战。
分布式数据库
分布式数据库中的数据在逻辑上是一个整体,但物理上分布在计算机网络的不同节点上。网络中的每个节点都可以提供数据服务,可以通过中间件或者协同服务器实现协调,以代理的形式完成数据库访问的策略控制。图3-1-2所示为一种集中代理方式,通过协同服务器实现多应用的数据读写访问,在这种方式中应用不感知分布式的多个节点,通过协同服务器进行读写节点的路由选择、读写分离控制、权限控制等。
分布式数据库增加了系统交互的复杂性,为系统引入了更多潜在的失败环节,但分布式系统带来的好处也非常明显。
(1)持续可用。分布式数据库对同一份数据维护多个副本,当某个副本出现故障时,其他副本还能继续正常提供服务。为避免多个副本同时服务同一份数据带来的数据一致性问题,引入分布式协议Paxos或Raft实现数据的一致性。以系统包含3个副本(1个主库,2个备库)为例,每次写事务都需要让主库和其中一个备库同步,在主库出现故障时,至少一个备库有完整的数据,数据不会丢失,可通过分布式协议完成选主,继续提供写服务。在任意一个备库出现故障时,主库仍然可以将数据同步到另一个备库,形成“多数派”,保证数据不会丢失。
(2)可扩展。通过对集群节点的扩容,完成读写容量的线性扩展,支撑大促的突发流量。
(3)低成本。分布式系统通常只需要采用廉价的普通服务器替代高端服务器与高端存储设备,通过自动容错能力实现运维成本的降低。
分布式事务与数据一致性
处理事务是数据库系统的基本能力,通过事务保证数据的准确性与一致性,从而减少了上层应用的复杂度。但数据库系统为实现事务,也进行了一定的性能牺牲。事务必须具有ACID属性。
- lA,原子性(Atomicity):事务中多个操作要么全部完成,要么全部未完成,不存在中间状态。
- lC,一致性(Consistency):事务必须始终保证系统的一致性状态,不管在什么时间,并发事务有多少。
- lI,隔离性(Isolation):为了防止事务操作的混淆,必须使请求序列化,使得在同一时间仅有一个请求作用于同一数据。
- lD,持久性(Durability):事务完成以后,事务对于数据的变更持久保存,不会进行回滚。
分布式事务通常是在多个节点的机器上运行,运行时有进行RPC的过程,相对于单系统数据库,在保证事务的原子性上会遇到更多的异常环节,存在更多的恢复与回滚情形,当前大多通过两阶段提交协议进行解决。分布式事务提交到多台服务器上进行处理时,每台服务器都需要进行日志的记录,当事务出现失败时,对应的服务器都需要进行回滚操作,典型的分布式事务处理过程。
图中左侧是协调者状态机,右侧是参与者状态机。协调者是驱动整个事务提交流程的主体,它可以在任意机器上,当然也可以和其中一个参与者在同一台机器上。参与者是真正的事务操作的执行者。协调者首先通知所有的参与者持久化(图中的prepare命令),当参与者使事务的日志处于持久化状态后会回复prepare OK,当所有参与者都回复prepare OK后,意味着整个事务完成了。
然后协调者会写下事务commit的日志,并且发送commit给所有参与者,如果其中任何一个参与者返回失败(即abort OK),那么协调者就会认为事务是失败的,记下事务回滚的日志,并且发送abort给所有参与者。在这个流程中,分布式事务提交的延迟是两次写日志(参与者写prepare日志,协调者写commit日志)的延迟和两次通信(协调者通知参与者prepare,协调者通知参与者commit)的延迟。