
简介这份PPT围绕“新一代金融核心业务系统云架构”展开面向金融行业IT、保险科技及企业架构师讲解传统核心系统上云与PaaS化改造的方法论。内容从项目背景切入分析传统保险企业技术陈旧、扩展性差的痛点进而给出公有云/私有云/混合云的部署选择以及SaaS/PaaS/IaaS服务模式落地路径并以批处理平台为实例展示如何通过ZooKeeper、分布式并行计算、动态节点管理和多租户隔离实现Batch PaaS改造。全部内容共1个pptx文件包体大小2.58MB结构完整、逻辑清晰。已有91人学习浏览适合需要参考金融核心系统云化、批处理分布式改造或保险行业IT升级方案的读者。通过这份PPT可快速理解从老旧JSPServlet架构迁移到云平台的关键设计掌握任务拆分、故障自动转移及资源隔离的实践要点为自己的转型规划提供思路。1. 金融核心业务系统云架构从「跑在云上」到「长在云上」的关键一跳「新一代金融核心业务系统云架构」这几个字放在 PPT 封面上时通常配着三地机房、双中心互备、业务连续性链路这样的漂亮图纸。但真正把它落地时你会发现核心业务系统上云的意思并不是把小型机换成虚拟机、Oracle 换成开源数据库而是把整个系统的运行模式从「单体加集中存储」翻成「分布式加故障域自愈」。这里的核心业务系统指的是账务核心、支付清算、存贷款这类每天承载数十万笔联机交易、日终还要跑完批处理的系统它比一般互联网业务更在意一致性和可审计性。这篇笔记想讲清楚三件事云架构到底在解决什么、组件和参数怎么定、以及上线时最容易在哪个环节翻车。2. 老核心系统为什么必须动单体账务库里藏着的三个改造硬骨头2.1 小型机集群与集中式存储IOE 架构的扩展上限传统金融核心系统最常见的是 IBM 小型机加 Oracle 数据库加 EMC 集中存储的组合行业里叫 IOE 架构。它本身并不差数据一致性靠数据库的 ACID 事务保证高可用靠小型机集群加共享存储的切换实现多年的运维经验也足够成熟。问题出在扩展方式上IOE 架构的扩展是「竖着扩」——CPU 不够换更大颗的 CPU内存不够加板卡磁盘不够挂更多 LUN所有这些动作都有一个物理上限。当业务量涨到一台小型机的处理能力之外除了继续买更贵的机器没有别的出路。价格只是其中一个问题更现实的制约是数据库连接数、共享存储带宽和单库锁竞争。核心库里最热的一张账户表可能只有几亿行但每天有大量并发更新落在同一批账户上行锁竞争让 CPU 再高也跑不满。而云架构天然是「横着扩」的思维把数据按客户维度切开让每个分片只承担一部分账户的读写锁竞争被物理拆散扩展靠加节点而不是换大机器。2.2 日终批处理与强一致事务架构转型的第一道坎老核心系统有两个云架构最难承接的特性。第一个是日终批处理。银行核心每天营业结束后要跑结息、计提、总分核对、报表生成这些批量任务对单库的连续读写能力要求极高而且批次之间有严格的先后依赖。把数据拆分到多个节点后原来一个存储过程搞定的事情变成多个分片并行执行还要保证每个分片的结果最后能汇总平账这需要重写批处理框架。第二个是强一致事务。转账、记账这类操作要求要么全成功要么全失败余额不能多也不能少。在单库中这由事务机制解决应用代码只需要一条 commit。在分布式环境中一个交易可能跨两个分片事务从一个数据库事务变成跨节点分布式事务涉及两阶段提交协议性能和一致性要重新取舍。很多团队就是在这里被拖住的分布式事务框架选型、全局锁设计、对账补偿机制每一项都是新东西。2.3 云架构的目标形态无状态接入、单元化分片与三地多活理解云架构的目标形态核心是看三张图。第一张是部署拓扑图接入层、应用层、数据层分开部署接入层和应用层无状态可以随时扩缩容数据层按客户维度分片每个分片的主副本和从副本分布在不同可用区。第二张是数据流图一个请求进来后如何通过路由键找到对应的分片如何保证一次交易的所有读写都落在同一个分片内。第三张是故障切换时序图某个可用区整体宕机后流量切换到另一个可用区数据层如何保证不丢账。这三张图里最关键的是「路由键」设计。常见做法是按客户号或账号 hash 分片让同一个客户的所有业务数据落在一个分片内这就是单元化思想一个单元包含完整的接入、应用、数据能力客户流量按维度被路由到某个单元。下面这段伪代码展示了路由键的选取逻辑def route_key(account_no, customer_no, txn_type): # 核心原则一次账务交易内所有数据访问必须落在同一个分片 # 账户号交易按账号路由客户信息类查询按客户号路由 if txn_type in (debit, credit, balance_query): return sha256(account_no) % SHARD_COUNT else: return sha256(customer_no) % SHARD_COUNT class Router: def __init__(self, shard_count): self.shard_count shard_count def shard_id(self, key): # 一致性哈希的简化写法生产环境建议用一致性哈希环避免扩容迁移 return sha256(key.encode()).hexdigest() % self.shard_count路由键的选定直接决定后续所有改造的复杂度。账号和客户号两个维度至少要能互相转换否则会出现同一个客户的不同账户被路由到不同分片跨分片查询和跨分片事务随之而来。我一般在设计评审时会把这张路由表拿出来反复对因为后面所有中间件和迁移方案都建立在它上面。架构图上画得很轻巧的「按客户维度单元化」七个字落地时是几十张关联表的路由属性梳理。3. 新架构的组件选型与核心参数从拓扑图到能落地的配置3.1 接入路由层全链路灰度流量的网关参数接入层的任务是承接外部渠道的请求完成协议转换、鉴权、限流和路由转发。金融核心系统的接入层和互联网网关有个重要区别它不能随意丢弃请求超时和拒绝都要有审计记录所以网关的限流策略需要设计成「排队」而不是「丢弃」。常见做法是用分布式网关配合消息队列做请求缓冲同时在下游分片能力不足时快速降级到只读或简易应答模式。网关的核心参数第一个是各类超时时间连接超时、读超时、写超时。连接超时一般设 1 到 3 秒读超时要根据下游 TP99 的响应时间来定通常下游 TP99 的 3 倍以上避免频繁误判超时。第二个是熔断参数阈值设多少、滑动窗口多大。金融系统比互联网系统更保守错误率阈值我会设 5% 而不是 50%因为账务类接口错误一旦放大对账和客服压力会瞬间打满。第三个是路由缓存过期时间网关会根据路由键缓存分片位置但缓存过期时间太短会导致路由频繁失效太长又会在扩容迁移后把流量打到已迁移的分片。下面这段配置描述了一个最小可用的网关限流与熔断策略实际产品中通常用 YAML 管理route: # 分片路由规则按 account_no 前 6 位映射到分片表 rule: hash(account_no) % 32 cache_expire_secs: 300 ratelimit: # 全局限流基于令牌桶每秒放行 5000桶容量 2000 qps: 5000 capacity: 2000 # 排队模式拒绝比例太高时自动降级 mode: queue circuitbreaker: # 滑动窗口 10 秒内错误率超过 5% 触发熔断 window_secs: 10 error_threshold_percent: 5 # 熔断后半开探测间隔 half_open_interval_secs: 10这些参数不是抄一遍就能用的。QPS 数值要根据压测结果标定错误率阈值要看「业务错误」和「平台错误」的区分业务校验失败不能计入熔断错误。我在项目里见过网关把余额不足这类业务错误算进错误率导致正常业务高峰期触发熔断整个柜面渠道直接不可用这个坑后面章节还会细说。3.2 计算层核心微服务的容器化资源参数核心服务拆成微服务后跑在 Kubernetes 上服务需要哪些容器资源和弹性策略是这一层最重要的决策。核心交易链路对延迟敏感不能像离线任务那样等冷启动扩容。常见做法是给交易类服务配置最小副本数平时就保持足够的冗余弹性阈值设得相对保守只有超过 70% CPU 或内存水位才扩容避免频繁扩缩容引起连接池反复重建。服务调优的第一件事是 JVM 参数。核心服务多数用 Java 开发堆内存设置过大或过小都会出问题。堆设得太大GC 停顿时间变长账务交易的 TP99 会抖动设得太小则频繁 Full GCCPU 飙升。我一般把堆上限设为容器内存的 50% 到 60%剩余留给 Metaspace 和堆外内存、线程栈。下面是一个最小化的 Kubernetes 部署片段包含资源水位和弹性策略apiVersion: apps/v1 kind: Deployment metadata: name: account-core-v2 spec: replicas: 12 strategy: # 核心服务用 RollingUpdate但 maxSurge 不能太大 rollingUpdate: maxSurge: 2 maxUnavailable: 1 template: spec: containers: - name: account-core image: registry.local/account-core:2.4.1 ports: - containerPort: 8080 resources: requests: cpu: 2 memory: 4Gi limits: cpu: 4 memory: 6Gi env: - name: JAVA_OPTS value: -Xms2g -Xmx3g -XX:MaxMetaspaceSize512m -XX:UseG1GC - name: DB_MAX_POOL_SIZE value: 50 --- apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: account-core-hpa spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: account-core-v2 minReplicas: 12 maxReplicas: 30 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 70Java 容器一个常见的坑是容器限额和 JVM 默认堆的关系老版本 JVM 默认堆是物理内存的 1/4容器限了 6Gi 但 JVM 可能按整机内存算堆大小导致超出 cgroup 限额被 OOM Killer 干掉。现在的主流 JDK 版本已经能识别 cgroup但我仍然建议显式设置 Xms 和 Xmx 而不是依赖默认值。数据库连接池参数也要跟容器副本数联动50 个连接乘以 12 个副本就是 600 个连接数据库侧必须能容纳这个量级这两边经常各调各的最后连接数一起爆掉。3.3 存储层分布式数据库的复制与一致性参数存储层是核心系统上云最关键也最容易出问题的地方。金融核心通常有两种选择一类是基于开源数据库自建比如 MySQL 加分布式中间件另一类是直接使用原生分布式数据库它们有几个共同的核心参数需要关注。第一个是副本数和复制模式。金融核心至少要有同城两副本加异地一副本同城副本用于高可用切换异地副本用于灾难恢复。复制模式上强同步和半同步之间的选择会直接影响交易延迟强同步保证任何一笔交易在主副本和从副本都落盘后才返回延迟增加明显半同步则允许延迟累积。账务核心我建议主副本和同城从副本之间用强同步或者类强同步协议异地副本可以做异步但要能承受一定延迟。第二个是分布式事务一致性级别。如果交易的多个数据项分布在同一个分片内事务还是单节点事务性能损失可以接受。一旦跨分片需要全局事务管理这会明显拉高延迟。下面的参数表是存储层几个关键设置的推荐范围和原因参数推荐范围说明同城副本数2一个主副本加一个同城从副本兼顾切换速度和成本异地副本数1容灾用异步复制即可太多会拖慢日志同步复制确认方式同城强同步 / 异地异步账务主库同城必须落盘确认异地允许延迟日志同步超时3 到 5 秒超过后自动降级为异步避免单点故障拖垮主库分片预热线程数4 到 8扩容分片后需要预热缓存和连接池过高会压垮新节点第三个是存储引擎的磁盘能力监控。云架构下数据库跑在云盘上云盘的 IOPS 和延迟与本地盘有明显差距。我们压测时遇到过一个情况单分片 TPS 上不去排查到最后是云盘排队深度打满数据库的 redo 日志写入成为瓶颈。所以存储参数里至少要留出对磁盘队列深度、写延迟的监控并预先做一轮独立 IO 压测别等数据库全线预警了才回头查磁盘。4. 两种迁移路径分布式中间件替换与单元化重建怎么选4.1 路径 A以分库分表中间件为代表的技术栈替换第一种路径保留原有的应用架构和业务代码只在数据访问层引入分库分表中间件把单库拆成多库多表。这种方式的优点是改造量小、上线快适合业务逻辑极其复杂、短期不可能重写的存量系统。缺点也明显应用代码里潜在的跨库 SQL、分布式事务、依赖单库特性存储过程、视图、触发器的地方都会变成雷区。实施时先做表结构梳理把表分成拆分表、广播表和全局表三类。拆分表按业务的客户维度路由广播表是字典类数据每个分片都复制一份全局表是极少数不能拆的小表放在固定节点。中间件负责拦截 SQL 并改写路由应用层改造成本最小。下面是一个典型的分片规则配置片段rules: - table: account_balance actualDataNodes: ds${0..31}.account_balance_${0..7} databaseStrategy: standard: shardingColumn: customer_no shardingAlgorithmName: customer_hash_mod tableStrategy: standard: shardingColumn: account_month shardingAlgorithmName: month_mod - table: code_type actualDataNodes: ds${0..31}.code_type broadcast: true配置里的关键在于分片字段的选择和分片算法的一致性。custome_no 作为数据库分片键account_month 作为表分片键这样按月查询可以走单表扫描跨月查询则要聚合多个表。注意算法名称里的 mod 必须是同一个哈希算法实现生产环境出现过两个环境 hash 算法不一致导致部分数据路由错位对账差了几百万。迁移这个路径时数据从旧库到新库需要先全量同步再增量追平中间用双写解决灰度期的新增数据这部分会在后面的切换小节展开。4.2 路径 B按客户维度的单元化重建第二种路径是推倒重来按单元化思想重新设计应用和数据架构每个单元是一套完整的服务集合单元间通过异步消息解耦。这种做法的改造量最大、周期最长但长期收益也最大适合有足够资源、且旧系统债务已经重到难以修修补补的场景。单元化重建的核心设计是「单元内闭环」一次客户请求涉及的读和写尽量都在同一个单元内完成。单元化的划分维度通常是客户号选定了维度之后所有服务的数据访问都要约束在这个维度内。比如查询一个客户的所有账户可以从客户号直接定位单元但如果是跨客户的批量操作比如代发工资涉及多个客户就得设计成异步任务拆分成单客户操作再汇总结果。这个约束会迫使业务团队重新审视每一个服务接口的入参设计是改造中最耗时的部分。单元化重建的技术栈可以选云原生分布式数据库。这类数据库天然支持按维度分片分片可以打散在不同可用区。迁移到一个全新架构时我一般会先把新系统的账务能力做成一个最小闭环只迁移一类客户或一个渠道的流量跑通后再逐步扩大。新老系统并行期间两边同时记账以老系统账为准每日做总分核对连续核对通过后才切换。这个过程很像把一块表从一个仓库搬到另一个仓库先搬一小部分货确认新旧库存一致再搬剩下的。4.3 灰度切换与回退机制设计无论哪条迁移路径灰度切换都是最后一道闸门。核心系统的切换不能像互联网应用那样简单地按用户比例放流量账务系统哪怕只有一分钟的不一致后续对账和冲正都很痛苦。常见做法是按「分片维度」灰度先选择某个分片或某一批客户让这些客户的流量切换到新系统其他客户仍走老系统两边并行运行并每日核对余额和流水。灰度切换的前提是双写机制。新老系统并行期间一笔交易既要写入老系统也要异步写入新系统写完后进行核对。核对分两层流水级核对逐笔对比交易流水号、金额、账户余额级核对按科目或账户汇总对比。下面是一个简化版的双写切换编排脚本控制流量比例和回退判断def switch_flow(shard_id, ratio, global_switch): 将某个分片的流水分流到新系统 ratio: 0.0 到 1.0表示放给新系统的比例 global_switch: 全局开关只在核对通过后打开 if not global_switch: print(fshard {shard_id} skipped, global switch off) return if shard_id in GRAY_SHARDS: # 灰度分片按比例放流量 target_ratio ratio.get(shard_id, 1.0) if random.random() target_ratio: route_to_new_system(shard_id) else: route_to_old_system(shard_id) else: route_to_old_system(shard_id) # 回退判断条件新系统错误率 1% 或对账差异金额 阈值 if check_consistency(shard_id) is False: rollback_shard(shard_id)回退机制中有一条铁律回退操作本身不能引起新的不一致。如果新系统已经处理了一部分交易并记账回退时要把这些交易在新系统中的状态标记为「已迁移待对账」而不是直接删掉否则会出现账单缺失。所以切流之前一定要先把回退方案推演一遍切了哪些分片、新系统写入了哪些账户、回退时怎么处理这些账户的后续交易、老系统能不能接住这些账户的余额变更。这些问题在切换演练中全部要过一遍。5. 云架构部署的常见坑与排查五条一线翻车记录5.1 对账差一分钱分布式事务补偿不完整现象灰度切换后第二天日终对账总账科目新增余额比明细流水汇总多了一笔金额不大但就是不平。原因一笔跨分片交易中第一个分片的扣款成功后第二个分片的入款操作因为超时被判失败本地事务已经提交没有可靠的补偿机制。解决账务类操作不能依赖最终一致的异步补偿必须使用带可靠补偿的事务方案。我们把所有账务交易改成「先预占、后确认」的模式同时在每个分片做本地事务日志对账脚本按预占单号逐笔核对发现超时未确认的预占当天自动冲正。5.2 高峰期数据库连接池被打满现象业务高峰时段交易超时率上升排查发现数据库活跃连接数触顶应用日志大量报获取连接超时。原因连接池参数和数据库侧参数没对齐。应用连接池的 maxLifetime 设成了 30 分钟数据库 wait_timeout 是 10 分钟数据库回收了连接但应用池不知道拿着失效连接去请求重新建立连接的开销在高峰期集中爆发。解决统一各组件参数连接池 maxLifetime 必须小于数据库 wait_timeout同时设置连接池的最小空闲连接数并开启连接池的 leak 检测。下面是我们在生产环境固定下来的一套连接池参数spring: datasource: hikari: maximum-pool-size: 50 minimum-idle: 10 connection-timeout: 3000 max-lifetime: 600000 # 数据库 wait_timeout 设为 900 秒留出缓冲 leak-detection-threshold: 300005.3 缓存雪崩打垮下游数据库现象某缓存集群一个分片节点宕机后大量请求直接穿透到数据库数据库连接数快速飙升连锁引发其他分片的缓存也失效。原因热点缓存集中在少数分片节点故障又没有做请求收敛所有穿透流量同时打向数据库。我们在缓存设计中偷懒用了统一的 key 前缀导致同尾号客户缓存集中在同一个分片。解决缓存 key 增加随机后缀分散写入热点数据在应用本地维护一层短时缓存穿透时用分布式锁限制并发回源数量节点故障时先把流量切换到其他可用节点而不是任由穿透打到数据库。5.4 日终批处理在分布式下越跑越慢现象分库分表后日终跑批的时间从原来的 1 小时变成 2 小时而且每增加一个分片耗时反而上升。原因批处理任务仍然按老方式串行执行但每一步都要跨分片汇总数据分布式协调开销超过了并行收益部分批任务在分片间产生大量跨节点数据传输。解决重写批处理调度让每个分片先本地处理、本地汇总最后只上送汇总结果跨分片依赖的任务改成多阶段流水线用消息队列缓冲阶段间数据。调整后日终跑批从 2 小时降回了 40 分钟关键在于批处理逻辑必须按分片边界重切不能保留原来的全局视角。5.5 压测通过、上线翻车磁盘性能的假象现象压测环境所有指标都达标正式环境一上线核心交易 TPS 直接掉了三分之一。原因压测环境数据库用的本地 NVMe 盘生产环境用了云盘两者的 IOPS 和写延迟差距达到数倍。压测时只关注了数据库层的 TPS没做磁盘层的基准测试。解决上线前对生产存储做一轮独立压测分别测顺序写、随机写和读写混合场景把预期负载下的磁盘队列长度和 P99 延迟记录在案同时把影响时延的刷盘策略调成同步提交确保账务日志真正落盘。云盘和本地盘的差距属于物理差异不能靠参数完全弥补选型阶段就要定清楚。6. 上线验证与进阶把故障演练变成团队的肌肉记忆架构到位的最终证明不是评审通过而是故障发生时系统能按设计收敛。我见过太多方案在 PPT 上逻辑完美一断电就现原形。验证工作建议分三步做。第一步是全链路压测不只是打接口要模拟真实业务配比查询、转账、开销户、日终批量混跑同时记录 TPS、TP99、错误率和数据库连接数。压测过程中人为制造分片故障观察故障转移时间和恢复后的数据一致性。这里的关键指标是 RPO 和 RTO账务系统允许丢多少数据、多长时间内恢复服务这两个数字必须比业务方定的底线更好。第二步是对账演练。每天日终后新老系统跑一遍总分核对和流水核对连续跑一到两周不能有差异。对账逻辑不要只用「总数相等」这种粗粒度校验要按账户逐笔比对一旦出现差异哪怕只有一分钱也要当天定位根因。核心账务系统的信心就是这么一天天积累起来的而不是靠一次大版本发布。第三步是故障注入和回退演练。定期随机杀掉一个分片的节点、断掉一条网络链路、模拟机房断电观察系统是否按预设计划切换运维人员的操作手册是否真的能跟上。这里我有一条踩过坑的教训故障演练要在业务低峰做但一定要用真实流量不能只在测试环境自娱自乐否则演练的是「理想状态下大家不紧张的应急流程」真出事时现场一定比预想混乱得多。我自己的习惯是核心系统上线前的最后一周每天下班前把团队叫在一起过一遍同一个问题如果现在这台机器原地消失账能不能平。这件事看起来很笨但它帮我们发现过不少配置疏漏。核心业务系统的云架构转型技术方案固然重要但真正决定成败的往往是这些「笨功夫」。希望这些思路能帮你在自己的项目里少走一段弯路。本文还有配套的精品资源点击获取