分布式数据库(十二)

小注

极客时间 - 分布式数据库 30 讲

银行是怎么选择分布式数据库的?

数据库作为一款基础软件,稳定性和可靠性就是它的立身之本。而对稳定性要求最严苛的行业,就是金融业,尤其是银行业。所以,只有经过金融场景的考验,一款数据库产品才能真正扬名立万,让其他行业的用户放心使用。

分布式数据库的应用场景主要特征是海量并发,所以理论上说,业务规模越大,使用分布式数据库的需求也就越迫切。无论从用户数量还是资产规模,国内最大的银行肯定是工商银行。

工商银行(分布式中间件)

工行之前的数据库主要是 Oracle 和 IBM 的 DB2,这很代表性,过去的 20 年银行业基本上就是在这两种产品中二选一。

Oracle 和 DB2 都是单体数据库,只能采用垂直扩展方式,在碰到技术天花板后就会限制业务的发展。作为业务量最大的『宇宙行』,工行面对这个问题的选择是,从单体数据库向以 MySQL 为基础的分库分表方案转型。

工商银行

为什么工行没有选择真正的分布式数据库呢?

其中主要原因是产品成熟度。工行的架构改造在 2018 年大规模落地,而调研和试点工作则在更早的 2016-2017 年。这个时点上,商用 NewSQL 数据库刚刚推出不久,而金融场景的种种严苛要求,注定了银行不会做第一个吃螃蟹的人,那么这种可能性就被排除了。同样,另一种 PGXC 风格的分布式数据库也正待破茧而出,反而是它的前身,『分布式中间件 + 开源单体数据库』的组合更加普及。

所以,对当时的工行来说,产品架构上是没有什么选择余地的,能做的就是选择产品。后来的结果是选择了 DBLE + MySQL 的组合,选择 MySQL 是因为它的普及程度足够高;而选择 DBLE 则因为它是在 MyCat 的基础上研发,号称是『增强版 MyCat』,由于 MyCat 已经有较多的应用案例,所以这一点给 DBLE 带来不少加分。

现在看来,这个方案显得有点平淡无奇。但正是这种稳妥,或者说有点保守的选择,最大程度规避了风险,也坚定了工行从主机下移应用系统的决心。从后来 MySQL 上千节点的使用规模看,这个方案更大的意义在于,使工行逐步脱离了对 IBM 主机和 Oracle 数据库的依赖。分布式数据库的尝试只是这个大目标下的副产品。

相对于 OLTP 技术应用上的平淡,工行在 OLAP 方面的技术创新则令人瞩目。基本是在同期,工行联合华为成功研发了 GaussDB 200,并在生产环境中投入使用。这款数据库对标了 Teradata 和 Greenplum 等国外 OLAP 数据库。在工行案例的加持下,目前不少银行计划或者正在使用这款产品替换 Teradata 数据库。


邮储银行(单元化)

邮政储蓄银行,简称邮储银行,由于特殊的历史沿革,它没有被归入通常所说『四大国有银行』,但这不意味着它的业务规模小。事实上,邮储银行的零售用户在 2019 年已经超过 6 亿。

这个庞大的用户基数使得邮储银行也早早地就开始探讨分布式数据库的使用。那他们采用了什么方案呢?

他们也没有选择分布式数据库。邮储的核心业务系统改造方案更接近于单元化架构,所以连分布式中间件都没使用。它的设计思路就是将原来商业数据库拆分成若干个小的单体数据库,分别设置对应的应用实例。邮储在单体数据库上选择了 PostgreSQL,这个在银行业中是相对较少使用的。

当然,单元化方案从应用整体看也是一种分布式架构,通过应用层面的重构弱化了对数据库的性能和稳定性等方面的要求。说到这,你可能会有个疑问,如果两种方式都能解决问题,那要怎么在单元化和分布式数据库之间选择呢?

从成本上看,系统的单元化改造要付出巨大的代价,是一个推倒重建的过程,远高于过渡到分布式数据库的代价。我认为,邮储之所以会选择这个方式,可能有两个原因:

  1. 对数据库的技术把控能力。毕竟分布式数据库带来的技术挑战不容忽视。
  2. 核心系统本身重构的必要性。如果应用系统的分布式改造势在必行,那么两个方案的目标都截然不同,成本的比较也就无从谈起了。

同样,民生银行也是在核心系统改造的背景下,完成了向分布式架构的升级。在民生银行的一份宣传材料中对分布式技术平台做了整体描述,其中有两段是和数据库相关,是这么写的『通过分库分表和读写分离实现分布式数据访问功能;基于可靠消息的最终一致性和基于冲正模型的反向处理实现分布式事务功能』。

邮储银行

可见民生银行也选择了与邮储银行大致相同的路线,弱化了分布式数据库的作用,更加强调整体架构改造,在应用系统层面做了更多的工作。


交通银行(研发 NewSQL)

交通银行的分布式数据库之路走得比较特别,它采用联合高校研发的方式,与华东师范大学和西北工业大学共同研发了分布式数据库 CBase。

CBase 研发开始于 2014 年,在分布式数据库中算是非常早的了,但它的整体架构风格非常接近于 NewSQL。不同于前几家银行,CBase 并不是某个重要业务系统的附属品,已经有点技术驱动的味道。

它最先用于历史库系统的数据存储,而后逐步实现了复杂 SQL 语句处理和高并发事务处理能力,在供应链、贷记卡授权和网联支付等系统使用。

交通银行

通过架构图,可以看到 CBase 的主要工作负载放在三类节点上,其中的数据存储节点与 NewSQL 风格完全一致,而剩下的 SQL 处理节点和事务处理节点,就是计算节点的细化。而且,CBase 也基于 Raft 协议设计和实现了轻量级分布式选举协议,分布式事务同样是在 2PC 上进行改进的。

这款数据库主要在交通银行内部使用,目前并没有看到其他的商业化案例,所以能够找到的资料比较少。不过,CBase 开发团队在 2019 年发表了一篇论文《分布式数据库在金融应用场景中的探索与实践》(刘雷 等 (2019)),介绍了 CBase 的部分设计。

交通银行研发分布式数据库在银行业是很有代表性的,因为之前还很少有在基础软件上进行大规模投入的先例。


中信银行(研发 PGXC)

GoldenDB 就是中信银行与中兴通讯联合研发的产品,而目前 GoldenDB 主要用户也是中信银行。中信银行的核心业务系统在 2020 年 5 月正式上线切换到 GoldenDB。这之前,基于 GoldenDB 的信用卡新核心系统已经在 2019 年 10 月投产运行。这两个重要系统的运行,使中信银行无可争议地成为分布式数据库应用最为深入的一家银行。核心业务系统是银行业务的心脏,它的稳定运行无疑为其他银行树立了标杆,客观上也加快分布式数据库的普及速度。

GoldenDB 和 CBase 有大致相同的发展路径,从产品研发到试点应用,只不过中信银行的步子更快些。当然,这并不是说交行研发人员的能力不行,因为这个速度上的差别确实有架构上的因素。GoldenDB 是 PGXC 风格的分布式数据库,遇到的技术挑战更小;当然 NewSQL 架构上的优势,也让我们对 CBase 的未来充满期待。

中信的目标就是完成 AS400 小机下移,将应用程序翻写到开放平台,但是对应用架构本身并没有改造诉求。所以,数据库层面的平滑过渡就有很大的优势,编码逻辑改动小,测试成本低,最重要的是不会因为技术原因变动业务流程,这样就大大降低了项目的实施难度。


北京银行(NewSQL)

北京银行是城市商业银行中的佼佼者,但相对于前几家银行,在资产规模和用户数量上有较大的差距。北京银行从 2018 年开始,先后在网联支付系统和网贷系统中应用了 TiDB。

事实上,很多比北京银行规模更小的城市商业银行,比如南京银行(OceanBase)、张家港银行(TDSQL)都已经上线了分布式数据库。表面上,似乎很难捕捉到他们替换数据库的动因。从业务压力的角度,业务量通常没有达到海量并发级别;同时城商行通常也不涉及『主机下移』带来可用性下降问题。

那么,他们为什么要做出这个选择呢?主要有三点原因:

1、国产化的诉求

由于各种原因,继续依赖 Oracle 这样的国外商业产品,很可能让银行将面临更大的风险。而对于小型银行来说,使用开源数据库还是分布式数据库,在成本上可能差异并不大。

随着国内厂商加大技术投入,隐约有一种趋势,就是分布式数据库正在逐步成为国产数据库的代名词。那些原本深耕单体数据库技术的厂商,比如达梦、人大金仓,也在朝着分布式架构转型。

所以,选择分布式数据库也就满足了国产化的诉求。

2、实际收益

由于小型银行的数据量并不大,上线分布式数据库后集群的节点规模没有大幅增长,对运维的冲击也相对小些。此外,利用分布式数据库的多租户特性,转变成类似 Aurora 使用方式,还能降低数据库实例管理的复杂度。所以,使用分布式数据库也是有一些实际收益的。

3、技术潮流

一旦技术的趋势形成,就会在无形中影响人们的选择。就像时尚潮流那样,在同等价位下,大家当然更愿意选那些流行款式。今天,分布式架构转型就是这样的潮流,微服务架构、分布式数据库甚至容器云都是这个大潮下的浪花。

在风险可控的前提下,受到技术潮流的影响,可能还会有更多的小型银行会选择分布式数据库。


光大银行(NewSQL & 分库分表)

简单来说,光大使用了双路线策略,也就是同时使用 NewSQL 和分库分表方案。

在云缴费系统中,光大使用了自研的分库分表方案。首先,这个系统的业务量,也就是缴费的业务量是非常大的。今天支付宝、微信甚至很多银行的缴费服务,在后台都是要调用光大的云缴费系统的。截至 2019 年,云缴费系统的累计用户达到了 5.49 亿。

其实,缴费业务是非常互联网化的业务,就是银行提供服务对接用户和缴费企业,所以它的业务模型比较简单和统一。这也意味着,它对分布式事务这样的复杂操作没有那么强烈的诉求。最后,用分库方案就很好地解决了海量业务的问题。

光大在另一个系统,新一代财富管理平台使用了 NewSQL 数据库,也就是 TiDB。这个系统是理财业务的全流程管理平台,业务量相对缴费要小很多,但业务要更复杂,而且在联机和批量方面都有计算需求。

这个架构选择更多是面向未来,因为理财业务是光大银行重点发力的业务,对未来业务量的增长还是有很大预期的。同时,伴随着 NewSQL 技术的发展,保持团队对新技术的感知和掌握,应该也是一个重要的原因。


选型建议

1、产品选型要服从于项目整体目标

局部最优的选择拼装在一起未必是全局最优的方案。如果目标是要对整个应用系统做彻底重构,例如把单体架构改为微服务架构,那么要解决原来某些局部的问题,可能会有更多选择。这时候要从整体上评估技术复杂度、工程实施等因素,而不是仅选择局部最合理的方案。

2、先进的产品可能会延长项目交付时间

最先进的产品不一定是完美的选择。尤其是有进度要求时,往往会选择更稳妥、快速的办法。但是,这本质上是在短期利益和长期利益之间做权衡,没有绝对的对错,搞清楚你想要的是什么就行。

3、当产品选型可能导致业务流程变更时,请慎重对待

对任何项目来说,协作范围的扩大一定会增加实施难度。当技术部门对业务流程变更没有决定权时,通过技术手段避免这种变更往往是更好的选择。

4、产品选型中的非技术因素

正视非技术因素,评估它的合理性不是技术团队的职责。

5、评估技术潮流对选型影响

跟随潮流并不是人云亦云,必须能够独立对技术发展趋势做出研判。太过小众的技术往往不能与工程化要求兼容。但同时,保持对新技术的敏感度和掌控力,也是非常必要的。


小结

  1. 工商银行在主机应用下移的过程中,采用分布式中间件加 MySQL 的方式替换了原有的单体数据库。这个选择,一方面受制于当时分布式数据库的成熟度,另外这个方案的主要意义是大量使用了 MySQL 数据库,降低对主机和 Oracle 数据库的依赖,而分布式方案是一个副产品。
  2. 邮储银行和民生银行是在新一代核心系统建设的背景下进行分布式架构改造,所以他们有更多的项目目标,也能够承受更大的改造成本,这样分布式数据库能够平滑过渡、减少应用改造的优势也就不那么重要了。最终,两家银行都采用了类似单元化的架构,在应用层处理分布式事务等工作。
  3. 交通银行和中信银行都选择了自研方式。中信银行目前已经在核心业务系统上线 GoldeDB,能够更快上线的一个原因就是 PGXC 的架构复用了单体数据库,遇到的技术挑战更少。
  4. 北京银行和很多规模更小的城商行也在陆续上线分布式数据库。我认为他们的选择因素有三个,国产化诉求、实际收益和技术潮流。我预测,未来还有更多的小型银行将上线分布式数据库。
  5. 光大银行采用了双路线策略,同时采用分库分表方案和 NewSQL。这一方面因为不同系统的业务特点不同,另一方面也是要跟进 NewSQL 技术发展,保持对新技术的感知和应用能力。

加餐:产品选型是系统建设中非常重要的工作,你觉得针对一个新建系统做产品选型时还要考虑哪些因素呢?这个产品,并不限于数据库?

对于分布式数据库的选型,最重要的是分析业务场景对于事务和查询方面的要求。事实上,这两部分内容也占据了我们课程的大半。在实践中,有的海量并发业务其实并没有相关性,也就是说,不同事务间数据重叠的概率非常低,这时就可以考虑分库分表方案。不过,多数的分库分表方案只能对数据做单向的路由分发,如果有跨分片的查询需求则很难满足。虽然,也可以通过 CDC 等工具导出到分析型系统实现这一点,但这时就要平衡系统的整体复杂度了。

跳出具体技术,产品选型要结合具体项目目标,选择尽量少的产品或技术组件,尽量不采用同质化的多种技术,让架构更加简洁和优雅。


哪些分布式数据库值得看?

NewSQL

Spanner

既然要说分布式数据库产品,第一个必须是 Google 的 Spanner。严格来说,是 Spanner 和 F1 一起开创了 NewSQL 风格,它是这一流派当之无愧的开山鼻祖。

在 2012 年 Google 论文 "F1: A Distributed SQL Database That Scales" 中首先描述了这个组合的整体架构。

Spanner 整体架构

其中 F1 主要作为 SQL 引擎,而事务一致性、复制机制、可扩展存储等特性都是由 Spanner 完成的,所以有时会忽略 F1,而更多地提到 Spanner。

Google 在 2012 年的另一篇论文 "Spanner: Google’s Globally-Distributed Database" 中介绍了 Spanner 的主要设计。

Spanner 架构中的核心处理模块是 Spanserver,下面是它的架构图。

Spanner 架构图

从图中可以看到,Spanserver 的核心工作有三部分:

  1. 基于 Paxos 协议的数据复制
  2. 基于 Tablet 的分片管理
  3. 基于 2PC 的事务一致性管理

软件架构会随着业务发展而演进,2017 年,Google 又发表了两篇新论文,介绍了 Spanner 和 F1 的最新变化。它们从原来的『金牌组合』走向了『单飞』模式。

Spanner 的论文是 "Spanner: Becoming a SQL System"。就像论文名字所说的,Spanner 完善了 SQL 功能,这样就算不借助 F1,也能成为一个完整的数据库。

这篇论文用大量篇幅介绍了 SQL 处理机制,同时在系统定位上相比 2012 版有一个大的变化,强调了兼容 OLTP 和 OLAP,也就是 HTAP。对应的,Spanner 在存储层的设计也从 2012 版中的 CFS 切换到了 Ressi。Ressi 是类似 PAX 的行列混合数据布局(Data Layout)。

F1 的新论文是 "F1 Query: Declarative Querying at Scale"。这一版论文中 F1 不再强调和 Spanner 的绑定关系,而是支持更多的底层存储。非常有意思的是,F1 也声称自己可以兼顾 OLTP 和 OLAP。

F1 底层存储


CockroachDB

按照时间顺序,在 Spanner 之后出现的 NewSQL 产品是 CockroachDB。CockroachDB 和 TiDB、YugabyteDB 都公开声称设计灵感来自 Spanner,所以往往会被认为是同构的产品。尤其是 CockroachDB 和 TiDB,经常会被大家拿来比较。但是,从系统架构上看,这两个产品有非常大的差别,先从 CockroachDB 角度来总结下。

最大的差别来自架构的整体风格。CockroachDB 采用了标准的 P2P 架构,这是一个非常极客的设计。只有 P2P 架构能够做到绝对的无中心,这意味着只要损坏的节点不超过总数一半,那么集群就仍然可以正常工作。因此,CockroachDB 具有超强的生存能力,而这也很符合产品名称的语义。

第二个重要差异是全球化部署。CockroachDB 采用了混合逻辑时钟(HLC),所以能够在全球物理范围下做到数据一致性。这一点对标了 Spanner 的特性,不同之处是 Spanner 的 TrueTime 是依赖硬件的,而 HLC 机制完全基于软件实现。

第三个点则是分片管理机制的不同。因为整体架构的差异,CockroachDB 在分片管理上也跟 TiDB 有明显的区别。

2020 年,CockroachDB 发表的论文 "CockroachDB: The Resilient Geo-DistributedSQL Database" 被 SIGMOD 收录。这篇论文对 CockroachDB 的架构设计做了比较全面的介绍。


TIDB

TiDB 也是对标 Spanner 的 NewSQL 数据库,因为开源的运行方式和良好的社区运营,它在工程师群体中拥有很高的人气。

不同于 CockroachDB 的 P2P 架构,TiDB 采用了分层架构,由 TiDB、TiKV 和 PD 三类角色节点构成,TiKV 作为底层分布式键值存储,TiDB 作为 SQL 引擎,PD 承担元数据管理和全局时钟的职责。

与 Spanner 不同的是,底层存储 TiKV 并不能独立支持事务,而是通过 TiDB 协调实现,事务控制模型采用了 Percolator。

作为与 CockroachDB 的另一个显著区别,TiDB 更加坚定的走向 HTAP,在原有架构上拓展 TiSpark 和 TiFlash,同时,TiDB 对于周边生态工具建设投入了大量资源,由此诞生了一些衍生项目:

  • Ti-Binlog 和 Ti-CDC 可以将数据导出,构建逃生通道或者实现数据分析。
  • Ti-Operator 可以更方便的实现容器云部署。
  • Chaos Mesh 支持混沌工程。

当然,TiDB 架构也存在一些明显的缺陷,比如不支持全球化部署,这为跨地域大规模集群应用 TiDB 设置了障碍。

与 CockroachDB 一样,TiDB 在 2020 年也发布了一篇论文 "TiDB, A Raft-based HTAP Database" 被 VLDB 收录,论文全面介绍了 TiDB 的架构设计。


YugabyteDB

YugabyteDB 是较晚推出的 NewSQL 数据库,在架构上和 CockroachDB 有很多相似之处,比如支持全球化部署,采用混合逻辑时钟(HLC),基于 Percolator 的事务模型,兼容 PostgreSQL 协议。所以,课程中对 CockroachDB 的介绍会帮助你快速了解 YugabyteDB。

为数不多的差异是,YugabyteDB 选择直接复用 PostgreSQL 的部分代码,所以它的语法兼容性更好。

可能是由于高度的相似性,YugabyteDB 与 CockroachDB 的竞争表现得更加激烈。YugabyteDB 率先抛出了产品比对测试,证明自己处理性能全面领先,这引发了 CockroachDB 的反击,随后双方不断回应。


OceanBase

从历史沿革看,OceanBase 诞生的时间可以追溯到 2010 年,但是那时产品形态是 KV 存储,直到在 1.0 版本后才确立了目前的产品架构。OceanBase 大体上也是 P2P 架构,但会多出一个 Proxy 层。

由于 OceanBase 是一款商业软件,所以对外披露的信息比较有限,期待 OceanBase 团队能够放出更多有价值的材料。


GoldenDB

GoldenDB 几乎是国内银行业应用规模最大的分布式数据库,和 TDSQL 同样在数据节点上选择了 MySQL,但全局时钟节点的增加使它称为一个标准的 PGXC 架构。

分库分表方案是一个长期流行的方案,有各种同质化产品,所以进一步演化出多少种 PGXC 风格的数据库很难历数清楚。借助单体数据库的优势,无疑会发展的更加快捷,但始终存在一个隐患。那就是单体数据库的许可证问题,尤其是那些选择 MySQL 作为数据节点的商业数据库。

MySQL 采用的 GPL 协议,这意味着不允许修改后和衍生的代码作为商业化软件发布和销售,甚至是只要采用了开源软件的接口和库都必须开放源码,否则将面对很大的法律风险。


小结

  1. 2012 年 Google 发表的两篇论文奠定了 Spanner / F1 作为 NewSQL 数据库开山鼻祖的地位。因为其中存储引擎、复制机制、分布式事务都在 Spanner 中实现,所以大家有时会略去 F1。而后,Spanner 演进为一个自带 SQL 引擎的完整数据库,并且同时兼顾 OLAP 和 OLTP 场景。
  2. CockroachDB 与 TiDB 都是 Github 上非常热门的项目,设计灵感均来自 Spanner。虽然两者在部分设计上采用了相同的策略,例如引入 RocksDB、支持 Raft 协议等,但在很多重要特性上仍有很大差距,例如全球化部署、时钟机制、分片管理、HTAP 支持程度等。
  3. YugabyteDB 与 CockroachDB 具有更大的相似性,导致两者间的竞争更加激烈。OceanBase 作为阿里的一款自研软件,整体风格上接近于 NewSQL,所以很多设计在原理上完全相同的。但由于商用软件的关系,开放的资料上远少于其他 NewSQL 数据库。
  4. PGXC 数据库是从分库分表方案上发展而来,而这一步跨越的关键就是通过全局时钟支持更严格的数据一致性和事务一致性。PGXC 具有架构稳定的优势,往往被视为更稳妥的方案,但单体数据库的软件许可证始终是 PGXC 架构商业数据库一个很大的法律隐患。
  5. VoltDB 和巨杉数据库是小众一些的数据库,在设计上采用了较为独特的方式,从而也带来了差异化的特性。

加餐:除了上述数据库之外,还有哪些有特点的分布式数据库?

FoundationDB 和 FaunaDB。

FoundationDB 是一个开源项目,而后被苹果收购后闭源,2018 年又重新开源。严格来说,它是一个支持 ACID 语义的 NoSQL 数据库,有比较独特的乐观并发控制。FoundationDB 可以通过上层的扩展可以支持更多的场景,而在增加了 Record Layer 后,它就成为一个关系型数据库,不过还不支持 SQL 接口。

对于 FaunaDB,它是一款商业数据库,从 NoSQL 逐渐过渡成为分布式数据库。FaunaDB 的理论原型是 Calvin,它和 Spanner 一样在 2012 年发表了 原型论文,被 SIGMOD 收录。虽然它们的目标都是提供强一致性的分布式关系型数据库,但设计思路截然不同。

FaunaDB

在 Calvin 的架构中设计了 Sequencer 和 Scheduler 两个组件。

其中 Sequencer 是基于锁机制为输入的事务操作进行排序,这样在事务真正执行前就能获得确定性的顺序,避免了过程中的无效交互和资源冲突。Scheduler 则是按照这个顺序执行,调度不同的事务执行线程完成最终操作。

这个设计思路被称为确定性并发控制,对应的数据库则称为确定性数据库(Deterministic Database)。

确定性并发控制算法的基本思路是,确保不同的副本始终能够获得相同的输入,所以就能独立地产生相同的结果,从而避免使用开销更大的提交协议和复制协议。通常,这类算法可以降低协调工作的通信开销,提高分布式事务的处理效率。而它的代价之一是无法为客户端提供一个交互操作过程,这就限制了它的使用场景。

目前基于 Calvin 理论模型的工业产品,似乎只有 FaunaDB。作为一种有代表性的分布式数据库,它值得我们继续关注。

此外,确定性数据库也是学术领域的重要研究方向。VLDB2020 收录的一篇论文 "Aria: A Fast and Practical Deterministic OLTP Database",就探讨了对确定性控制算法的优化方案。


学习资料

刘雷 等: 分布式数据库在金融应用场景中的探索与实践

Bart Samwel et al: F1 Query: Declarative Querying at Scale

David F. Bacon et al: Spanner: Becoming a SQL System

Dongxu Huang et al.: TiDB, A Raft-based HTAP Database

Jeff Shute et al.: F1: A Distributed SQL Database That Scales

James C. Corbett et al.: Spanner: Google’s Globally-Distributed Database

Rebecca Taft et al.: CockroachDB: The Resilient Geo-DistributedSQL Database


更新时间:2022-02-07 13:33:12

本文由 caroly 创作,如果您觉得本文不错,请随意赞赏
采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载 / 出处外,均为本站原创或翻译,转载前请务必署名
原文链接:https://caroly.fun/archives/分布式数据库十二
最后更新:2022-02-07 13:33:12

评论

Your browser is out of date!

Update your browser to view this website correctly. Update my browser now

×