架构思维:构建高并发读服务_异构数据的同步一致性方案

news2025/5/9 21:55:22

文章目录

  • 一、引言
  • 二、全景架构回顾
  • 三、潜在问题
    • 问题1:Binlog 延迟——理想 vs 实际
    • 问题2:Binlog 格式解析
    • 问题3:高可靠消费
      • 1. 串行 ACK 消费
      • 2. 并行消费+乱序风险
      • 3. 解决方案
    • 问题4:缓存数据结构设计
      • 1. Key–Value 冗余
      • 2. Hash 结构局部更新
      • 3. 组合方案
  • 四、数据一致性校验与兜底
      • 1. 定期对比
      • 2. 主动写入兜底
  • 五、总结

在这里插入图片描述


一、引言

在架构思维:利用全量缓存架构构建毫秒级的读服务中,我们提出了基于 Binlog 的全量缓存读服务架构,能够满足百毫秒级平均延迟、实时性与最终一致性。

‘’但要将此方案落地,仍需攻克一系列细节难题:

  • Binlog 真正的端到端延迟有多大?
  • 如何解析和处理 Binlog 的多种格式?
  • 在高并发和快速迭代下,如何保证消费链路零丢失、零乱序?
  • 缓存中数据该如何设计,才能兼顾读写性能与业务灵活性?

接下来我们将一一拆解并给出最佳实践

二、全景架构回顾

> 占位图:图 1 — 同步架构全景图

该架构核心组件:

  1. 主库写入 → 2. Binlog 生成 → 3. 订阅中间件(Canal/Maxwell 等) → 4. 消费 & 转码 → 5. 缓存写入 → 6. 读服务调用

我们将在此全景图基础上,聚焦四大问题并给出对策。


三、潜在问题

问题1:Binlog 延迟——理想 vs 实际

MySQL 主从同步延迟通常在毫秒级,但自研 Binlog 同步引入了:

  • 协议转换:从 MySQL 协议到中间件协议,多了 CPU 与网络开销;
  • 额外组件:多了中间件与消费服务,链路更长;
  • 从库读取:为保护主库,一般从从库订阅 Binlog,增加一跳延迟;
  • 串行吞吐瓶颈:Binlog 文件串行读写限制了吞吐。

优化思路

  • 精简协议:保持中间件与 MySQL 协议兼容度,减少解析开销;
  • 链路监控:端到端打点,定位各环节耗时;
  • 并行读写(详见问题三)。

问题2:Binlog 格式解析

MySQL 支持三种格式:

  1. statement:记录 SQL 文本,体积小,但需复杂 SQL 解析,易出错。

    statement 格式是把每次执行的 SQL 语句记录到 Binlog 文件里,在主从复制时,基于 Binlog 里的 SQL 语句进行回放来完成主从复制。比如执行了如下 SQL 成功后:

    update demo_table set status='无效' where id =1
    

    Binlog 中记录的便是上述这条具体的 SQL。采用 SQL 格式的 Binlog 的好处是内容太少,传输速度快。但存在一个问题,在基于 Binlog 进行数据同步时,需要解析上述的 SQL 获取变更的字段,存在一定的开发成本。


  1. row:记录行级前后镜像及变更字段,数据量大但解析简单。
{
  "before":{
    "id":1,
    "message":"文本""status":"有效",
    "created":"xxxx-xx-xx",
    "modified":"xxxx-xx-xx"
  },
  "after":{
    "id":1,
    "message":"文本""status":"无效",
    "created":"xxxx-xx-xx",
    "modified":"xxxx-xx-xx"
  },
  "change_fields":["status"]
}
  1. mixed:自动在前两者间切换,兼顾性能与兼容。

推荐:使用 rowmixed

  • row 模式解析逻辑最简单,无需 SQL 引擎;
  • mixed 针对 DDL 保留 statement,节约空间。

问题3:高可靠消费

1. 串行 ACK 消费

> 占位图:图 2 — 串行消费流程

  • 优点:天然有序、易保证一致性;
  • 缺点:单线程瓶颈,延迟随数据量急剧上升。

2. 并行消费+乱序风险

> 占位图:图 3 — 并行消费架构

  • 利用 MQ 拆分到多消费者组,提高吞吐;

    借用了 MQ 进行拆分。在 Binlog 处仍然进行串行消费,但只是 ACK 数据。ACK 后数据直接发送到 MQ 的某一个 Topic 里即可。因为只做 ACK 并转发至 MQ,不涉及业务逻辑,所以性能消耗非常小,大概只有几毫秒或纳秒

  • 乱序会导致后写数据被覆盖。

3. 解决方案

  • 分布式锁细粒度串行:按业务维度(如订单号)加锁,串行同一键写入;
  • MQ 分区/串行通道:比如 Kafka Partition,将同一 key 的消息路由到同一分区,自然串行。

在这里插入图片描述

最终既保留高吞吐,又能保证单键顺序。

在采用了 MQ 进行纯串行转并行时,将 Binlog 发送到 MQ 可以根据情况进行调整,当数据量很大或者未来很大时,可以将 Binlog 的数据按表维度发送到不同的 Topic。一是能够实现扩展性;二是可以提升性能;三是通过不同表使用不同的 Topic,可以起到隔离的作用,减少表之间的相互影响


问题4:缓存数据结构设计

Redis 常见几种存储模式:

1. Key–Value 冗余

将多表数据合并序列化为一个大 JSON 存储,优点简单,缺点全量更新和查询开销大。


2. Hash 结构局部更新

> 占位图:图 5 — Hash 结构示例

  • 各业务实体字段映射到 Hash 的不同 field,可单字段更新;
  • 保证同一 hash slot,避免跨分片查询;

3. 组合方案

  • 反查全量覆盖:针对偶发大变更,消费端反查数据库,重建整个缓存对象;
  • 分布式锁协调:多表变更时,对同一业务 ID 加锁,串行更新 Hash。

四、数据一致性校验与兜底

1. 定期对比

> 占位图:图 6 — 校验架构

  • 选用数据库从库作比对源,定时扫描与缓存做比对;
  • 异常重试 + 告警 + 现场记录。

2. 主动写入兜底

虽然上述在提升同步吞吐量上做了非常多地设计,但不可否认延迟总是存在的,即使是纯数据库主从同步间也会因为网络抖动和写入量大的情况出现毫秒或者秒级延迟,我们这里基于 Binlog 的改良方案自然不例外。

绝大部分的业务和场景,对于毫秒或秒级延迟无感知。但为了方案的完整性和极端场景的应对,可以在异步同步的基础上,增加主动同步。方案如下图所示:
在这里插入图片描述

  • 在关键写事务提交后,异步或同步写入缓存;
  • 失败不回滚,由 Binlog 保底最终一致;

上述的架构是对一些关键场景在写完数据库后,主动将数据写入缓存中去。但对于写入缓存可能出现的失败可以不处理,因为主动写入是为了解决缓存延迟的问题,主动写入导致的丢失数据由 Binlog 保障最终一致性。此架构是一个技术互补的策略,Binlog 保证最终一致性但可能存在延迟,主动写入保障无延迟但存在丢数据。在架构中,也可以采用此思路。一个单项技术无法完美解决问题时,可以对短板寻找增量方案,而不是整个方案完全替换

此「主动 + 被动」组合,兼顾实时性与可靠性。

五、总结

  1. 延迟——链路中的每一跳都要监控与优化;
  2. 格式——row/mixed 模式下解析最简单可靠;
  3. 消费——利用 MQ 分区或锁机制保证“高吞吐+强有序”;
  4. 结构——Hash 优于 KV,可局部更新、同分片;
  5. 一致性——数据对比与主动写入互补兜底。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2371814.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

剑指大规模 AI 可观测,阿里云 Prometheus 2.0 应运而生

作者:曾庆国(悦达) Prometheus 大家应该非常熟悉,正文开始前,让我们一起来回顾开源 Prometheus 项目的发展史。Prometheus 最初由 SoundCloud 的工程师 Bjrn Rabehl 和 Julius Volz 于 2012 年开发。当时,…

游戏引擎学习第260天:在性能分析器中实现钻取功能

昨天那个帧内存满之后触发段错误实在没找到什么原因导致的 继续研究一下为什么导致的 内存不够进来释放frame 释放frame 应该会给DebugState->FirstFreeStoredEvent 赋值吧 这段宏定义: #define FREELIST_DEALLOCATE(Pointer, FreeListPointer) \if(Pointer) {…

【自然语言处理与大模型】使用Xtuner进行QLoRA微调实操

本文首先对Xtuner这一微调框架进行简单的介绍。手把手演示如何使用Xtuner对模型进行微调训练,包括数据准备、训练命令执行及训练过程中的监控技巧。最后,在完成微调之后,本文还将介绍如何对微调结果进行简单对话测试。 一、Xtuner微调框架 X…

扣子创建一个应用

什么是扣子应用 扣子应用可以让你相对轻松的搭建一个具备AI功能的应用,它区别智能体,在于智能体的ui和交互相对固定,主要是以对话框聊天的方式进行交互,而扣子应用则可以让ui交互表现更加丰富。 实践一个生成图片的应用 这里我…

SpringBoot教程(vuepress版)

Spring Boot 教程 项目介绍 这是一个系统化的 Spring Boot 学习教程,采用循序渐进的方式,帮助开发者从零开始掌握 Spring Boot 开发。 教程特点 系统化的知识结构实用的代码示例完整的实战案例丰富的练习作业 目录结构 基础入门 Spring Boot 简介…

FiLo++的框架图介绍

FiLo框架图模块详解 1. 文本生成模块 Normal Texts 功能:生成正常样本的文本描述。输入:固定模板(如 A [domain] photo of [state][cls])和可学习模板(如 [v1][v2]...[vm][state][cls])。输出:融…

C++--入门基础

C入门基础 1. C的第一个程序 C继承C语言许多大多数的语法,所以以C语言实现的hello world也可以运行,C中需要把文件定义为.cpp,vs编译器看是.cpp就会调用C编译器编译,linux下要用g编译,不再是gcc。 // test.cpp #inc…

准确---Typora配置Gitee图床并实现自动图片上传

下载地址:https://github.com/Molunerfinn/picgo/releases 安装就直接下一步,下一步就行 安装完以后然后回到Typora上偏好设置指定一下路径 默认是 C:\Program Files\PicGo\PicGo.exe 并且还需要选择规则 接下来就需要去PicGo上面配置了 配置之前需要去…

Day111 | 灵神 | 二叉树 | 验证二叉搜索树

Day111 | 灵神 | 二叉树 | 验证二叉搜索树 98.验证二叉搜索树 98. 验证二叉搜索树 - 力扣(LeetCode) 方法一:前序遍历 递归函数传入合法的左右边界,只有当前结点是合法的边界,才是二叉搜索树,否则就返回…

Redis 8.0 正式版发布,新特性很强!

就在前两天,Redis 8.0 正式版 (GA) 来了!这并不是一次简单的更新,Redis 8.0 不仅带来了性能上的进一步提升,还带来一些实用的新特性与功能增强。并且,最重要的是拥抱 AGPLv3 重归开源! 下面,简单…

以太坊智能合约开发框架:Hardhat v2 核心功能从入门到基础教程

一、设置项目 Hardhat 项目是安装了 hardhat 包并包含 hardhat.config.js 文件的 Node.js 项目。 操作步骤: ①初始化 npm npm init -y②安装 Hardhat npm install --save-dev hardhat③创建 Hardhat 项目 npx hardhat init如果选择 Create an empty hardhat.…

了解Dockerfile

定制docker 镜像的方式: 手动修改容器内容,导出新的镜像基于dockerfile 自行编写指令,基于指令流程创建镜像 镜像和容器的层级实现 docker拉取镜像到docker engine 之后,共享系统内核。 在内核层上有镜像层(本质上只…

强化学习--2.数学

强化学习--数学 1、概率统计知识1.1 随机变量与观测值1.2 概率密度函数(PDF)1.3 期望1.4 随机抽样 2、数据期望E3、正态分布4、条件概率1. **与多个条件相关**(依赖所有前置条件)2. **仅与上一个条件相关**(马尔可夫性…

边缘计算:开启智能新时代的“秘密武器”

大家好,我是沛哥儿,我们又见面了。今天我们来简单说下什么是边缘计算,它怎么工作的,有哪些优势。有哪些具体的应用场景。 文章目录 1、边缘计算是什么?2、边缘计算如何工作?3、边缘计算有哪些优势&#xff…

# 如何使用 PyQt5 创建一个简单的警报器控制界面

如何使用 PyQt5 创建一个简单的警报器控制界面 引言 在现代自动化和监控系统中,警报器扮演着至关重要的角色。它们可以提醒我们注意潜在的危险或紧急情况。在这篇文章中,我将向您展示如何使用Python的PyQt5库创建一个简单的警报器控制界面。这个界面将…

MySQL报错解决过程

我在调试datagrip的时候,显示拒绝连接,开始的时候,我以为只是服务没有开启,结果到后来在网上搜索各种解决办法无果后,就选择卸载,卸载之后安装新的MySQL 以下就是我的解决过程。 如果只是在使用外置软件&…

【AI入门】CherryStudio入门5:创建知识库,对接Obsidian 笔记

前言 来吧,继续CherryStudio的实践,前边给Cherry Studio添加知识库,对接思源笔记,但美中不足,思源笔记得导出再导入知识库,本文看一下obsidian笔记,笔记内容直接被知识库使用,免去导…

Redis 8.0正式发布,再次开源为哪般?

Redis 8.0 已经于 2025 年 5 月 1 日正式发布,除了一些新功能和性能改进之外,一个非常重要的改变就是新增了开源的 AGPLv3 协议支持,再次回归开源社区。 为什么说再次呢?这个需要从 2024 年 3 月份 Redis 7.4 说起,因为…

【Redis】Redis常用命令

4.Redis常见命令 4.1 Redis数据结构介绍 Redis是一个key-value的数据库,key一般是String类型,不过value的类型多种多样: 命令太多,不需要死记,学会查询就好了~ Redis为了方便我们学习,将操作不同数据类型…

贪心算法应用:最小反馈顶点集问题详解

贪心算法应用:最小反馈顶点集问题详解 1. 问题定义与背景 1.1 反馈顶点集定义 反馈顶点集(Feedback Vertex Set, FVS)是指在一个有向图中,删除该集合中的所有顶点后,图中将不再存在任何有向环。换句话说,反馈顶点集是破坏图中所…