核心银行系统 之十七 批量任务

批量任务

账务处理子系统作为核心银行系统的系统内核,这使得账务处理子系统的设计和实现成为商业银行核心业务系统构建过程中的一个难点。作为核心业务系统的内核,账务处理子系统一般通过批量方式完成,故也称为批量处理子系统。在构成核心银行系统的四个基本子系统中,批量处理子系统处于核心银行系统的中间位置,起着承接业务处理子系统和会计报表子系统的枢纽作用,批量处理子系统在核心银行系统所处的位置如下图所示:

image.png

批量处理子系统是会计账务核算信息的集中体现,在设计中必须充分结合会计核算理论,充分考虑会计核算的发展趋势和业务发展的要求,把系统中具有共性和相对稳定的内容提炼出来,形成通用和能以不变应万变的核心账务处理系统,稳定性和适应性是账务处理子系统最重要和最基本的要求。 但是在数据逻缉集中及应用重构后由于系统架构的调整必然会影响原有批量的处理逻缉。例如,某商业银行批量流程总体架构没有大的变化,主要是在布局上按业务分区拆开,部分应用之间的信息交互需要改造为跨分区的方式。对于两个分区批量处理的流程调度通过 IBM 公司的 TWS 作业管理软件统一实现。为了保证个人分区和对公分区的系统时间的一致性,通过技术手段控制两分区同步日切,如果出现单分区宕机时,正常分区要等待故障分区恢复后才能同步日切,并进行后续的批量处理。

批量处理分类:

1、按所属数据库的不同区分,批量处理可分为:
  ·核心业务主机批量处理
  ·数据处理主机批量处理
2、按业务归属的不同区分,批量处理可分为:
  ·会计核算
  ·对公业务
  ·个人业务
  ·信用卡业务
  ·客户信息业务
  ·数据处理业务等
3、批量处理所完成功能的不同区分,批量处理可分为:
  ·统计分析功能
包括核心业务批量的总分核对与试算平衡的处理。日终、月终、年终的交易数据和账户数据的统计分析。
此外,统计分析功能也是数据处理主机批量的主要功能。
  ·交易补记账功能
同样也是批量处理的核心功能。除了日终的补记账、清算、外汇买卖和黄金买卖的平仓处理外,还包括根据计提的统计分析结果做的内部户划转、年终汇兑损益结转、年终决算等综合核算的处理。
批量的交易补记账功能在功能设计上是有着很大优势的,其最大的特点便是解决了内部户科目的热点问题,大大减轻了联机交易的负担,缩短了联机交易的响应时间。
  ·批量业务处理
包括批量代收代付业务、个人贷款到期还款、信用卡自动还款、定期自动转存、基金定投和结息处理等。
  ·对外系统的数据供应
外围的运营型应用和分析型应用,均需要从主机取得大量的交易数据和账户数据,进行后续的统计分析处理。对外围系统和应用的供数也是主机批量处理的主要功能,在整个批量处理中,对外系统的数据供应占据了较大的比重。
 ·数据移行处理
移行主要包括 3 部分的内容:
1)投产移行:
为版本投产准备的数据迁移,参数统一设置等处理。
2)功能移行:
包括本部机构调整、银行资产购入或资产卖出、客户信息整合等。
3)系统维护:
指针对生产中心常见的变更操作等所提供的批量工具。
4、按批量应用运行时间窗口的不同区分,批量处理可分为:
  ·日终批量
  ·日间批量
  ·投产移行批量等

总体而言,批量处理的 5 大功能划分与运行时间窗口的划分并非一一对应的。批量业务处理主体是在日间批量中,但是为了更多的避免与联机交易的冲突,实际当中同样会在日终批量作业中安排大量的批量业务处理。对外围系统供数是日终批量的主要功能,但数据处理主机的日终批量运行时间实际已经是白天,甚至包括核心银行主机,也存在因为业务数据时效性性要求,在日间也有对外围应用的数据下载处理,所有这些,无疑对批量处理的性能与效率提出了极高的要求。 批量处理的功能与结构,简单的图示表示如下:

image.png

批量作业调度架构设计

image.png

START1 到 STARTN,表示日间批量处理的起始作业,这些批量大部分是独立存在的,前后关联比较少,各个应用批量流程的作业可以各自开始和结束。
STRATAD 中 STARTJOB,表示日终批量的起始作业,不同应用业务的日终批量均紧跟这个作业之后开始运行。
应用作业,表示各自业务的批量处理作业,各应用系统间互不干扰,各自运行。
关联作业,表示各自业务的批量处理间,存在等待关系的作业,应用间的等待关系,依靠关联作业标识其是否已经完成或是否可以开始。
ENDAD 中 ENDJOB,表示日终批量的结束,日终所有作业均需要关联到该作业上。数据备份作业可以选择在该ENDJOB 作业结束后开始运行。
OSTART1 到 OSTARTN,表示运行在上午的日间批量的起始作业,类似START1-STARTN。

应用系统批量划分

在并行批量的设计中,各应用的业务功能自有边界是首先可以考虑的并行划分依据。各类业务功能的自然划分,为此类批量处理的并行提供了现成可用的方法,以某商业银行的业务范围划分方法,日终的批量处理,可划分为如下几大类:
1、业务支持类应用:
如核算、清算、资产管理等,为各经营类业务功能提供支持的应用,可归做一类。
2、业务功能类应用:
如个人零售、个人贷款、个人信用卡、对公贷款、对公存款等,各类面向具体客户的经营类业务应用,应用间有明显的划分边界,可归做一类。
3、数据处理类应用:
数据统计、筛选、下载等不直接包含对客功能的业务应用的批量处理,可归做一类。
从应用归属的不同,进行日终批量功能及并行批量的设计,则日终批量功能可划为如下较为独立的几块:

image.png

需要注意的几个问题:
1、按业务应用划分批量处理,应在业务范围的边界下做划分,即首先尊重业务在功能、管理上已有的划分。
2、各应用系统的划分和独立,并不意味着各应用系统间不再存在关联关系,需要从业务功能与技术处理等多个角度,发掘出内部潜在的前后关联,避免遗漏。

并行批量实现方法

传统的批量处理,所有的数据依次顺序处理完毕,我们可将其数据分成几个大小均等的单位并行地进行处理。每个单
位数据的处理方式和业务功能,都基本与原来依次顺序处理的方式一致,不同的地方是,原来由一套作业完成表中所有数据的处理,现在由多套处理逻辑相同的作业流并发来完成,数据处理的效率将得到大幅的提升。

image.png

第一步:对数据库表进行分区

为什么要对进行数据表分区呢?当由多套作业流并发地发起对数据库表的处理时,面临的最大技术障碍是在数据页、索引页上的访问冲突。要避免并发访问冲突,则需要将数据分成若干独立的分区进行物理存储,这样并发访问数据时,不会因为访问到相同的数据页(由于相同表的不同 PARTITION 使用不同的物理存储文件),避免了因访问冲突而导致的程序死锁中断或超时中断。

数据分区的方法有很多,可以按不同的业务功能归属分,可以按交易产生的时间分,也可以按银行分户账的归属、业务客户的归属等做区分。在金融行业的信息系统中,选择机构代号(俗称地区号)作为数据分区的基准,具有以下两点突出的优势
1、在金融信息系统中,机构号是金融业务核算的基本单位,以机构号做划分,则每套批量作业流程处理的数据基本是一个较为独立的单位,与其它数据之间不存在关联性,每套作业流基本可以独立运行互不干扰。
2、在金融信息系统中,机构号广泛出现在各类数据存储中,其存在的普遍性和易识别性,也决定了其作为分区标准的客观特性。
在目前流行的关系型数据库中,例如: DB2 、ORACLE 都支持数据分区存储的策略,只需要通过表空间参数定义,为每个数据分区定义一个分区标准区间(最小值和最大值)。当有新的数据进入时,数据库会自动根据设定的参数值,将新数据存储到指定的区域,这个过程不需要人为干预。

第二步:建立批次的对应关系

当对数据以“机构号”完成了分区存储(PARTITION)后,我们面临的是如何建立批量单位与数据间对应关系的问题。
这样我们需要以“机构号”为基础,建立《机构号与批量单位对应表》参数表,通过该参数表,完成批量单位到机构号,也即分区数据之间的对应。对应关系具体可参考以下示例:

image.png

上表中的批量单位 001,对应的机构号是 0001 和 0010 之间的所有机构,而批量单位 002,对应的机构号则是 0011 和 0020 之间的所有机构,批量单位003 类似。
那么根据什么来确定一个批量单位处理多大的“机构号区间”的数据,如何确定适合的并发的批量单位个数呢?我们可按如下的方法:

1、保证不同批量单位间无交叉:并行批量的设计基本原则,即是不同批量单位间不会发生并发访问的资源冲突问题,如此,在数据和批量单位规划上,应注意不同的批量单位,不会访问到相同的数据分区的数据。
2、确定单个批量单位处理容量:机构号作为数据划分的基础,决定了最小的批量单位的处理量即是一个机构的数据,如此,可对需要处理的数据分机构号做统计,按最小数据分区的数据总量不小于单个最大机构数据的方法,确定单个批量单位的处理容量。
3、不保持同批量单位数据均衡:根据短板理论可知,要提高系统整体的运行效率,就需要保证各个批量单位的数据基本均匀,如此各批量单位的运行时间才能基本相同,进而达到最大程度优化整体批量目的。
4、最终确定并发批量单位总数:每个批量单位的处理容量确定后,由于总的数据量是基本固定的,这样即可确定并发批量单位的总数。

第三步:建立数据访问的模式

一个批量单位就是一套完整的作业流,作业中通过调用相应的应用程序来完成既定的业务功能。如何让每套作业流按《机构号与批量单位对应表》设定的对应方式访问数据呢?
我们通过改造批量作业流,在作业流输入中为每套作业流分配一个特定的编号文件,通过对应的处理程序,根据作业流中输入的批量单位编号信息,结合《机构号与批量单位对应表》参数,在编号与数据分区之间,建立起对应关系,进而可以在程序内指定数据访问范围。具体范例如下:
1、传统应用程序访问逻辑:
SELECT * FROM TABLE_A WHERE COLUMN_A = ? AND COLUMN_B = ? ……
2、并行批量的程序访问逻辑:
SELECT * FROM TABLE_A WHERE ‘机构号’ BETWEEN 最小机构号 AND 最大机构号 AND COLUMN_A = ? AND COLUMN_B = ? ……
按照上述的改造方法,经过对作业流和应用程序的简单改造,可以实现仅在作业流中指定批量单位信息,即可按照《批量单位与机构号对应表》设定的对应关系,并行地对海量数据做分批快速处理。

第四步:参数化设定批量单位

经过以上的改造,作业流和应用程序并发运行的条件已经具备,下面介绍参数化设定批量单位的方法,以减少作业及程序的开发和配置工作:
1、改造传统的批处理作业,在作业名的编排中,增加批量单位(编号)信息。
2、改造作业流,为每个作业步增加流内数据,定义本套作业流对应的批量单位编号。
3、在实际运行前,按设计好的批次数量,展开作业流,并完成作业流内批量单位编号的参数化工作。
通过以上步骤,各并行单位的作业即可快速建立,未来新增批次,也可按此方式完成快速的扩展。

第五步:并行批量作业的提交

通过以上的手段,在静态上建立了多个批量单位,在日常的生产运行中,如何能够更准确高效地控制和管理并发作业?
传统的批量处理方式,往往由经过专业培训的运行操作员,通过远程终端,按既定的作业排程要求,进行单个作业的逐一提交。传统的手工提交方式,不论是在工作量上,还是在准确度上,都存在诸多缺陷。随着计算机技术的提高,陆续出现了自动化调度作业的专业软件,比如 IBM 公司的 TWS 作业管理软件。 并行批量模式下,作业的数量,及批量作业排程都变得更加复杂,更加需要专业软件来管理和控制作业的运行。由于各个批量单位中的作业可以同时提交,所以同样可以通过 TWS 来完成这一复杂的工作,其原则和设计方法,与传统批量的方式是基本一致

随着业务的高速发展,或会出现新增机构或拆分机构的需求,伴随而来的,即是新增批次的需求,在这个情况下,我们只需要增加《批量单位与机构号对应表》,根据业务要求新建对应关系,即可快速地扩展批量单位,快速完成新增机构批量系统需要完成的技术准备工作。

image.png

核心批量流程优化

以某商业银行核心日终批量流程为例,目前日终批量的关键路径大致的流
程图如下:

image.png

围绕日终批量关键路径,可主要包括如下优化点:
1、增加上一日日结业务的收口

收口如昨日日结收口的作业包括如下:
日切后,日志解析前必须完成的业务;
日志解析;
补账处理,总账更新;
总分核对、试算平衡处理。

2、提前数据备份处理时间
上一日日结业务之后,即开始数交的备份恢复,将数交批量的处理进一步提前。
日终批量的关键完成时间点,可设计如下:
上日业务记账完成:日切后,日志解析前处理的上一日业务,总体运行时间控制在 30 分钟内。
上日业务处理完成:日切后,所有上日业务完全完成入账等处理,总体运行时间控制在 1.5 个小时内。
日终批量完全结束:可要求所有应用的批量处理时间控制在日切后 3 小时内。
按照上述 3 点整体时间控制的要求,各应用科学地规划各自应用批量的作
业执行流程,规划后的日终批量大致的流程图如下:

image.png

移行分类

按照移行的目的区分

投产移行:项目或系统的投产,需要完成的数据迁移或数据结构的调整。投产移行的主要特点是一次性。对于投产移行,在设计时可以考虑停联机处理。而且程序设计时,在实现断点再续有困难的情况下可以考虑使用备份表的方式处理程序的中断。

功能性移行:主要是实现自身的数据按一定规则要求的迁移。与投产移行相反,功能性移行往往是多次的。或者是不同地区顺次进行的移行。功能性移行最重要的一点,是必须支持联机 24 小时。

按照移行的对象区分

数据移行:移行的对象是数据,主要是完成数据的迁移。包括:旧系统到新系统的数据迁移;他系统到我行系统的数据迁移;同系统内部移行,包括不同数据结构间的数据迁移,或数据自身的属性发生改变;我行自身不同系统间的移行。数据移行往往需要分行技术人员或者业务人员的配合进行。

结构移行:因数据结构发生变化而做的移行。结构移行对分行依赖程度较小。

应用程序移行设计

目前主要分静态程序移行和动态程序移行。静态程序适用与通常情况下的移行;而动态程序移行适用于当移行有大量的针对不同数据结构的相同操作的情况。移行程序往往具有一次性,即程序往往只运行一次。正是因为其仅运行一次,所以成败的关键就全系于其一身,因此做移行程序设计的时候,一个最重要的原则是力求移行程序的尽量简单,避免移行程序因为过于复杂而在编码时出现各类意想不到的错误。

移行的处理流程

移行的流程根据移行对象和移行要求的不同而不同。当移行是针对某一个数据库表进行的,完成的数据库表内部的数据的属性变化(这些属性通常不是索引)。往往采用的是直接更新的方式进行。例如以前投产项目中的个人账户表的移行,需要将取款人的证据类型、证件号码、户名等内容进行更新的情况,系统设计时是采用一个程序直接完成这个表的相应字段的更新。还有一种移行的处理流程是采用的比较多的而且较为通用的模式,即表->文件->表的处理流程模式:

image.png

这种模式是最通用的模式,尤其使在不同系统之间进行移行或者在同系统的不同数据库对象之间移行时,往往采用这种模式。 表->文件->表的移行魔术,具有如下优点:
  1. 该模式流程清晰。将复杂的移行功能分为多步进行,使每一步的处理尽量简化;
  2. 应用程序对断点再续的实现更为容易。
  3. 对于数据的修改,转换,可以在移行中间文件上进行。因为主机对文件的操作处理的效率远远大于对数据库表的处理效率。所以如果移行的转换处理较为复杂的情况下,采用在中间文件上进行转换,可以在一定程度上缩短程序移行的时间。
  4. 移行优化考虑发挥的余地较大。在由表到文件的过程中,可以对表进行顺读,增加应用的异步 I/O。在由文件到表的过程中,可以先对文件按照导入表的 PI 排序。这样,一方面,顺序插入,使得插入过程中,数据库对表的索引维护开销较小,提高数据导入数据库表的效率;另一方面,文件导入表之后,表内的数据不需要做 REORG便已经是顺序排列。避免了在移行完成之后,对表的维护。

移行的时间点考虑

移行可供选择的时间点包括:日切前(日间)、日切后批前、批后。其中日切前(日间)同批后在时间点上是相同的,只是由于参照物不同导致的叫法差异。总结以往的移行,绝大多数的移行都是选择在批后进行。
在时间点的选择上往往需要考虑的因素包括:
1、 版本投产的要求,尤其对与投产移行的程序,通常选择版本投产停联机的时间进行,绝大多数的情况是批后;
2、 移行数据量的考虑,比如对联机结算类日志的移行,往往选择在批后,因为此时联机结算类日志的数据量是最小的。
3、 移行当日批量的考虑,主机的日终批量往往有时间要求,移行往往不能使得主机批量的推迟,否则会影响当日日终报表下传的时间。考虑这一点,移行往往选择在批后,而不在批前。
4、 仅当少数的情况下,移行有着特殊要求,且移行时间不长的情况,需要选择在批前移行。例如,移行的目的是完成参数表的修改,而这个参数表在日切后的新工作日内,需要联机使用移行后的参数表的情况,则需要在日切后,批前完成移行,重新下载参数表。

工行的核心批量

image.png

image.png

数据库分区(PARTITION):将一个数据库表空间分成多个独立的存储单元,每个存储单元就叫做一个数据库分区(PARITION),每个 PARTITION 都对应一个单独的物理文件,但是多个分区在逻辑上构成一个完整的 table。 并行耦合体:并行耦合体是指多个系统共享同一套系统文件,在不同的机器上运行。多个系统互相协作,进行负载均衡,互相备份,而且系统具有良好的扩充性,提供了充足的系统资源,满足日益增长的数据处理要求。

PARTITION 划分原则

image.png

根据上述表的 PARTITION 划分情况,给出应用整合后表的 PARTITION划分设计,主要包含以下四大类:

  1. 表不分 PARITITION
  2. 分 PARTITION 的小表:表分 24 个 PARTITION
  3. 数据量大表:表分 47 个 PARTITION
  4. 数据量特大表:表分 206 个 PARTITION

逻缉整合后 PARTITION 的划分遵循以下原则:

需要划分 PARTITION 的表有两大类:

  1. 并行批量涉及的表。
  2. 表数据量大于 2G,根据数据量增长估计将来会超过 4G 的表。另外,表记录数如果超过 500 万(如果记录长度为 400,数据量为 2G),可以考虑划分 PARTITION。

PARTITION 大小:

  1. 划分 PARTITION 后,每个 PARTITION 的大小不超过 2G。随着生产运行,如果 PARTITION 大小超过了 3.5G,考虑把该 PARTITION 细分为 2 个。

PARTITION 个数:

  1. 为了日常版本安装时,维护方便,减小维护工作量,对因为并行批量要求分 PARTITION 的小表,在 PARTITION 个数上保持统一,并且和并行批量单位相适应。对因为数据量特别大的表,在PARITION 个数上也保持统一。
  2. 对大数据量表尽可能做到南方和北方的数据分在不同的PARTITION 中,以达到以下目的:
    1在数据回装时,南北数据可以同时回装,获得最好的并发效果,有利于数据移行。
    2有利于并行批量单位划分。
    3可以避免某个 PARTITION 因为南北方数据叠加,而超过 4G。
    4保证文件数量基本和目前南北中心的 DB2 文件数量相当,不会有很大的增长。
  3. 小表定义:现在生产环境,南方片分 18 个 PARTITION 的表,北方片分 27 个 PARTITION 的表。
  4. 大数据量表定义:
    1 现在生产环境,南方片分 PARTITION 个数超过 18 的表,北方片分 PARTITION 个数超过 27 的表。
    2现在北方片分 PARTITION 27 个或南方片分 PARTITION 18 个的表,但有的 PARTITION 数据量超过 2G 或记录数超过 500 万,并有可能继续增加,需要细分 PARTITION 的表。
  5. 整合目标生产环境 PARTITION 数量:
    根据上面几个 PARTITION 个数方面的原则,应用整合后小表统一划分为 24 个 PARITION,大数量量表统一划分为 47 个PARTITION,数据量特大表划分为 206 个 PARTITION。

并行批量单位划分原则

并行批量单位的划分直接影响小表 PARTITION 的划分。并行批量单位的划分原则是:保证各个批次需要的处理的数据量基本均衡,并且处理的数据量和目前生产上一个批次处理的数据量基本相当,以保证并行批量的运行时间基本和现在生产上的运行时间差不多。目前南北方片批次的划分情况是:北方片 8 个批次、南方片 9 个批次,另外还有:总行、卡中心、香港分行 3 个特殊批次。数据逻缉整合后批量单位划分情况如下:普通分行分 16 个批次,另外还有:总行、卡中心、香港分行 3 个特殊批次。具体情况如下表:

image.png

image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容