亿级订单系统分库分表技术方案和Flink数据同步方案

本文探讨了公司订单系统面临的挑战,如数据量增大、并发压力和扩展性问题。提出了解决方案,包括合并主键、使用分库分表、将OLTP数据同步到OLAP、清洗和标准化旧数据、以及选择ShardingSphere-JDBC作为分库分表工具。还讨论了不同ID生成算法和分片策略的优缺点。

一、需求背景

随着公司业务的发展,订单系统的数据量和访问量日益增长,单库单表的架构已经无法满足我们的需求。主要面临以下问题:

  1. 数据量大:单一数据库存储所有订单数据,导致数据量过大,影响查询效率。
  2. 并发压力大:大量用户同时访问系统,产生高并发请求,对数据库造成较大压力。
  3. 扩展性差:当需要对订单表进行改动时,大量的数据造成表结构修改时间变长

二、业务现状

  1. 订单表有主键orderId和唯一索引orderNo,orderId依赖数据库自增,orderNo自定义生成并且后4位为类用户id,内部场景用orderId进行数据传递,外部场景用orderNo进行数据传递

解决方案:去除数据库自增,将orderId和orderNo进行合并,将自定义编号作为唯一主键,内外部场景全部采用orderNo进行数据传递

  1. 订单表超过10个索引,部分索引用于C端场景,部分索引用于B端场景

解决方案:将OLTP中的订单数据同步到OLAP数据库中;确保所有C端场景能够命中分库分表的分片键;将B端分析场景进行剥离,例如查询订单列表,在OLAP数据库中进行查询,再根据订单主键CRUD时,再走OLTP数据库

  1. 订单表中存在部分老数据,老orderNo没有采用后4位是类用户id,并且老orderNo中可能存在字母

解决方案:借助Flink将老订单编号数据进行清洗(数据清洗技术方案另行商议),统一采用现有订单编号规则

  1. 订单表存在一些拓展表,比如订单位置、订单申诉记录等,有些采用orderNo进行关联,有些采用orderId进行关联

解决方案:和第1点一样,统一采用主键进行关联,并且需要保证关联字段为分片键。如果有分库,最好将拓展表也进行分库分表,并且需要保证拓展表的分库分表规则和原表一致

  1. 订单表中字段过多,有计费、开票、退款等非核心数据

解决方案:考虑纵向拆分,可以考虑这几个方面:是否核心、更新是否频繁、字段长度是否过大

三、技术选型

1、分库分表和分布式数据库对比

理解普通数据库、分布式数据库、云原生数据库、云原生分布式数据库区别

  • 普通数据库:通常采用传统的垂直架构,由单一的数据库服务器提供数据存储和查询服务。
  • 分布式数据库:采用水平分片的方式,将数据分散到多个数据库服务器上,实现数据的高可用性和可扩展性。
  • 云原生数据库:基于云计算技术构建,具有容器化、微服务等特性,可以快速部署和扩展。
  • 云原生分布式数据库:结合了分布式数据库和云原生数据库的特点,实现高性能、高可用、可扩展的数据库服务。
产品名称 PolarDB-分区表 OceanBase PolarDB-X TIDB 传统分库分表
<think>嗯,用户深入询问了数据冗余方案中如何保证跨库数据一致性的问题,这确实是分布式系统中的核心挑战。从用户引用的资料来看,ta已经对MQ事务、Redis双写一致性等概念有所了解,但需要更系统的解决方案。 用户可能正在设计一个高并发的分库分表系统,遇到了冗余字段同步的痛点。考虑到ta之前关注过分片JOIN查询,这次的问题应该是延续性的架构设计思考。用户的技术水平较高,需要的是落地方案而非基础概念。 我注意到引用[3]提到"只能多做冗余保护措施",这提示我们需要分层设计一致性保障机制。在电商或金融场景中,这类问题尤为关键,比如订单商品库存表的冗余同步。 关于数据冗余一致性的保障,可以从这几个层面展开: 首先在写入端,采用事务消息机制能解决生产者消费者之间的原子性问题。比如订单创建时,通过RocketMQ的半消息确保业务数据消息的原子提交,这是引用[1][3]提到的思路。 其次在同步过程中,需要处理幂等性顺序性问题。Redis的Lua脚本实现原子操作(引用[2])可以用于去重,而Kafka的分区有序特性能保证关键字段的同步顺序。 最后是核对修复环节,引用[4]提到的Elasticsearch冗余策略其实暗含了校验思想——通过定期比对binlog消息队列的位点,自动触发补偿。金融系统常用的T+1对账就是典型实践。 特别要注意的是,用户场景中可能存在跨云数据库的情况。这时基于GTID的增量同步比双写更可靠,比如用Canal监控MySQL主库的变更,避免直接写从库导致的主从延迟问题。 对于即时性要求高的场景(如库存显示),可以采用"缓冲队列+本地缓存"的组合策略:先更新Redis并设置短时过期,同时异步刷新数据库。这样既保证读取性能,又通过后台线程保证最终落地。</think>在数据冗余方案中保证跨库数据的一致性,需结合多种技术手段分层控制。以下是核心解决方案及实践要点: --- ### 一、分层一致性保障机制 #### 1. **写入层控制** - **事务消息(MQ事务)** 通过消息队列实现**业务操作**与**冗余数据更新**的解耦: ```mermaid graph LR A[业务主库操作] --> B[发送半事务消息] B --> C[提交本地事务] C --> D[MQ投递消息] D --> E[消费端更新冗余库] ``` - **关键点**: - 生产者:采用**本地事务表**记录消息状态(如`INSERT INTO message_table`)[^1] - 消费者:需实现**幂等消费**(Redis SETNX或数据库唯一键防重) #### 2. **同步层控制** - **增量日志捕获(CDC)** 通过数据库日志(如MySQL Binlog)捕获变更: ```sql /* 示例:Canal解析Binlog */ UPDATE user SET name='new' WHERE id=123; ↓↓↓ 解析为 ↓↓↓ {"table":"user","op":"update","data":{"id":123,"name":"new"}} ``` - **优势**:避免侵入业务代码,实时性高(毫秒延迟) - **工具**:Debezium、Canal、Flink CDC - **双写策略优化** ```java // 伪代码:双写+异步校验 public void updateData(Data data) { // 1. 主库事务 transaction(() -> { primaryDB.update(data); // 2. 同步写Redis(保障读取一致性) redis.set(data.key, data.value); }); // 3. 异步写冗余库(最终一致) asyncExecutor.execute(() -> redundantDB.update(data)); // 4. 定时补偿任务 scheduleCompensationTask(data.key); } ``` #### 3. **核对修复层** - **自动对账系统** | 核对维度 | 实现方式 | 频率 | |----------------|------------------------------|----------| | 数据总量校验 | 对比主/备库count(*) | 每小时 | | 关键字段比对 | 抽样MD5(字段)校验 | 实时抽查 | | 时间窗口修复 | 按create_time修复延迟数据 | 每天 | --- ### 二、关键场景解决方案 #### 1. **高并发写场景** - **策略**:`本地缓存+批量合并` - 先将更新操作缓存到Redis队列 - 定时合并相同键的操作(如`set name=A; set name=B` → 只保留B) - 批量写入冗余库减少压力 #### 2. **金融强一致** - **方案**:`TCC(Try-Confirm-Cancel)` ```mermaid graph TB Try[Try阶段:锁定主库记录] --> Confirm{主库成功?} Confirm -->|是| Confirm[Confirm阶段:更新冗余库] Confirm -->|否| Cancel[Cancel阶段:释放锁] ``` - **代价**:性能下降30%-50%,仅用于关键业务 #### 3. **缓存与数据库一致性** - **组合拳**: ```mermaid graph LR W[写请求] --> D[先写DB] D --> P[发布Binlog] P --> C[CDC同步] C --> R[删除Redis缓存] R --> F[下次读请求回源DB] ``` 通过**延迟双删**避免并发问题: ```java redis.del(key); // 第一次删除 db.update(data); thread.sleep(500); // 等待主从同步 redis.del(key); // 第二次删除 ``` --- ### 三、架构设计原则 1. **容忍延迟分** | 数据类别 | 允许延迟 | 同步方式 | |----------------|----------|------------------| | 用户昵称 | 5分钟 | 异步队列 | | 订单状态 | 30秒 | 可靠消息 | | 账户余额 | 0秒 | 分布式事务 | 2. **冗余字段设计规范** - 仅冗余**极少变更**的字段(如用户ID、创建时间) - 禁止冗余**高频更新**字段(如计数器、状态码) 3. **自动熔断机制** - 监控冗余库延迟,超过阈值自动降为**读主库** - 异常时切换数据源,避免雪崩 --- ### 典型问题修复流程 ```mermaid graph TD A[监控告警] --> B{延迟类型} B -->|网络抖动| C[重试3次] B -->|数据冲突| D[触发对账服务] D --> E[按时间戳覆盖] E --> F[记录差异日志] F --> G[人工介入分析] ``` > ⚠️ **重要原则**: > - 优先保证**主库数据正确性**,冗余库允许暂时不一致 > - 通过`SELECT ... FOR UPDATE`避免修复时的并发写冲突[^3] --- ### 相关问题延伸 1. 如何设计高可用的数据核对系统? 2. 在微服务架构下,如何实现跨服务的分布式事务? 3. 使用CDC工具同步数据时如何避免循环复制? 4. 对于PB历史数据,如何高效实现全量一致性校验? [^1]: 事务消息通过本地事务表保障可靠性 [^2]: CDC日志捕获避免业务侵入 [^3]: 行锁机制保障修复原子性 [^4]: 最终一致性需配合自动补偿机制
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值