作者:潘安群,腾讯TEG/计费平台部技术总监,年毕业于华中科技大学,随即加入腾讯,一直负责计费领域相关系统建设工作,先后主导账户平台、风控平台、HOLD及TDSQL、计费集群等平台建设。本文为《程序员》原创文章,未经允许不得转载,更多精彩文章请订阅年《程序员》
TDSQL(TencentDistributedMySQL,腾讯分布式MySQL)是由腾讯技术工程事业群计费平台部针对金融联机交易场景开发的高一致性数据库集群产品。该产品第一个版本诞生于年,当时主要承载公司数字支付相关业务,包括Q币Q点、包月、各类点券等核心支付数据的托管;年被WeBank选中,作为其核心系统的数据库解决方案;年,在腾讯金融云上正式推出,作为唯一一款金融级数据库产品,为金融、政企机构提供数据库的公有云以及私有云服务。
TDSQ作为我们计费平台第四代数据库产品,是计费平台年以来,对金融类存储产品的思考沉淀之作,同时作为一款定位于金融的数据库,其产品质量也必须符合金融行业标准:数据多备份高一致、零丢失、高可用。正因如此,本文试着从计费平台(TBOSS)四代存储系统的发展过程,来谈谈TDSQL在存储平台数据一致性、可用性和易用性等方面的一些考量。
何为一致性
谈到一致性,业界常提的有传统关系型数据库ACID理论的C,以及分布式系统中CAP理论的C,虽翻译过来都叫“一致性”,但从狭义角度来看,此C非彼C:ACID中的C通常指事务一致性,CAP中的C通常指数据复制一致性。但从广义角度来看,二者又是相通的。
ACID中的C
ACID理论中的C,是在事务执行过程中,对外界应看到系统何种状态的约束(相对的,原子性是对系统如何执行这个事务的约束:要么全部成功,要么全部不执行)。严格意义来说,一致性要求在事务执行过程中,系统不能看到该事务执行过程中的中间状态。举个例子:假如银行里一共有个个人账户,每人有10块钱余额,彼此之间可以转账,但无论同时发生多少次转账,我们任何时候看到的银行总余额应该始终是0块,不多不少。
CAP中的C
分布式中的C,一般是指数据多副本情况下的复制一致性,即数据虽然多副本,但需要保证任意时刻,从系统中读到的数据都是一致的。例如某人的银行账户需扣款元,在分布式系统中,执行该操作后,可能部分副本数据已更新为扣除后余额,但是部分副本可能数据还没有更新,那这就是一个中间状态,强一致性则要求这个中间状态不可见。用户在查询个人余额时,不能时而查询到扣除前的余额,时而又查询到扣除后的余额。初看起来,它与ACID中的C是两个概念,但如果把分布式系统中的一个写入操作当作一个事务(这个事务由多个写操作组成,因为需要在不同的服务器写多个副本),那这两个C概念又是相通的。
一致性、隔离性与锁
谈了一致性,就不能不谈隔离性。ACID中四种不同的隔离级别,理解起来比较晦涩。我们先抛开具体的隔离级别,而从下面的角度来看,就容易理解得多:系统要实现最严格的事务一致性,最简单的办法就是用一把全局锁,这样就实现了可序列化隔离级别,但这种情况下,系统的吞吐量极差,于是我们考虑将锁粒度缩小,再加入读写锁等机制以提升系统吞吐量。锁的粒度越小,系统的一致性就越弱,于是各种隔离级别应运而生,不同的隔离级别就是系统在吞吐量与一致性之间的不同平衡程度。
备注:在各种数据库实现中,通常为了进一步提升吞吐量,并不是简单地用锁控制并发,往往会结合一些更为复杂的实现,例如MVCC等。
但在分布式系统下,如果继续使用锁机制来实现一致性,会因为各种因素,例如网络时延、网络故障、机器故障等情况,导致这个锁实现异常复杂,需要考虑的情况太多。
Paxos、ZAB、Raft
在分布式系统中确保各个节点数据一致性,Paxos是业界指定的唯一算法,经过严格数学证明,但是很不好理解,而且工程实现难度很高,所以后面出现了一些变种,例如ZooKeeper的ZAB协议,以及现在比较火的Raft协议,均是Paxos协议变种,但是从工程角度来看,无论可理解性,还是可实现性,均有大幅提升。
CAP
这里补充说明一下,CAP理论作者EricBrewer,在年在《Computer》杂志发表新文章《CAPTwelveYearsLater:Howthe“Rules”HaveChanged》,中文版《CAP理论十二年回顾:“规则”变了》:“首先,由于分区很少发生,那么在系统不存在分区的情况下没什么理由牺牲C或A。其次,C与A之间的取舍可以在同一系统内以非常细小的粒度反复发生,而每一次的决策可能因为具体的操作,乃至因为牵涉到特定的数据或用户而有所不同。最后,这三种性质都可以在程度上衡量,并不是非黑即白的有或无。可用性显然是在0%到%之间连续变化的,一致性分很多级别,连分区也可以细分为不同含义,如系统内的不同部分对于是否存在分区可以有不一样的认知。”
在文章后面,我们也会来看看我们对CAP的理解。
何为可用性?
对于存储系统来说,可用性一般要处理下面这两种情况:
出现故障时,如何处理请求。分布式系统中,故障的情况有很多,例如网络故障、服务器故障、软件故障等;
出现性能或容量瓶颈时,导致的系统吞吐量降低,时耗增加等不可用问题。
何为易用性?
对于一套存储系统,易用性主要包含两个方面:
提供给业务开发人员的API接口。例如常见的存储系统接口有:标准SQL、KV等。一般来说SQL比KV功能更丰富,易用性更高。此外是更强的一致性,应用程序无需考虑数据不一致的情况,易用性也更高。
提供给DBA运维人员的运维接口。例如监控体系、发布体系、故障定位及处理体系、备份系统等。一般来说周边配套设施越完善,易用性越高。
TBOSS存储平台的历程
下面,我们将从TBOSS存储平台从1.0到4.0的发展历程,来谈谈TDSQL在数据一致性、可用性及易用性等方面的考虑。
-:1.0,MySQL热备
1.0属于起始阶段,数据的备份容灾,主要依赖于MySQL的异步复制机制,主MySQL提供服务,备MySQLStandby,按天冷备数据到异地。该架构的优势是简单粗暴,但数据备份依赖于MySQL的异步复制机制,在主备数据同步有延迟时,如果主机发生故障,系统会有数据丢失,业务系统不能直接切换到备机。所以通常情况下,如果主机发生了故障,对于账户类数据,需要先利用业务日志来修复备机数据后,再切换到备机。
一致性与可用性:从CAP角度来看,在P发生时,备机数据恢复之前,直接让系统此时不可用,也就是完全忽略A,保障C。
易用性:系统足够简单,开发、运营易用性均比较高。
-:2.0,TBOSS7*24容灾
1.0架构在故障(P)时,要么忽略A保障C,要么忽略C保障A的机制,明显控制粒度过大。我们其实知道在故障发生时,主备MySQL没有同步的数据只是极少数,其他绝大部分数据都已同步,是一致的。有没有可能出现故障时,只让未完成同步的数据不可用,而大部分已经一致的数据继续可用呢?这也就达到了更细粒度的控制:在P发生时,仅仅牺牲少量可用性,来保证一致性。
于是我们在2.0架构里,引入了一个中间模块,叫一致性控制中心(CC)。如果从ACID事务角度来看一致性,那CC可以看到是一个事务管理器;如果从锁机制来看一致性,那它就可以视作一个锁管理器。应用层在每次更新数据之前,先告之CC,即将更新某数据,麻烦先将该数据加“锁”。“锁”的释放由CC来负责,CC会根据版本号不断比对主备数据之间的一致性,一旦数据一致,则释放锁,否则继续持有。大部分情况下,这把锁会很快被释放。一旦故障发生,CC中会持有全部未同步数据的锁(黑名单),此时如果应用层需要切换到备机,需要先到CC拉取这份黑名单,将这些数据置为不可用状态,而其他数据则可以直接访问备机。此外,需要注意的是,这把锁是异步的,在故障未发生的情况下,它释放与否,并不影响正常的数据访问及更新。
一致性与可用性:引入CC机制后,故障发生时,在C与A之间,我们确实做到了一个不错的平衡。
易用性:但系统在易用性上存在很大问题:在容灾逻辑上,应用层与CC、数据层耦合太紧,例如故障发生时,需要应用层去拉取未同步数据的黑名单,以及应用层决定何时切换到备机模式,每次数据访问需要先上报CC等,这些都使得应用层程序嵌入太多容灾逻辑,开发难度增高。
-至今:3.0,厚德(HOLD)存储平台
厚德平台试图将CC与应用层剥离,让应用层不再白点疯白癜风最好的治愈方法